【问题标题】:How to use EXECUTE IMMEDIATE to populate temp table in Oracle如何使用 EXECUTE IMMEDIATE 在 Oracle 中填充临时表
【发布时间】:2017-06-15 13:14:20
【问题描述】:

我有许多可能的查询可以执行所有这些都将返回两列。在调用过程之前不知道实际运行的查询。在将这些查询中返回的数据放入另一个已知表之前,我需要对它们进行操作。

所以我创建了一个表类型来存储这两条记录。我获取查询,使用 EXECUTE IMMEDIATE,并尝试使用批量收集。像这样:

create or replace TYPE TEMP_RECORD IS object (
   Identifier VARCHAR2(5000), 
   Message varchar2(5000)
  );
  /
create or replace TYPE THETEMP_TABLE IS TABLE OF TEMP_RECORD;

DECLARE
  ID NUMBER(38);
  runID NUMBER(38);
  sqlToRun varchar(5000);
  tempTable THETEMP_TABLE;
  CURSOR myCursor IS 
  select ID, SQL FROM QueryTables  
  where IsActive = 1; 

BEGIN

    OPEN myCursor;
    LOOP
    FETCH myCursor INTO id,sqlToRun;

        EXIT WHEN myCursor%notfound; 

        INSERT INTO Run(RunID,StartDateTime)
        VALUES (id,(select sysdate from dual))
        RETURNING ID INTO runID;

       -- dbms_output.PUT_LINE(runID);
        EXECUTE IMMEDIATE sqlToRun BULK COLLECT INTO tempTable;

        INSERT INTO RunResults(RunDate,RunID,SourceID,ResultDescription)
        SELECT (select sysdate from dual),runID, Identifier, Message FROM tempTable;


    END LOOP; 
    CLOSE myCursor ;

END;

问题出在: EXECUTE IMMEDIATE sqlToRun BULK COLLECT INTO tempTable;

我收到此错误:

ORA-00932: inconsistent datatypes: expected - got -
ORA-06512: at line 23
00932. 00000 -  "inconsistent datatypes: expected %s got %s"

我相信数据类型是正确的。我猜这是一个错误,我正在尝试这样做。

编辑:这些动态查询之一的示例。

SELECT c.CustomerIdentifier as SourceIdentifier,'Invalid Customer Type record' as InvalidFields
FROM Customer c
WHERE 
c.CustomerType <> 'a' and c.CustomerType <> 'b' and c.CustomerType <> 'b'

那么:如何从返回已知数量的相同数据类型的列的动态查询中填充临时表?

【问题讨论】:

  • 请分享sqlToRun的例子。似乎问题出在sql查询本身ORA-06512: at line 25,但EXEC IMMEDIATE在脚本的第23行。
  • 感谢@disiaq - 我添加了一个示例,尽管行不同的原因是因为我为 Stack Overflow 进行了格式更改。我已对其进行更正以确认错误是在 EXECUTE IMMEDIATE 行上引发的。
  • 我不会这样做;相反,我会将其作为立即执行的一部分进行插入 - 例如:execute immediate 'insert into runresults (...) select sysdate, :runid, t.* from (' || sqltorun ||') t' using runid;

标签: plsql


【解决方案1】:

问题是因为您不能直接从集合中选择 - 您必须先将其转换为表格。例如:

SELECT sysdate ,runID, Identifier, Message FROM table(tempTable as THETEMP_TABLE);

但是,与其运行 select 语句,将结果提取到集合中,然后使用集合将行插入表中,为什么不简单地执行 insert-as-select 呢?这将节省内存(您不再临时将结果提取到变量中)并且更快更高效。

例如类似:

execute immediate 'insert into runresults (...) select sysdate, :runid, t.* from (' || sqltorun ||') t' using runid;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-10
    • 2021-04-11
    相关资源
    最近更新 更多