2015-04-15 7 views
3

Я просто хочу, чтобы пользователи не запускали инструкцию UPDATE без предложения WHERE. Я обеспечил мне PLSQL нижеНеверный тип SQL: sqlKind = UNINITIALIZED - ошибка 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'' 
') 

я получаю это сообщение:

Неверный тип SQL: sqlKind = UNINITIALIZED

Не могли бы вы помочь мне узнать, как преодолеть это ROR?

+0

при использовании 'dynamic sql', попытайтесь поместить значения varchar внутри двух двух кавычек' ''whatever''', я имею в виду использование' '' '' '' – jfun

+0

Помимо ошибки, которую вы видите, несбалансированный одинарные кавычки и что 'exec' должен быть на одной строке, я не уверен в вашей цели. Если вы хотите проверить предложение 'where', чтобы вызывающий абонент не смог сразу обновить все записи, что мешает им делать что-то вроде' where 1 = 1'? –

+0

Этот plsql предназначен для экспериментов. Я не рассматриваю безопасность на данный момент – user311509

ответ

2

Это работает, смотрите изменения, не правда использовать в предложении в выполнить немедленное

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 в обновлении, тогда смотрите этот

[email protected] 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 

[email protected] 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  

другой пример

[email protected] 16-APR-15> select * from test1; 

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

[email protected] 16-APR-15> exec secure_update('update test1 set val1=555 where val1=2'); 
updated succesfully 

PL/SQL procedure successfully completed. 

[email protected] 16-APR-15> select * from test1; 

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


[email protected] 16-APR-15> exec secure_update('update test1 set val1=555'); 
no where clause in update 

PL/SQL procedure successfully completed. 
0

Оператор 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 и он будет работать. Кроме того, альтернативный механизм цитирования используется, чтобы избежать экранирования кавычек.

+0

Кстати, вы пытаетесь создать общую программу для обработки любого типа динамического оператора SQL? Если это так, у вас может быть много работы. Просто выяснить, что это за постановка, и получить соответствующее сообщение обратной связи сложно. Я работаю над такой системой [здесь] (https://github.com/jonheller1/plsql_lexer). Он не будет готов в течение нескольких недель, но это может дать вам представление о том, насколько сложной может быть задача. –

1

Разработчик 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 

Процедура вызывается без аргументов, потому что нет ни на одной и той же линии, что и фактическое exec, так что вы получите PLS -00306 от этой линии. Затем остаток интерпретируется как отдельная команда, которая получает сообщение об ошибке «недопустимый тип SQL». (В SQL Developer, то есть в SQL * Plus вы получите тот же PLS-00306 для первой части, но ORA-00928: missing SELECT keyword для остальных).

Вы можете либо переместить все заявление в одну строку:

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

Или использовать явный анонимный блок, а не exec стенографии:

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

Заметим также, что я должен был двигаться UPDATE в любом случае, так как ваш чек не допускает пробелов (включая разрыв строки) в начале команды. into msg в вашей процедуре ничего не делает, но, похоже, не вызывает проблемы; если вы хотите увидеть, сколько строк было обновлено, используйте SQL% ROWCOUNT после execute immediate.

Смежные вопросы