【问题标题】:Getting invalid identifier ORA-00904获取无效标识符 ORA-00904
【发布时间】:2021-07-18 16:06:44
【问题描述】:

我有一个程序

Create or replace procedure schoolstudents(
    LS1 OUT NUMBER,
    LS2 OUT NUMBER,
    val in VARCHAR2)
IS
 val1 VARCHAR2(128);
 schoolId NUMBER;

BEGIN
    val11 := val;
    schoolId := function(val1);
    insert := 'Insert into sname values("a","b") RETURNING '||schoolId||' into :0, '||schoolId||' into :1';
   Execute immediate insert USING OUT LS1,OUT LS2;

   COMMIT;
  

我遇到了一个错误

ORA-00933:SQL 命令未正确结束。

【问题讨论】:

  • 您的执行块中的val11 是什么?你声明了一个变量val1,你的意思是给它赋值,而不是给val**11**?

标签: sql oracle stored-procedures plsql


【解决方案1】:
  • 您需要一个 END; 语句来完成 PL/SQL 块。
  • 您尚未声明insert 变量,而insert 是关键字,您不应将其用作变量名。
  • 字符串文字需要用单引号(而不是双引号)括起来。
  • RETURNING INTO 的语法是RETURNING column1, column2 INTO :1, :2

如果你有设置:

CREATE TABLE sname (
  col1 VARCHAR2(20),
  col2 VARCHAR2(20)
);

CREATE FUNCTION function( tablename IN VARCHAR2) RETURN NUMBER
IS
BEGIN
  RETURN 1;
END;
/

那么你的程序是:

Create or replace procedure schoolstudents(
    LS1 OUT NUMBER,
    LS2 OUT NUMBER,
    tablename in VARCHAR2)
IS
 lname     VARCHAR2(128);
 schoolId  NUMBER;
 insert_sql VARCHAR2(200);
BEGIN
  lname := tablename;
  schoolId := function(lname);
  insert_sql := 'Insert into sname values(''a'',''b'') RETURNING '||schoolId||', '||schoolId||' into :1, :2';
  EXECUTE IMMEDIATE insert_sql RETURNING INTO LS1, LS2;

  COMMIT;
END;
/

但是,您可以在没有动态 SQl 的情况下将您的过程重写为:

Create or replace procedure schoolstudents(
    LS1 OUT NUMBER,
    LS2 OUT NUMBER,
    tablename in VARCHAR2)
IS
 schoolId NUMBER;
BEGIN
    schoolId := function(tablename);
    Insert into sname values('a','b');
    LS1 := schoolId;
    LS2 := schoolId;

   COMMIT;
END;
/

db小提琴here

【讨论】:

  • 嘿,知道如何将这两个返回值存储在一个对象中,比如说数组吗?
  • @SQLdeveloper 这两个值是什么?从哪里回来?我相信你可以,但我不明白你的要求是什么,这似乎超出了你原来问题的范围。
  • 立即执行 insert_sql 返回 LS1、LS2 。不是有 2 个输出,而是有可能将两个值存储为单个 OUTPUT
  • 创建或替换程序schoolstudents(LS1 OUT NUMBER, LS2 OUT NUMBER, tablename in VARCHAR2) IS lname VARCHAR2(128);学校编号; insert_sql VARCHAR2(200);开始 lname := 表名; schoolId := 函数(lname); insert_sql := '插入 sname 值(''a'',''b'') 返回 '||schoolId||', '||schoolId||'进入:1,:2';立即执行 insert_sql 返回 LS1,LS2;犯罪;结束;
  • @SQLdeveloper 是的,只需像您一样将 2 个值返回到两个变量中,然后声明一个集合类型变量并将值添加到该变量中,然后返回集合并更改过程的签名。跨度>
【解决方案2】:

不少错误。修复后,它会编译(不知道它会按照您的计划进行)。

  • 您使用了insert 变量,但从未声明它。无论如何,您必须更改其名称,insert 用于插入
  • function(lname) 到底是什么?你不能命名一个函数function(类似于我之前提到的insert)。我不知道它是什么所以我把它注释掉了
  • 不要对字符串使用双引号,而是使用单引号。但是,在动态 SQL 中,您必须转义它们(通过将它们加倍),或者 - 更简单 - 使用 q-quoting 机制

最后:

SQL> CREATE OR replace PROCEDURE schoolstudents(
  2    ls1        OUT  NUMBER,
  3    ls2        OUT  NUMBER,
  4    tablename  IN   VARCHAR2
  5  )IS
  6    lname VARCHAR2(128);
  7    schoolid NUMBER;
  8    l_insert varchar2(200);                             --> not INSERT, it is reserved
  9  BEGIN
 10      lname := tablename;
 11      schoolId := lname; --function(lname);             --> what is FUNCTION?
 12      l_insert := q'[Insert into sname values('a','b')  --> q-mecanism; single, not double quotes
 13        RETURNING ]'||schoolId||' into :0, '||schoolId||' into :1';
 14     Execute immediate l_insert
 15       USING OUT ls1, OUT ls2;
 16    COMMIT;
 17  END;
 18  /

Procedure created.

SQL>

【讨论】:

    【解决方案3】:

    正如其他人指出的那样,这段代码存在很多问题。没有人指出的是,似乎没有任何理由在这里使用 EXECUTE IMMEDIATE 。我建议:

    Create or replace procedure schoolstudents(LS1 OUT NUMBER,
                                               LS2 OUT NUMBER,
                                               tablename in VARCHAR2)
    IS
      schoolId  NUMBER;
    BEGIN
      schoolId := some_function(tablename);
    
      Insert into sname values('a', 'b');
    
      COMMIT;
    
      LS1 := schoolId;
      LS2 := schoolID;
    END schoolstudents;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-08
      • 2022-01-22
      • 2011-08-27
      • 2011-04-21
      • 2019-06-29
      • 2013-10-20
      相关资源
      最近更新 更多