获取无效标识符 ORA-00904

时间:2021-04-24 20:16:55

标签: sql oracle stored-procedures plsql

我有一个程序

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 命令没有正确结束。

3 个答案:

答案 0 :(得分:2)

  • 您需要一个 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<>fiddle here

答案 1 :(得分:1)

相当多的错误。修复后,它会编译(不知道它是否会按照您的计划执行)。

  • 您使用了 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>

答案 2 :(得分:0)

正如其他人指出的,这段代码存在不少问题。没有人指出的是,似乎没有任何理由在这里使用 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;