Как я могу выполнять только выборочные операторы из файла SQL? - PullRequest
4 голосов
/ 20 ноября 2010

У меня есть файл .sql, в котором есть последовательность операторов создания таблиц, например:

crtab.sql

define ll='&1';
define ul='&2';

create table TAB1 (...);
create table TAB2 (...);
create table TAB3 (...);
...
create table TAB1000 (...);

Пользователь передает в качестве аргументов два параметра - нижний предел ll и верхний предел ul, которые обозначают диапазон создаваемых номеров таблиц.


Например,

sqlplus crtab.sql 3 67

должен создавать только таблицы TAB3 до TAB67.

Как я могу реализовать эту логику в моем файле .sql?

Ответы [ 5 ]

2 голосов
/ 23 ноября 2010
  1. Использовать ассоциативный массив , и вставьте все запросы в этот массив следующим образом:

myArray(1) := 'CREATE TAB 1 ...';

...

myArray(1000) := 'CREATE TAB 1000 ...';

2. Перейдите через ll к ul и выполните эти запросы, т.е. * * 1 016

for i in ll..ul
  loop
       @sql = myArray(i);
       exec @sql; 
  end loop;

Прошу прощения за любые синтаксические ошибки.

2 голосов
/ 24 ноября 2010

Может быть, вот так

CREATE OR REPLACE PROCEDURE TABS_V1 (ll number, ul number) IS
BEGIN
    IF 1 BETWEEN ll AND ul THEN
          EXECUTE IMMEDIATE 'create table TAB1 (...)';
    END IF;
    IF 2 BETWEEN ll AND ul THEN
          EXECUTE IMMEDIATE 'create table TAB2 (...)';
    END IF;
    IF 3 BETWEEN ll AND ul THEN
          EXECUTE IMMEDIATE 'create table TAB3 (...)';
    END IF;

    ...

    IF 1000 BETWEEN ll AND ul THEN
          EXECUTE IMMEDIATE 'create table TAB1000 (...)';
    END IF;
END;



CREATE OR REPLACE PROCEDURE TABS_V2 (ll number, ul number) IS
    TYPE tabs IS TABLE OF VARCHAR2(4000) INDEX BY NUMBER;
    tabs all_tabs;
BEGIN
    all_tabs(1) = 'create table TAB1 (...)';
    all_tabs(1) = 'create table TAB2 (...)';
    all_tabs(1) = 'create table TAB3 (...)';
    ...
    all_tabs(1000) = 'create table TAB1000 (...)';

    FOR cnt IN ll .. ul LOOP
        EXECUTE IMMEDIATE all_tabs(cnt);
    END LOOP;
END;
1 голос
/ 29 ноября 2010

Есть несколько способов сделать это.Во-первых, вы можете использовать анонимный блок с вложенной таблицей операторов или ассоциативным массивом операторов.Подход с использованием вложенных таблиц требует немного меньших изменений в существующем сценарии, но существует риск того, что числа выйдут из последовательности.Обратите внимание, что я использую альтернативный механизм цитирования, например, q '[символ] ... [символ]', на тот случай, если ваш DDL содержит некоторые апострофы.

Этот код похож на некоторые другие ответы, но с синтаксисом Oracle и не требует создания дополнительных объектов.

Сценарий вложенной таблицы:

--Only create the tables between the two values (nested table)
declare
  type varchar_tab is table of varchar2(32767);
  table_statements varchar_tab := varchar_tab(
    q'!create table tab1 (test1 number)!',
    q'!create table tab2 (test1 number)!',
    q'!create table tab3 (test1 number)!',
    q'!create table tab4 (test1 number)!'
  );
begin
  for i in &1 .. &2 loop
    execute immediate table_statements(i);
  end loop;
end;
/

Сценарий ассоциативного массива:

--Only create the tables between the two values (associative array)
declare
  type varchar_tab is table of varchar2(32767) index by number;
  table_statements varchar_tab;
begin
  table_statements(1) := q'!create table tab1 (test1 number)!';
  table_statements(2) := q'!create table tab2 (test1 number)!';
  table_statements(3) := q'!create table tab3 (test1 number)!';
  table_statements(4) := q'!create table tab4 (test1 number)!';

  --Only create the tables between the two values
  for i in &1 .. &2 loop
    execute immediate table_statements(i);
  end loop;
end;
/

Если выВ поисках способа сохранить ваш сценарий практически идентичным его текущей форме, другой подход будет состоять в том, чтобы запустить весь сценарий и затем иметь в конце анонимный блок, который удаляет ненужные таблицы.Это делает верх вашего скрипта действительно простым, но, очевидно, могут возникнуть некоторые проблемы с автоматическим удалением таблиц.

--Drop all the tables except for those within the range
declare
  table_does_not_exist exception;
  pragma exception_init(table_does_not_exist, -00942);
begin
  for i in 1 .. 1000 loop
    if i between &1 and &2 then
      null;
    else
      begin
        execute immediate 'drop table tab'||i;
      exception when table_does_not_exist then null;
      end;
    end if;
  end loop;
end;
/
1 голос
/ 20 ноября 2010

Предполагая, что структуры таблиц одинаковы, было бы лучше создавать и выполнять динамические операторы SQL в цикле, основанном на ваших ll и ul.Например (в синтаксисе сервера SQL)

declare @sql varchar(1000)
declare @i int set @i = @ll
while @i <= @ul begin
    set @sql = 'create table TAB' + cast( @i as varchar ) + '(...);'
    exec @sql
    set @i = @i + 1 
end

Если структуры таблиц отличаются, просто поместите оператор if вокруг каждого создания.

0 голосов
/ 02 декабря 2010

Один из хакерских способов сделать это - использовать препроцессор C и директивы #if, чтобы включать или не включать каждое выражение в некоторые макросы, которые вы определили в командной строке.Затем запустите предварительно обработанный файл, а не оригинальный.

...