Не используйте динамический SQL или, если вам нужно использовать динамический SQL, либо внесите белый список имен столбцов, либо выполните некоторую проверку имени столбца, чтобы убедиться, что это действительный идентификатор SQL.
Бездинамический SQL:
CREATE PROCEDURE test (
in_column_name IN VARCHAR2,
in_value IN VARCHAR2,
out_cursor OUT SYS_REFCURSOR
)
IS
BEGIN
OPEN out_cursor FOR
SELECT *
FROM employees
WHERE CASE UPPER( in_column_name )
WHEN 'FIRST_NAME' THEN first_name
WHEN 'LAST_NAME' THEN last_name
WHEN 'SALARY' THEN TO_CHAR( salary )
WHEN 'DEPARTMENT' THEN department
ELSE NULL
END
= in_value;
END;
/
С динамическим SQL - внесите белый список в столбцы и используйте переменную связывания для значения:
CREATE PROCEDURE test2 (
in_column_name IN VARCHAR2,
in_value IN VARCHAR2,
out_cursor OUT SYS_REFCURSOR
)
IS
BEGIN
IF UPPER( in_column_name ) NOT IN ( 'FIRST_NAME', 'LAST_NAME', 'DEPARTMENT', 'SALARY' )
THEN
raise_application_error( -20000, 'Invalid Column Name' );
END IF;
OPEN out_cursor FOR
'SELECT * FROM employees WHERE ' || in_column_name || ' = :value'
USING in_value;
END;
/
С динамическим SQL - используйте DBMS_ASSERT
для проверки имени столбцаи переменная связывания для значения:
CREATE PROCEDURE test3 (
in_column_name IN VARCHAR2,
in_value IN VARCHAR2,
out_cursor OUT SYS_REFCURSOR
)
IS
BEGIN
OPEN out_cursor FOR
'SELECT * FROM employees WHERE ' || DBMS_ASSERT.SIMPLE_SQL_NAME( in_column_name ) || ' = :value'
USING in_value;
END;
/
дБ <> fiddle