如何在Oracle中存储和填充Execute Immediate返回的数据?

如何在Oracle中存储和填充Execute Immediate返回的数据?,oracle,plsql,execute-immediate,Oracle,Plsql,Execute Immediate,在我的项目中,我正在尝试执行以下查询: DECLARE Sid nvarchar2(30) := ''; /*Here the values will come from some other variable>*/ Bid nvarchar2(30) := ''; /*Here the values will come from some other variable>*/ ExecuteDSQL varchar2(1000); ExecuteDSQLResult

在我的项目中,我正在尝试执行以下查询:

DECLARE
  Sid nvarchar2(30) := ''; /*Here the values will come from some other variable>*/
  Bid nvarchar2(30) := ''; /*Here the values will come from some other variable>*/
  ExecuteDSQL varchar2(1000);
  ExecuteDSQLResult varchar2(10000);
BEGIN

  IF Sid IS NULL THEN Sid := '1' ; ELSE Sid := '4' ; END IF;
  IF Bid IS NULL THEN Bid := '1' ; ELSE Bid := '5' ; END IF;

  ExecuteDSQL := '  SELECT * FROM iftlog WHERE serverid='''|| Sid
                 || ''' AND bpid=''' || Bid  || '''  ';

  EXECUTE IMMEDIATE ExecuteDSQL INTO ExecuteDSQLResult;

  DBMS_OUTPUT.PUT_LINE(ExecuteDSQLResult);

END;
/

查询导致了不一致数据类型的错误,除此之外,问题是我们能否像MS-SQL那样将结果存储到临时表中?我是oracle数据库的新手。我需要临时表来存储1到20之间的记录,我将使用Row_Number()并在我的项目中相应地修改查询。

Oracle
中,您可以使用

  • 对象类型/表类型
  • 动态光标
  • 使用对象类型/表类型

    CREATE TYPE obj_typ AS OBJECT ( 
       id          number,
       name        VARCHAR2(20)
    );
    /
    
    CREATE TYPE tab_typ AS table of  obj_typ;
    /
    
    declare
        v_type  tab_typ :tab_typ();
        .....
    begin
        .....
        execute immediate 'select obj_typ(id, name) from tbl' into v_type;
        .....
    end;
    
    现在您可以使用
    v_type
    作为
    temp table

    类型的一个限制是在使用它们之前必须在模式中创建它

    使用动态光标

    sql_stmt := 'SELECT * FROM emp WHERE job = :j';
    OPEN emp_cv FOR sql_stmt USING my_job;
    

    限制您必须循环通过
    光标
    以打赌数据不如
    临时表
    灵活SQL Server临时表的Oracle等价物是PL/SQL集合。我们可以使用
    %rowtype
    语法定义与表的投影匹配的本地类型。我们可以使用该类型将局部变量声明为选择的目标

    遗憾的是,没有方便的机制来打印记录:您需要在DBMS_OUTPUT.PUT_LINE()调用中指定每个单独的列

    以下是用idomatic PL/SQL重新编写的代码:

    DECLARE 
    
        Sid nvarchar2(30) := '';/*Here the values will come from some other variable>*/
        Bid nvarchar2(30) := '';/*Here the values will come from some other variable>*/
    
        ExecuteDSQL varchar2(1000) := 'SELECT * FROM iftlog WHERE serverid= :1 AND bpid= :2';
        type iftlog_nt is table of  iftlog%rowtype;
    
        ExecuteDSQLResult iftlog_nt;
    
    BEGIN
    
        IF Sid IS NULL THEN Sid := '1' ; ELSE Sid := '4' ; END IF;
        IF Bid IS NULL THEN Bid := '1' ; ELSE Bid := '5' ; END IF;
    
        EXECUTE IMMEDIATE ExecuteDSQL 
            bulk collect into ExecuteDSQLResult
            using sid and bid;
    
        -- loop through all records in PL/SQL table
        for idx in 1..ExecuteDSQLResult.count()
        loop
            DBMS_OUTPUT.PUT_LINE(ExecuteDSQLResult(idx).some_col||'::'||ExecuteDSQLResult(idx).some_other_col);
        end loop;
    
    END;
    /
    
    当然,像这样重新编写代码显然根本不需要动态SQL。因此,我们可以用一个简单的选择来替换executeimmediate调用:

    SELECT * 
    bulk collect into ExecuteDSQLResult 
    FROM iftlog 
    WHERE serverid= sid 
    AND bpid= bid;
    
    你也可以使用

    插入的数据在会话的整个过程中都是可用的(在提交保存时),可以使用SQL进行访问

    select * from tmp;
    

    另请参见本-谢谢。剪切粘贴错误加上不测试代码:)@APC谢谢你的回答,但它会显示所有记录吗?我的意思是,如果有多条记录要返回?@MaximusDecimusMeridius-是的,循环将逐步通过填充集合中的每一行。你应该清楚,尽管你可以使用GTT。。在这种情况下,你不应该
     create global temporary table tmp  
     (serverid varchar2(10),
      bpid varchar2(10),
      txt varchar2(100)
      )
     ON COMMIT PRESERVE ROWS  
     ;
    
     DECLARE 
    
     Sid varchar2(30) := '1'; 
     Bid varchar2(30) := '1'; 
     ExecuteDSQL varchar2(1000);
    
     BEGIN
    
     ExecuteDSQL := 'insert into  tmp  
     SELECT serverid,bpid,txt FROM iftlog WHERE serverid=:Sid  AND bpid=:Bid';
    
     EXECUTE IMMEDIATE ExecuteDSQL  using sid, bid;
     commit;
     END;
     /
    
    select * from tmp;