【问题标题】:EXECUTE IMMEDIATE results into Table Type立即执行结果到表类型
【发布时间】:2019-10-23 12:49:48
【问题描述】:

我需要让 EXECUTE IMMEDIATE 将其结果返回到表类型(AS TABLE OF)

如果立即执行返回单个值,我可以使用“INTO somevariable”保存结果

但是,我的立即执行将返回一个多列的表,并且没有多少谷歌搜索可以帮助我弄清楚!

首先我创建类型

CREATE OR REPLACE TYPE T_VALIDITY_RECORD AS OBJECT (
   TIME_COL  DATE,
   VALUE_COL NUMBER
);
/

CREATE OR REPLACE TYPE T_VALIDITY_TABLE AS TABLE OF T_VALIDITY_RECORD;
/

然后我尝试代码

DECLARE
   RET_TABLE   T_VALIDITY_TABLE;
BEGIN

EXECUTE IMMEDIATE 'SELECT my_date,
                          my_numbers  
                   FROM   my_table
                   WHERE  somthing = somthingelse' INTO RET_TABLE;
END;

这只是一个非常简化的例子,真正的代码会做(会做其他事情)

我尝试了各种方法,例如 BULK COLLECT INTO 等,但似乎无法正常工作。

我收到以下错误:

错误报告
ORA-00932:不一致的数据类型:预期 - 得到 -
ORA-06512:在第 5 行
00932. 00000 - “不一致的数据类型:预期的 %s 得到了 %s”
*原因:
*行动:

【问题讨论】:

    标签: oracle plsql


    【解决方案1】:

    您需要BULK COLLECT INTO,并且需要收集T_VALIDITY_OBJECT 的实例,而不是NUMBERDATE 值对。

    Oracle 设置

    CREATE OR REPLACE TYPE T_VALIDITY_RECORD AS OBJECT (
       VALUE_COL NUMBER,
       TIME_COL  DATE
    );
    /
    
    CREATE OR REPLACE TYPE T_VALIDITY_TABLE AS TABLE OF T_VALIDITY_RECORD;
    /
    
    CREATE TABLE my_table ( my_date, my_number, something ) AS
    SELECT 1, DATE '2019-01-01', 1 FROM DUAL UNION ALL
    SELECT 2, DATE '2019-01-02', 1 FROM DUAL UNION ALL
    SELECT 3, DATE '2019-01-03', 1 FROM DUAL;
    

    PL/SQL

    DECLARE
      RET_TABLE   T_VALIDITY_TABLE;
    BEGIN
      EXECUTE IMMEDIATE 'SELECT T_VALIDITY_RECORD( my_date, my_number )
                         FROM   my_table
                         WHERE  something = :value'
        BULK COLLECT INTO RET_TABLE
        USING 1;
    
      FOR i IN 1 .. RET_TABLE.COUNT LOOP
        DBMS_OUTPUT.PUT_LINE( i || ': ' || ret_table(i).time_col || ', ' || ret_table(i).value_col );
      END LOOP;
    END;
    /
    

    输出

    1: 2019-01-01 00:00:00, 1 2: 2019-01-02 00:00:00, 2 3: 2019-01-03 00:00:00, 3

    db小提琴here

    【讨论】:

      【解决方案2】:

      一些问题:

      您将两列提取到一个结构中,该结构只有一个元素,由两个值组成。

      另外,如果您的选择可以提供多于一行,则需要BULK COLLECT

      如果您在这里不需要严格的动态 sql,则可以使用纯 SQL 查询:

      DECLARE
         RET_TABLE   T_VALIDITY_TABLE;
      BEGIN    
          SELECT T_VALIDITY_RECORD(my_date, my_numbers  )
                bulk collect INTO RET_TABLE
         FROM   my_table ;
      END;
      

      如果因为其他原因需要动态sql:

      DECLARE
         RET_TABLE   T_VALIDITY_TABLE;
      BEGIN
          execute immediate ' SELECT T_VALIDITY_RECORD(my_date,
                                    my_numbers  )
                              FROM   my_table'   
                bulk collect INTO RET_TABLE;                   
      END;
      

      【讨论】:

      • 谢谢,但我上面的例子被简化了,我需要使用立即执行(因为我正在动态创建 SQL 部分)有没有办法使用立即执行来实现?
      猜你喜欢
      • 2021-09-13
      • 1970-01-01
      • 1970-01-01
      • 2018-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-13
      相关资源
      最近更新 更多