Конвертировать формат LONG в DATE без функции - PullRequest
2 голосов
/ 26 июня 2019

Столбец HIGH_VALUE содержит данные, аналогичные приведенным ниже, типа LONG и всегда имеет одинаковую длину:

TIMESTAMP' 2019-01-30 00:00:00'

Как я могу преобразовать его в DATE тип без использования функции?

Моя общая цель - создать набор результатов, который затем можно будет использовать в качестве внутреннего запроса для других агрегатов. Например, я хотел бы иметь возможность суммировать количество строк за год в соответствии с датой, полученной путем преобразования столбца HIGH_VALUE в дату.

У меня есть только разрешения на чтение для этой базы данных, и поэтому я не могу создавать функции. Я видел другие решения на StackOverflow и других сайтах, но все они требуют создания функции.

ALL_TAB_PARTITIONS - это стандартная встроенная таблица Oracle, и поэтому я не включаю структуру таблицы. В случае, если это проблема, пожалуйста, дайте мне знать, и я создам пример таблицы.

Ниже приведен пример запроса и одна строка данных, полученная в результате этого запроса. Обратите внимание, что я не могу создавать таблицы в этой базе данных, поэтому мне также понадобится метод, который работает без создания временной таблицы.

Insert into EXPORT_TABLE (TABLE_OWNER,TABLE_NAME,PARTITION_NAME,HIGH_VALUE,NUM_ROWS) 
VALUES ('TO','TN','SYS_P201709','TIMESTAMP'' 2019-01-30 00:00:00''',5053133);

SELECT TABLE_OWNER, TABLE_NAME, PARTITION_NAME, HIGH_VALUE, NUM_ROWS
from ALL_TAB_PARTITIONS;

Ответы [ 3 ]

4 голосов
/ 26 июня 2019

Если вы используете Oracle 12c, вы все равно можете использовать функцию, но определенную встроенную:

WITH FUNCTION with_function(p_id IN NUMBER) RETURN NUMBER IS
BEGIN
    -- logic here
    RETURN p_id;
END;
SELECT with_function(id)
FROM   your_table

Связанный: Улучшения предложения WITH в Oracle Database 12c Release 1 (12.1)

2 голосов
/ 26 июня 2019

Для преобразования типа LONG (HIGH_VALUE) в TIMESTAMP, один вариант - использовать динамический sql и выполнить вставку через анонимный блок.Процедура или функция не требуются.

DECLARE
     tstamp TIMESTAMP;
BEGIN
     FOR rec IN ( SELECT table_owner,table_name,partition_name,high_value,num_rows
                  FROM all_tab_partitions
                  WHERE ROWNUM < 5
                ) LOOP
          EXECUTE IMMEDIATE 'BEGIN :dt := '
                            || rec.high_value
                            || '; END;'
             USING OUT tstamp;  --assign the long to an external timestamp variable
     INSERT INTO export_table (
               table_owner,table_name,partition_name,high_value,num_rows
          ) VALUES (rec.table_owner, 
            rec.table_name, rec.partition_name, tstamp, rec.num_rows
          );

     END LOOP;
END;
/

AS @APC прокомментировал. Существует также решение , использующее Pure SQL , в котором используется слегка сложное выражение Xml.

1 голос
/ 26 июня 2019

Сочетание решения чистого SQL из комментария APC с улучшениями в Oracle 12, позволяющими объявлять функции в предложениях WITH и метод использования Каушика Наяка EXECUTE IMMEDIATE чтобы преобразовать строковое значение в дату , тогда вы можете получить это:

Oracle Setup - Тестовая таблица и данные :

CREATE TABLE EXPORT_TABLE (
  TABLE_OWNER     VARCHAR2(30),
  TABLE_NAME      VARCHAR2(30),
  PARTITION_NAME  VARCHAR2(30),
  HIGH_VALUE      LONG,
  NUM_ROWS        INTEGER
); 

INSERT INTO EXPORT_TABLE VALUES ( 'TO', 'TN', 'PN', 'TIMESTAMP ''2019-06-26 12:34:56''', 12345 );

Запрос

WITH FUNCTION clobToDate( value IN CLOB ) RETURN DATE
  IS
    ts DATE;
  BEGIN
    EXECUTE IMMEDIATE 'BEGIN :ts := ' || value || '; END;' USING OUT ts;
    RETURN ts;
  END;
SELECT TABLE_OWNER,
       TABLE_NAME,
       PARTITION_NAME,
       clobToDate(
         EXTRACTVALUE(
           dbms_xmlgen.getxmltype(
             'SELECT high_value'
             || ' FROM  EXPORT_TABLE'
             || ' WHERE TABLE_OWNER    = ''' || t.table_owner || ''''
             || ' AND   TABLE_NAME     = ''' || t.table_name || ''''
             || ' AND   PARTITION_NAME = ''' || t.partition_name || ''''
           ),
           '//text()'
         )
       ) AS HIGH_VALUE,
       NUM_ROWS
FROM   EXPORT_TABLE t;

выход

TABLE_OWNER | TABLE_NAME | PARTITION_NAME | HIGH_VALUE          | NUM_ROWS
:---------- | :--------- | :------------- | :------------------ | -------:
TO          | TN         | PN             | 2019-06-26 12:34:56 |    12345

дБ <> скрипка здесь


Обновление : Если вы хотите объединить некоторые столбцы, то:

WITH FUNCTION clobToDate( value IN CLOB ) RETURN DATE
  IS
    ts DATE;
  BEGIN
    EXECUTE IMMEDIATE 'BEGIN :ts := ' || value || '; END;' USING OUT ts;
    RETURN ts;
  END;
SELECT table_owner,
       table_name,
       MAX( high_value ) AS max_high_value,
       SUM( num_rows ) AS total_rows
FROM   (
  SELECT TABLE_OWNER,
         TABLE_NAME,
         PARTITION_NAME,
         clobToDate(
           EXTRACTVALUE(
             dbms_xmlgen.getxmltype(
               'SELECT high_value'
               || ' FROM  EXPORT_TABLE'
               || ' WHERE TABLE_OWNER    = ''' || t.table_owner || ''''
               || ' AND   TABLE_NAME     = ''' || t.table_name || ''''
               || ' AND   PARTITION_NAME = ''' || t.partition_name || ''''
             ),
             '//text()'
           )
         ) AS HIGH_VALUE,
         NUM_ROWS
  FROM   EXPORT_TABLE t
)
GROUP BY table_owner, table_name;

дБ <> скрипка здесь

...