2

该列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;
4

3 回答 3

4

如果您使用的是 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

相关:Oracle Database 12c 第 1 版 (12.1) 中的 WITH 子句增强

于 2019-06-26T11:03:03.643 回答
2

对于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;
/

正如@APC 评论的那样,还有一个使用 Pure SQL 的解决方案,它使用了一个稍微复杂的 Xml 表达式。

于 2019-06-26T11:18:01.317 回答
1

APC 评论中的纯 SQL 解决方案与Oracle 12 中的增强功能相结合,以允许在子句中声明函数以及Kaushik Nayak用于将字符串值转换为日期的方法,然后您可以得到:WITHEXECUTE IMMEDIATE

Oracle 设置 - 测试表和数据

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;

输出

表所有者 | 表名 | PARTITION_NAME | 高值 | NUM_ROWS
:------------ | :--------- | :------------- | :----------------- | --------:
到 | 田纳西州 | PN | 2019-06-26 12:34:56 | 12345

db<>在这里摆弄


更新:如果你想聚合一些列,那么:

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;

db<>在这里摆弄

于 2019-06-26T12:03:54.550 回答