Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you convert LONG data to TIMESTAMP or VARCHAR2?

I need something like:

SELECT PARTITION_NAME,
       to_char(LONG_TO_TIMESTAMP(HIGH_VALUE), 'MM/DD/YYYY HH24:MI:SS') AS HIGH_VAL
  FROM USER_TAB_PARTITIONS
 WHERE TABLE_NAME = 'TABLE_NAME'

Output should look something like this:

PARTITION_NAME         HIGH_VAL
----------------   --------------------
SOME_NAME          01/01/2010 00:00:00

When I run:

SELECT PARTITION_NAME, HIGH_VALUE FROM USER_TAB_PARTITIONS

It looks like:

PARTITION_NAME         HIGH_VAL
----------------   --------------------
SOME_NAME          TIMESTAMP' 2010-01-01 00:00:00'

If I use UTL_RAW.CAST_TO_VARCHAR2(HIGH_VALUE),
I end up getting an ORA-00997: illegal use of LONG datatype error.

If I use ''||HIGH_VALUE or to_clob(HIGH_VALUE) or to_char(HIGH_VALUE),
I get an ORA-00932: inconsistent datatypes: expected [DATA_TYPE] got LONG error

My working function thanks to shobi:

CREATE OR REPLACE FUNCTION GET_HIGH_VALUE_AS_DATE (
    p_TableName     IN VARCHAR2,
    p_PatitionName  IN VARCHAR2
) RETURN DATE
IS
   v_LongVal LONG;
BEGIN
    SELECT HIGH_VALUE INTO v_LongVal
      FROM USER_TAB_PARTITIONS
     WHERE TABLE_NAME = p_TableName
       AND PARTITION_NAME = p_PatitionName;

    RETURN TO_DATE(substr(v_LongVal, 11, 19), 'YYYY-MM-DD HH24:MI:SS');
END GET_HIGH_VALUE_AS_DATE;

SQL Looks like

SELECT PARTITION_NAME, GET_HIGH_VALUE_AS_DATE(TABLE_NAME, PARTITION_NAME)
  FROM USER_TAB_PARTITIONS
 WHERE TABLE_NAME LIKE 'TABLE_NAME'
   AND ROWNUM < 2;
like image 291
ScrappyDev Avatar asked Mar 10 '12 04:03

ScrappyDev


People also ask

Can we convert date to TIMESTAMP in Oracle?

Oracle has expanded on the DATE datatype and has given us the TIMESTAMP datatype which stores all the information that the DATE datatype stores, but also includes fractional seconds. If you want to convert a DATE datatype to a TIMESTAMP datatype format, just use the CAST function.

What is the length of VARCHAR2?

The maximum length for VARCHAR2 is 32672 BYTE or 8168 CHAR which is the same as the maximum length for VARCHAR of 32672 OCTETS or 8168 CODEUNITS32. Similarly, when the NVARCHAR2 data type is explicitly encountered in SQL statements, it is implicitly mapped following the same rules as the NVARCHAR data type.

How do you convert a number into a TIMESTAMP?

To convert a NUMBER to a TIMESTAMP you can use an expression like TO_TIMESTAMP(TO_CHAR(...)) . To compute the number of seconds between two timestamps, one solution is to cast both to dates, and substract them : you will get a (decimal) result in days, which can be then converted to seconds.

Can we change data type from number to VARCHAR2 in Oracle?

TO_CHAR (number) converts n to a value of VARCHAR2 datatype, using the optional number format fmt . The value n can be of type NUMBER , BINARY_FLOAT , or BINARY_DOUBLE . If you omit fmt , then n is converted to a VARCHAR2 value exactly long enough to hold its significant digits.


2 Answers

The only way to convert LONG columns is in PL/SQL. Look at the following example, which determines the length of the LONG field:

SET SERVEROUTPUT ON SIZE 10000;  
DECLARE
long_var LONG;
BEGIN
SELECT text_column INTO long_var
FROM table_with_long
WHERE rownum < 2;
DBMS_OUTPUT.PUT_LINE('The length is '||LENGTH(long_var));
END;

Basically, you define a variable as the LONG type, then SELECT the column INTO the variable. Finally, it is output to the user. SET SERVEROUTPUT ON SIZE 10000 allows spooling from the PUT_LINE to go to the screen.

You can use a similar method to select the LONG into a varchar field. The following example puts the first 2000 characters into TABLE_B, which for our purposes has one column, TEXT_FIELD:

DECLARE
   long_var LONG;
   var_var  VARCHAR2(2000);
   BEGIN
   SELECT text_column INTO long_var
   FROM table_with_long
   WHERE rownum < 2;
   var_var := substr(long_var,1,2000);
   INSERT INTO table_b
   VALUES (var_var);
   END;
like image 108
shofee Avatar answered Nov 12 '22 01:11

shofee


There's a good trick to do this using dynamic sql ( EXECUTE IMMEDIATE )

SET SERVEROUTPUT ON
DECLARE
     l_date   DATE;
BEGIN
     FOR r IN (
          SELECT partition_name,high_value
            FROM user_tab_partitions
          WHERE table_name = 'MYTABLE'
     ) LOOP
          EXECUTE IMMEDIATE 'BEGIN :v := ' || r.high_value || '; END;' 
             USING  OUT l_date;
          DBMS_OUTPUT.PUT_LINE(r.partition_name||','|| l_date);
     END LOOP;
END;
/

This produces an output of the form

SYS_P601452,19-10-18  --(partition_name,high_value)
SYS_P601451,18-10-18
SYS_P601453,20-10-18
SYS_P601454,21-10-18
SYS_P601455,22-10-18
..
..

Here I used a DATE type partitioned column. You may use a TIMESTAMP variable.

like image 28
Kaushik Nayak Avatar answered Nov 12 '22 01:11

Kaushik Nayak