【问题标题】:PL/SQL: “00904. 00000 - ”%s: invalid identifier"PL/SQL:“00904。 00000 - “%s: 无效标识符”
【发布时间】:2020-04-07 22:42:40
【问题描述】:

您好,我有以下代码:

CREATE OR REPLACE PROCEDURE instead_of_select(
where_in_sname IN VARCHAR2,
where_in_city IN VARCHAR2)
IS
BEGIN
    EXECUTE IMMEDIATE
    'DECLARE rowss  SAL%ROWTYPE;
        BEGIN SELECT * INTO rowss from SAL where SNAME=' || where_in_sname || 
        ' and CITY='|| where_in_city ||';
    END;';
END instead_of_select;

BEGIN 
    instead_of_select('Peel', 'London');
END;    

但是当我运行它时,我无法弄清楚它不喜欢什么。它给了我以下错误

PL/SQL: ORA-00904: "LONDON": 无效标识符 ORA-06550:第 2 行,第 11 列: PL/SQL:忽略 SQL 语句 ORA-06512: 在“SYSTEM.INSTEAD_OF_SELECT”,第 7 行 ORA-06512: 在第 2 行 06550. 00000 - “第 %s 行,第 %s 列:\n%s” *原因:通常是 PL/SQL 编译错误。

表格存在,数据正确,会出现什么问题?

天哪,这让我发疯了

【问题讨论】:

    标签: oracle


    【解决方案1】:

    您传入的参数是字符串,并且您将它们连接到您的动态查询中;但没有引号,所以内部查询最终为:

    SELECT * INTO rowss from SAL where SNAME=Peel and CITY=London;
    

    您可以在这些值周围添加引号(但必须对其进行转义):

    EXECUTE IMMEDIATE
    'DECLARE rowss  SAL%ROWTYPE;
        BEGIN SELECT * INTO rowss from SAL where SNAME=''' || where_in_sname || 
        ''' and CITY='''|| where_in_city ||''';
    END;';
    

    它会生成:

    SELECT * INTO rowss from SAL where SNAME='Peel' and CITY='London';
    

    但最好使用绑定变量:

    EXECUTE IMMEDIATE
    'DECLARE rowss  SAL%ROWTYPE;
        BEGIN SELECT * INTO rowss from SAL where SNAME=:where_in_sname' || 
        ' and CITY=:where_in_city' USING where_in_sname, where_in_city;
    END;';
    

    rowss 变量只存在于该动态语句中,但过程及其调用者看不到结果。

    无论如何,这根本不需要动态;你可以这样做:

    CREATE OR REPLACE PROCEDURE instead_of_select(
        where_in_sname IN VARCHAR2,
        where_in_city IN VARCHAR2)
    IS
        rowss SAL%ROWTYPE;
    BEGIN
        SELECT * INTO rowss
        from SAL
        where SNAME=where_in_sname
        and CITY= where_in_city;
    END instead_of_select;
    

    但是调用者仍然看不到rowss。目前尚不清楚您期望或希望结果发生什么 - 可能您希望将它们作为 OUT 变量、记录或引用游标传回。 (大概过滤器使结果唯一,否则你会得到一个过多的行错误;你仍然可以得到 no-data-found。)

    【讨论】:

      【解决方案2】:

      这里有一个建议可以帮助您自己调试这种东西。与其尝试构建大的、连接的、动态的字符串作为 EXEC IMMEDIATE 的一部分,不如将其分配给一个变量,然后使用 dbms_output.put_line 来显示你所构建的确切内容,然后只需 EXEC IMMEDIATE多变的。

      CREATE OR REPLACE PROCEDURE instead_of_select(
      where_in_sname IN VARCHAR2,
      where_in_city IN VARCHAR2)
      IS
      rowss  SAL%ROWTYPE
      v_sql varchar2(4000);
      BEGIN
          v_sql := 'SELECT * INTO rowss from SAL where SNAME=' || where_in_sname || 
              ' and CITY='|| where_in_city ';
          dbms_output.put_line(v_sql);
           EXECUTE IMMEDIATE v_sql;
      END instead_of_select;
      

      以上,我只是展示了一种设置和运行(和调试)EXEC IMMEDIATE 语句的更好方法。如果您不使用绑定变量,我没有解决转义引号的需要。另请注意,dbms_output 行仅用于调试目的。解决问题后,您可以将其注释掉。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多