【问题标题】:How Can use Execute Immediate statement be nested inside in the Execute Immediate如何使用 Execute Immediate 语句嵌套在 Execute Immediate 中
【发布时间】:2021-04-15 14:29:58
【问题描述】:

我有一个固定的执行即时叙述。里面的sql_text只会带一个参数做一个简单的语法查询

例子

EXECUTE IMMEDIATE sql_text USING SN RETURNING INTO MSG;

sql_text 是可以交替使用的搜索语句

sql_txt = 'select count(1) from productDetails  where ID = :parameter1'

原来EXECUTE IMMEDIATE只会带一个参数来执行sql_text。这次我想引入多个参数来执行sql_text,而不影响现有的只有一个参数的sql_text操作。

因此,许多尝试都失败了。错误的SQL如下

DECLARE
    SQL_TEXT VARCHAR2(1000);
    MSG VARCHAR2(500);
    SN VARCHAR2(500) := parameter1/parameter2;
BEGIN

   sql_text := '
   DECLARE
   parameters VARCHAR2(50);
   parameter1 VARCHAR2(50);
   parameter2 VARCHAR2(50);
   sql_txt VARCHAR2(1000);
   BEGIN
      parameters := :SN;
      parameter1 := substr(parameters,0,10);
      parameter2 := substr(parameters,11,10);
      
      sql_txt = ''select count(1) from productDetails  where ID = :parameter1
      AND NUMBER = :parameter2''
      EXECUTE IMMEDIATE sql_txt USING parameter1 RETURNING INTO MSG;
   END;'; 
   
    EXECUTE IMMEDIATE sql_text USING SN RETURNING INTO MSG;
    DBMS_OUTPUT.put_line(MSG);
END;

我尝试将多个参数放在一个参数中。

SN VARCHAR2(500) := parameter1/parameter2;

从sql_text中取出参数并使用

 parameters := :SN;
      parameter1 := substr(parameters,0,10);
      parameter2 := substr(parameters,11,10);

它不断尝试并失败

数据库版本:oracle database 19c

寻求帮助

谢谢

【问题讨论】:

  • 发布任何错误消息。请注意,您的内部 exec 内部的字符串直接引用外部外部 SQL 的变量。这将如何工作?
  • 错误信息需要等到明天才能提供。

标签: oracle stored-procedures plsql dynamic-sql oracle19c


【解决方案1】:

您的“错误”SQL 有几个问题:

  1. sql_text 的分配末尾缺少分号。

  2. 在同一语句中,NUMBER 不是 Oracle 中的有效标识符,除非它被引用。

  3. SN的初始化需要在文字周围加撇号。

所以sql_text 的赋值应该是

sql_txt := ''select count(1) from productDetails  where ID = :parameter1
          AND "NUMBER" = :parameter2'';

所以你的块应该是

DECLARE
    SQL_TEXT VARCHAR2(1000);
    MSG VARCHAR2(500);
    SN VARCHAR2(500) := 'parameter1/parameter2';
BEGIN

   sql_text := '
   DECLARE
   parameters VARCHAR2(50);
   parameter1 VARCHAR2(50);
   parameter2 VARCHAR2(50);
   sql_txt VARCHAR2(1000);
   BEGIN
      parameters := :SN;
      parameter1 := substr(parameters,0,10);
      parameter2 := substr(parameters,11,10);
      
      sql_txt = ''select count(1) from productDetails  where ID = :parameter1
      AND "NUMBER" = :parameter2'';
      EXECUTE IMMEDIATE sql_txt USING parameter1 RETURNING INTO MSG;
   END;'; 
   
    EXECUTE IMMEDIATE sql_text USING SN RETURNING INTO MSG;
    DBMS_OUTPUT.put_line(MSG);
END;

但是,上面的内容可以通过以下方式大大简化:

