Операторы DDL в PL/SQL?

Я пытаюсь использовать приведенный ниже код для создания таблицы в PL/SQL:

DECLARE
    V_NAME VARCHAR2(20);
BEGIN
    EXECUTE IMMEDIATE 'CREATE TABLE TEMP(NAME VARCHAR(20))';
    EXECUTE IMMEDIATE 'INSERT INTO TEMP VALUES(''XYZ'')';
    SELECT NAME INTO V_NAME FROM TEMP;
END;
/

Оператор SELECT завершается с ошибкой:

PL/SQL: ORA-00942: table or view does not exist

Возможно ли CREATE, INSERT and SELECT все в одном блоке PL/SQL один за другим?


person Aspirant    schedule 30.06.2012    source источник
comment
почему вы используете динамический sql? это более медленно и опасно. а вставка работает?   -  person Simon Dorociak    schedule 30.06.2012
comment
Это плохая идея. Это обычная конструкция в некоторых других разновидностях СУБД, таких как SQL Server, но Oracle предлагает лучшие подходы. Для получения дополнительной информации прочитайте этот мой старый ответ: stackoverflow.com/a/1193443/146325   -  person APC    schedule 01.07.2012


Ответы (2)


Я предполагаю, что вы делаете что-то вроде следующего:

declare
   v_temp varchar2(20);
begin
   execute immediate 'create table temp(name varchar(20))';
   execute immediate 'insert into temp values(''XYZ'')';

   select name into v_name from temp;
end;

Во время компиляции таблица TEMP не существует. Он еще не создан. Поскольку его не существует, вы не можете выбрать из него; поэтому вы также должны выполнять SELECT динамически. На самом деле нет необходимости выполнять SELECT в этой конкретной ситуации, хотя вы можете использовать returning into.

declare
   v_temp varchar2(20)
begin
   execute immediate 'create table temp(name varchar2(20))';
   execute immediate 'insert into temp 
                      values(''XYZ'')
                      returning name into :1'
                returning into v_temp;
end;

Однако необходимость динамического создания таблиц обычно указывает на плохо спроектированную схему. Это не должно быть необходимо.

Я могу порекомендовать сообщение Рене Ниффенеггера "Почему динамический SQL - это плохо?" по причинам, по которым вам следует избегать динамического SQL, если это вообще возможно, с точки зрения производительности. Также имейте в виду, что вы гораздо более открыты для SQL инъекции и должны использовать переменные связывания и DBMS_ASSERT чтобы защититься от него.

person Ben    schedule 30.06.2012
comment
Спасибо за решение!! Я как бы проверял, можно ли создавать, вставлять и выбирать значения... - person Aspirant; 30.06.2012
comment
@Aspirant, мое предложение действительно создает таблицу, вставляет в нее и выбирает значения... - person Ben; 30.06.2012

Если вы запустите программу несколько раз, вы получите сообщение об ошибке даже после изменения программы для запуска оператора select как динамического SQL или использования предложения return into. Потому что, когда вы запускаете программу в первый раз, она создаст таблицу без каких-либо проблем, но когда вы запустите ее в следующий раз, поскольку таблица уже создана в первый раз, и у вас нет оператора удаления, это вызовет ошибку: «Таблица уже существует в База Данных». Поэтому я предлагаю перед созданием таблицы в программе pl/sql всегда проверять, существует ли уже какая-либо таблица с таким же именем в базе данных или нет. Вы можете выполнить эту проверку, используя представления словаря данных/системные таблицы, в которых хранятся метаданные в зависимости от типа вашей базы данных.

Например, в Oracle вы можете использовать следующие представления, чтобы решить, нужно ли создавать таблицы или нет:

БД_ТАБЛИЦЫ, ВСЕ_ТАБЛИЦЫ, ПОЛЬЗОВАТЕЛЬСКИЕ_ТАБЛИЦЫ

person Gourabp    schedule 11.02.2013