Синтаксис динамического SQL с использованием EXECUTE IMMEDIATE

Оператор динамического обновления SQL, как показано ниже:

EXECUTE IMMEDIATE 'UPDATE '||l_prefix||'CRS_CUSTOMERS SET CUSTOMER_SOURCE_REF_ID = '||i.CUSTOMER_REF_ID||' WHERE CUSTOMER_ID = '||i.CUSTOMER_ID;

l_prefix параметр содержит префикс имени таблицы, назначенное значение - T_i.CUSTOMER_REF_ID а также i.CUSTOMER_ID поля, извлеченные из курсора.

Ошибка динамического оператора ORA-00904: invalid identifier когда данные получены.

Когда переписать его статическим способом, запрос работает нормально:

UPDATE T_CRS_CUSTOMERS SET CUSTOMER_SOURCE_REF_ID = i.CUSTOMER_REF_ID WHERE CUSTOMER_ID = i.CUSTOMER_ID;

Я знаю, что это должно быть что-то не так в конкатенации динамического SQL, просто не могу точно определить это, так как компиляция в порядке.

1 ответ

Решение

ВНИМАНИЕ: Динамический SQL, подобный этому, подвержен атакам SQL-инъекций. По возможности переписывайте свой динамический SQL, чтобы вместо него использовать переменные связывания.

Вместо того, чтобы создавать свой динамический SQL следующим образом:

L_SQL := 'UPDATE '||l_prefix||'CRS_CUSTOMERS SET CUSTOMER_SOURCE_REF_ID = '||i.CUSTOMER_REF_ID||' WHERE CUSTOMER_ID = '||i.CUSTOMER_ID;
EXECUTE IMMEDIATE L_SQL;

Использовать этот:

L_SQL := 'UPDATE '||l_prefix||'CRS_CUSTOMERS SET CUSTOMER_SOURCE_REF_ID = :REF_ID WHERE CUSTOMER_ID = :CUST_ID';
EXECUTE IMMEDIATE L_SQL USING i.CUSTOMER_REF_ID, i.CUSTOMER_ID;

Это все еще подлежит внедрению SQL на l_prefix, но если вы контролируете это значение программно, это может быть в порядке. Кроме того, разделение конструкции SQL и его выполнения на два этапа позволяет упростить замену EXECUTE IMMEDIATE с DBMS_OUTPUT.PUT_LINE(SQL); проверить ваш запрос на наличие синтаксических ошибок. Вы также можете хотеть DBMS_OUTPUT.PUT_LINE ваши параметры i.CUSTOMER_REF_ID а также i.CUSTOMER_ID проверить их значения.

Другие вопросы по тегам