如何使用Execute Immediate语句嵌套在Execute Immediate里面

How Can use Execute Immediate statement be nested inside in the Execute Immediate

我有一个固定的执行即时叙述。其中的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

寻求帮助

谢谢

你的方法看起来很复杂。你试过这个吗:

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;

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

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

您可以使用:

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<>fiddle here

你的“错误”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会正确return'3'进入MSG.

db<>fiddle here