в любом случае выполняет DDL, так что хорошее напоминание!

новка задачи

У меня есть динамический SQL, который мне нужно хранить в таблице, но перед сохранением SQL мне нужно проверить SQL со списком столбцов, хранящихся в другой таблице. Без выполнения запроса можно ли найти имя столбца в списке выбора?

Approach1 Единственный вариант, о котором я могу подумать, это попытаться использовать план объяснения запроса и прочитать метаданные в таблице словарей данных. Но, к сожалению, я не могу найти таблицу с такими данными. Пожалуйста, дайте мне знать, если вы знаете такие представления ?

Approach2 Используйте пакет DBMS_SQL.DESCRIBE_COLUMNS, чтобы найти имя столбца, но я верю, что это выполнит весь запрос.

Ответы на вопрос(2)

будем выполнить оператор DDL. Если строка'select * from employees' заменяется'drop table employees' код потерпит неудачу, но таблица все равно будет удалена.

Если вы беспокоитесь только о производительности получения метаданных, то ответ Алекса Пула будет работать нормально.

Если вас беспокоит неправильный тип операторов, вы можете внести некоторые коррективы в ответ Алекса Пула.

Удивительно сложно сказать, является ли утверждениеSELECT вместо чего-то еще. Простая проверка условия, что строка начинается сselect будет работать 99% времени, но получение от 99% до 100% - это огромный объем работы. Простые регулярные выражения не могут идти в ногу со всеми различными ключевыми словами, комментариями, альтернативным форматом цитирования, пробелами и т. Д.

/*comment in front -- */ select * from dual
    select * from dual
with asdf as (select * from dual) select * from asdf;
((((((select * from dual))))));

Если вам нужна 100% точность, я рекомендую вам использовать мой открытый исходный кодPLSQL_LEXER, После установки вы можете надежно протестировать такие типы команд:

select
    statement_classifier.get_command_name('  /*comment*/ ((select * from dual))') test1,
    statement_classifier.get_command_name('alter table asdf move compress') test2
from dual;

TEST1    TEST2
-----    -----
SELECT   ALTER TABLE
 Alex Poole23 нояб. 2017 г., 16:04
Я прочитал вопрос как относящийся только к запросам, но я забыл, чтоparse в любом случае выполняет DDL, так что хорошее напоминание!
Решение Вопроса

чтобы получить имена столбцов, вам просто нужно разобрать его; например в качестве простого примера:

set serveroutput on

declare
  l_statement varchar2(4000) := 'select * from employees';
  l_c pls_integer;
  l_col_cnt pls_integer;
  l_desc_t dbms_sql.desc_tab;
begin
  l_c := dbms_sql.open_cursor;
  dbms_sql.parse(c=>l_c, statement=>l_statement, language_flag=>dbms_sql.native);
  dbms_sql.describe_columns(c=>l_c, col_cnt=>l_col_cnt, desc_t=>l_desc_t);

  for i in 1..l_col_cnt loop
    dbms_output.put_line(l_desc_t(i).col_name);
  end loop;

  dbms_sql.close_cursor(l_c);
exception
  when others then
    if (dbms_sql.is_open(l_c)) then
      dbms_sql.close_cursor(l_c);
    end if;
    raise;
end;
/

какие выводы:

EMPLOYEE_ID
FIRST_NAME
LAST_NAME
EMAIL
PHONE_NUMBER
HIRE_DATE
JOB_ID
SALARY
COMMISSION_PCT
MANAGER_ID
DEPARTMENT_ID

PL/SQL procedure successfully completed.

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

Помните, что вы будете видеть (и проверять) только имена столбцов или псевдонимы для выражений столбцов, которые не обязательно будут отражать данные, которые фактически извлекаются. Кто-то может создать запрос, который извлекает любые данные из любого места, к которому у него есть разрешение, но затем дает псевдонимы столбцов / выражений, которые считаются действительными.

Если вы пытаетесь ограничить доступ к определенным данным, посмотрите на другие механизмы, такие как представления, виртуальная частная база данных и т. Д.

Ваш ответ на вопрос