无效 SQL 类型:sqlKind = UNINITIALIZED - PLSQL 错误

Invalid SQL type: sqlKind = UNINITIALIZED - PLSQL Error

我只是想阻止用户在没有 WHERE 子句的情况下使用 运行 UPDATE 语句。我在下面提供了我的 PLSQL

create or replace PROCEDURE secure_update(update_query IN varchar2)
IS
  msg varchar2(30000);
  flag char(1);
  qry varchar2(30000);
BEGIN

  IF upper(update_query) LIKE 'UPDATE%SET%WHERE%=%' THEN
    flag := '1';
  ELSE
    flag := '0';
  END IF;

  IF (flag = '1') THEN
    --qry := update_query;
    execute immediate update_query into msg;
  END IF;

  dbms_output.put_line(msg);

END;

我就是这样执行的

EXEC secure_update
('
UPDATE dummy_table
SET col1 = ''whatever''
WHERE pk = ''1234''
')

我不断收到这条消息:

Invalid SQL type: sqlKind = UNINITIALIZED

你能帮我看看如何克服这个错误吗?

一个UPDATE语句不应该被执行into任何东西,它应该被执行。此代码演示了错误,但错误消息与您发布的消息略有不同。

create table dummy_table(col1 varchar2(100), pk number);

declare
    msg varchar2(30000);
begin
    execute immediate q'[
        UPDATE dummy_table
        SET col1 = 'whatever'
        WHERE pk = '1234'
    ]' into msg;
end;
/

ORA-01007: variable not in select list
ORA-06512: at line 4

删除 into msg 即可。此外,替代引用机制用于避免转义引号。

这有效,请查看更改,不要在立即执行中使用 into 子句

create or replace PROCEDURE secure_update(update_query IN varchar2)
IS
  msg varchar2(30000);
  flag char(1);
  qry varchar2(30000);
BEGIN

  IF upper(update_query) LIKE 'UPDATE%SET%WHERE%=%' THEN
    flag := '1';
    dbms_output.put_line('updated succesfully');
  ELSE
    flag := '0';
    dbms_output.put_line('no where clause in update');
  END IF;

  IF (flag = '1') THEN
    --qry := update_query;
    execute immediate update_query ;
  END IF;

  END;

如果你想在更新中使用 varchar 那么请看这个

SCOTT@research 16-APR-15> select * from test2;

A     B
----- -----
a     b

code to execute procedure :

declare
lsql varchar2(100):= 'update test2 set a=''z'' where b=''b'' ';
begin
secure_update(lsql);
end;

output:     updated succesfully

SCOTT@research 16-APR-15> select * from test2;

A     B
----- -----
z     b

declare
lsql varchar2(100):= 'update test2 set a=''z''';
begin
secure_update(lsql);
end;

output

no where clause in update    

另一个例子

SCOTT@research 16-APR-15> select * from test1;

      VAL1       VAL2       VAL3
---------- ---------- ----------
         2          2          4
         3          2          4
       123          2          3
        42          3

SCOTT@research 16-APR-15> exec secure_update('update test1 set val1=555 where val1=2');
updated succesfully

PL/SQL procedure successfully completed.

SCOTT@research 16-APR-15> select * from test1;

      VAL1       VAL2       VAL3
---------- ---------- ----------
       555          2          4
         3          2          4
       123          2          3
        42          3


SCOTT@research 16-APR-15> exec secure_update('update test1 set val1=555');
no where clause in update

PL/SQL procedure successfully completed.

SQL 开发人员(和 SQL*Plus,但可能不是其他客户端!)需要将 exec 命令放在一行上。您没有显示从该调用中获得的早期错误:

EXEC secure_update
Error report -
ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'SECURE_UPDATE'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
06550. 00000 -  "line %s, column %s:\n%s"
*Cause:    Usually a PL/SQL compilation error.
*Action:

Error starting at line : 25 in command -
('
UPDATE dummy_table
SET col1 = ''whatever''
WHERE pk = ''1234''
')
Error at Command Line : 25 Column : 2
Error report -
SQL Error: Invalid SQL type: sqlKind = UNINITIALIZED

调用过程时没有参数,因为 none 与实际 exec 在同一行,因此您从该行得到 PLS-00306。然后余数被解释为一个单独的命令,它得到你报告的 'invalid SQL type' 错误。 (在 SQL Developer 中,即;在 SQL*Plus 中,第一部分会得到相同的 PLS-00306,但其余部分会得到 ORA-00928: missing SELECT keyword)。

您可以将整个语句移动到一行中:

EXEC secure_update ('UPDATE dummy_table SET col1 = ''whatever'' WHERE pk = ''1234''');

或者使用显式匿名块而不是 exec shorthand:

BEGIN
  secure_update
  ('UPDATE dummy_table
  SET col1 = ''whatever''
  WHERE pk = ''1234''
  ');
  dbms_output.put_line('after');
END;
/

另请注意,我不得不将 UPDATE 向上移动一行,因为您的检查不允许在命令开头有任何空格(包括换行符)。您程序中的 into msg 没有做任何事情,但似乎没有引起问题;如果您想查看更新了多少行,请在 execute immediate 之后使用 SQL%ROWCOUNT。