oracle 中execute immediate作用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了oracle 中execute immediate作用相关的知识,希望对你有一定的参考价值。

oracle存储过程中,有什么作用

简单来说 就是你一个存储过程当中 创建了一个表 table_a 然后要用insert into将其他的数据插入到这个table_a当中,但是因为你在创建过程的时候 table_a还不存在,过程就会显示有编译错误,因为table_a不存在必然导致过程无法执行,所以无法编译成功,而把insert into语句加如到 execute immediate之后 则oracle不会再去理会这个对象是否存在,因此可以成功编译和执行。 参考技术A 执行动态SQL语句,举例str := ‘select * from test’;execute immediate str;多用于拼接的SQL,其它情况我暂时没遇到过 参考技术B execute immediate ‘SQL 语句’
动态执行SQL语句字符串

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

【中文标题】如何在 Oracle 中存储和填充 Execute Immediate 返回的数据?【英文标题】:How to store and populate data returned by Execute Immediate in Oracle? 【发布时间】:2015-08-09 10:44:38 【问题描述】:

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

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() 并在我的项目中相应地修改查询。

【问题讨论】:

【参考方案1】:

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。所以我们可以用一个简单的选择替换 EXECUTE IMMEDIATE 调用:

SELECT * 
bulk collect into ExecuteDSQLResult 
FROM iftlog 
WHERE serverid= sid 
AND bpid= bid;

【讨论】:

@Ben - 谢谢。 Cut'n'paste 错误加上不测试代码:) @APC 感谢您的回答,但它会显示所有记录吗,我的意思是如果有多个记录要返回? @MaximusDecimusMeridius - 是的,循环将遍历填充集合中的每一行【参考方案2】:

Oracle你可以使用

    Object type/table type 或 动态光标

使用对象类型/表格类型

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 喜欢,

select id from table(v_type);

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

使用动态光标

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

限制你必须循环通过cursor 来打赌数据不如temp table 灵活

【讨论】:

【参考方案3】:

你也可以使用global temporary table

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

插入的数据在整个会话期间都可用(提交保留),并且可以使用 SQL 访问

select * from tmp;

另见GTT on SO

【讨论】:

您应该明确表示您可以使用 GTT.. 在这种情况下您不应该

以上是关于oracle 中execute immediate作用的主要内容,如果未能解决你的问题,请参考以下文章

oracle 中execute immediate作用

ORACLE EXECUTE IMMEDIATE 小结

在 Oracle 中使用 Execute Immediate 将数据插入表中

执行 `EXECUTE IMMEDIATE` Oracle 语句出现错误

mariadb 10.2.3支持oracle execute immediate语法

Oracle 的 EXECUTE IMMEDIATE 与存储过程中的 LIKE 子句