SELECT COUNT(*)
  INTO MSG
  FROM PRODUCTDETAILS
  WHERE ID = (SELECT REGEXP_SUBSTR(SN, '[^/]+', 1, 1) FROM DUAL) AND
        "NUMBER" = (SELECT REGEXP_SUBSTR(SN, '[^/]+', 1, 2) FROM DUAL);

代替嵌入式动态 PL/SQL 块。因此,如果我们使用

创建PRODUCTDETAILS
CREATE TABLE PRODUCTDETAILS(ID, "NUMBER", OTHER_FIELD) AS
  SELECT 'parameter1', 'parameter2', 'DATA1' FROM DUAL UNION ALL
  SELECT 'parameter1', 'parameter2', 'DATA2' FROM DUAL UNION ALL
  SELECT 'parameter2', 'parameter3', 'DATA3' FROM DUAL UNION ALL
  SELECT 'parameter3', 'parameter4', 'DATA4' FROM DUAL UNION ALL
  SELECT 'parameter1', 'parameter2', 'DATA5' FROM DUAL UNION ALL
  SELECT 'parameter4', 'parameter2', 'DATA6' FROM DUAL UNION ALL
  SELECT 'parameter5', 'parameter6', 'DATA7' FROM DUAL

上述 SQL 将正确地将'3' 返回到 MSG。

db<>fiddle here

【讨论】:

    【解决方案2】:

    您的方法似乎很复杂。你试过这个吗:

    DECLARE
        SQL_TEXT VARCHAR2(1000);
        MSG VARCHAR2(500);
        SN VARCHAR2(500) := '[your_parameter_values]';
        parameter1 VARCHAR2(50);
        parameter2 VARCHAR2(50);
    BEGIN
        parameter1 := substr(SN,0,10);
        parameter2 := substr(SN,11,10);
      
        SQL_TEXT = 'select count(1) from productDetails where ID = :p1 AND NUMBER = :p2';
        EXECUTE IMMEDIATE SQL_TEXT USING parameter1, paramemter2 RETURNING INTO MSG;
        DBMS_OUTPUT.put_line(MSG);
    END;
    

    【讨论】:

    • 这是不正确的;您可以将 PL/SQL 匿名块传递给 EXECUTE IMMEDIATE,因为它是单个命令(单个 PL/SQL 块)。
    【解决方案3】:

    您有多个语法错误,包括:

    • = 而不是 :=
    • RETURNING INTO 而不是 INTOOUT 参数。
    • NUMBER 是一个关键字,不能用作标识符(除非你引用它,但你没有引用它)。
    • SUBSTR 是 1-indexed 而不是 0-indexed(这不是语法错误,但会导致您的代码给出意外的结果)。

    你可以使用:

    DECLARE
        SQL_TEXT VARCHAR2(1000);
        MSG VARCHAR2(500);
        SN VARCHAR2(500) := 'parameter1/parameter2';
    BEGIN
    
    sql_text := 'DECLARE
       parameters VARCHAR2(50);
       parameter1 VARCHAR2(50);
       parameter2 VARCHAR2(50);
       sql_txt VARCHAR2(1000);
    BEGIN
       parameters := :SN;
       parameter1 := substr(parameters,1,10);
       parameter2 := substr(parameters,12,10);
        
       sql_txt := ''select count(1) from productDetails  where ID = :parameter1 AND value = :parameter2'';
       EXECUTE IMMEDIATE sql_txt INTO :msg USING IN parameter1, IN parameter2;
    END;'; 
       
        EXECUTE IMMEDIATE sql_text USING IN SN, OUT MSG;
        DBMS_OUTPUT.put_line(MSG);
    END;
    /
    

    其中,对于样本数据:

    CREATE TABLE productDetails ( id, value ) AS
    SELECT 'parameter1', 'parameter2' FROM DUAL;
    

    输出:

    1
    

    db小提琴here

    【讨论】:

      猜你喜欢
      • 2019-03-14
      • 2021-04-11
      • 2011-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-15
      • 1970-01-01
      • 2015-10-07
      相关资源
      最近更新 更多