存储过程EXECUTE IMMEDIATE V_SQL执行很慢或出不来,如果把V_SQL语句拿出来单独执行很快,这是为啥?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了存储过程EXECUTE IMMEDIATE V_SQL执行很慢或出不来,如果把V_SQL语句拿出来单独执行很快,这是为啥?相关的知识,希望对你有一定的参考价值。

存储过程EXECUTE IMMEDIATE V_SQL执行很慢或出不来,如果把V_SQL语句拿出来单独执行很快,这是为什么?高手帮忙看下,谢谢

参考技术A 这个可能的原因有很多;
首先,execute immediate v_sql语句需要硬解析,这是一个较为耗时的过程,而直接拿出来执行的语句,其查询分析树已经存在,所以只需要软解析。
另外,execute immediate语句由于是硬解析,所以每次出来的计划都有可能不同,这是最需要注意的,可以为两种执行方法设置10046跟踪,看一下每种方法的耗时点,以及执行计划的异同。

以下配置可以在plsql developer的命令窗口中执行,也可以在sqlplus中执行;

sql> alter session set events '10046 trace name context forever,level 8';
sql > execute immediate v_sql;
sql> v_sql;

sql> alter session set events '10046 trace name context off';

完成上述操作后登录到数据库服务器上,在cmd(windows)或者 shell(unix)环境下执行
$ tkprof tracefile.trc tracefile.txt sys=no

从存储过程调用时,PL SQL Execute Immediate 不起作用

【中文标题】从存储过程调用时,PL SQL Execute Immediate 不起作用【英文标题】:PL SQL Execute Immediate not working when calling it from a stored procedure 【发布时间】:2020-07-15 20:12:48 【问题描述】:

我已经创建了以下 SP

create or replace PROCEDURE RM_SUPPORT_SCRIPTS_V2 
(
              V_TABLENAME IN USER_TABLES.table_name%type
            , V_SETCOLNAME IN NVARCHAR2 
            , V_SETVALUE IN NVARCHAR2 
            , V_WHERECOLNAME IN NVARCHAR2 
            , V_WHEREKEYVALUE IN NVARCHAR2 
            , USER_ID IN NVARCHAR2 
    ) 
    IS 
    BEGIN
      EXECUTE IMMEDIATE 
        'UPDATE '||DBMS_ASSERT.simple_sql_name(V_TABLENAME) 
            ||' SET :1 = :2, update_by_userid = :3, UPDATE_DATE = SYSDATE'
            ||' WHERE :4 = :5 '
            using V_SETCOLNAME, V_SETVALUE, USER_ID, V_WHERECOLNAME, V_WHEREKEYVALUE; 
    
END RM_SUPPORT_SCRIPTS_V2;

但是当我从 EXECUTE 语句中调用它时

EXEC RM_SUPPORT_SCRIPTS_V2 (USERS_TABLE, USER_ID,ORTEGALUX,USER_ID,TESTED,FX);    

我收到以下错误

错误报告 - ORA-06550:第 1 行,第 31 列: PLS-00357:此上下文中不允许表、视图或序列引用“USERS_TABLE” ORA-06550:第 1 行,第 7 列: PL/SQL:语句被忽略 06550. 00000 - “第 %s 行,第 %s 列:\n%s” *原因:通常是 PL/SQL 编译错误。 *行动:

有谁知道为什么会发生这种情况?我尝试在每个表、列的调用中加入简单的逗号,但仍然失败。

谢谢。

【问题讨论】:

【参考方案1】:

错误来自调用,而不是过程。您正在传递字符串,因此您需要引用它们:

EXEC RM_SUPPORT_SCRIPTS_V2 ('USERS_TABLE', 'USER_ID','ORTEGALUX','USER_ID','TESTED','FX');

但是你不能对列名使用绑定变量,你需要将它们连接起来,就像你使用表名一样。

      EXECUTE IMMEDIATE 
        'UPDATE '||DBMS_ASSERT.simple_sql_name(V_TABLENAME) 
            ||' SET ' || V_SETCOLNAME || ' = :1, update_by_userid = :2, UPDATE_DATE = SYSDATE'
            ||' WHERE ' || V_WHERECOLNAME || ' = :3 '
            using V_SETVALUE, USER_ID, V_WHEREKEYVALUE; 

尽管您可能也想为这些添加断言检查。

【讨论】:

谢谢@Alex Poole 我已尝试按照您的通知引用,但我现在收到此错误code 错误从第 1 行开始:命令中的 BEGIN RM_SUPPORT_SCRIPTS_V2 ('user_list', 'USERS_TABLE' ,'ORTEGALUX','USER_ID','TESTED','FX');结尾;错误报告 - ORA-06550:第 1 行,第 316 列:PLS-00201:必须声明标识符 'RM_SUPPORT_SCRIPTS_V2' ORA-06550:第 1 行,第 316 列:PL/SQL:语句被忽略 06550。00000 -“第 %s 行,列%s:\n%s" *原因:通常是 PL/SQL 编译错误。 *行动: 您将 RM 更改为 FMV?那似乎不存在...? 嗯,它真的存在吗?在您调用它的同一架构中? (错误真的是指第 316 列吗?这看起来很奇怪。 你是对的,我的架构有误,现在我得到了这个 ORA-01747: invalid user.table.column, table.column, or column specification ORA-06512: at "OPTIMA.RM_SUPPORT_SCRIPTS_V2" ,第 12 行 ORA-06512:在第 1 行 01747.00000 -“无效的 user.table.column、table.column 或列规范” 更新,我有不同表的脚本,错误仍然存​​在。

以上是关于存储过程EXECUTE IMMEDIATE V_SQL执行很慢或出不来,如果把V_SQL语句拿出来单独执行很快,这是为啥?的主要内容,如果未能解决你的问题,请参考以下文章

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

从存储过程调用时,PL SQL Execute Immediate 不起作用

PL/SQL里 execute immediate的用法 谁给解释下

oracle 中execute immediate作用

execute immediate

存储过程EXECUTE IMMEDIATE V_SQL执行很慢或出不来,如果把V_SQL语句拿出来单独执行很快,这是为啥?