如何只从SQL文件中执行选择性语句?

时间:2010-11-20 09:32:13

标签: sql oracle sqlplus

我有一个.sql文件,它有一系列create table语句,如下所示:

  

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

应该只创建表TAB3TAB67

如何在.sql文件中实现此逻辑?

5 个答案:

答案 0 :(得分:2)

  1. 使用associative array, 并按以下方式在该数组中插入所有查询:
  2. myArray(1) := 'CREATE TAB 1 ...';

    ...

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

    2。 循环ll到ul并执行这些查询, 即。

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

    我很抱歉任何语法错误。

答案 1 :(得分:2)

也许喜欢这些

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;

答案 2 :(得分:1)

假设桌面结构相同,你最好创建&基于你的ll和ul在循环中执行动态sql语句。例如(在sql server语法中)

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语句。

答案 3 :(得分:1)

有几种方法可以做到这一点。首先,您可以使用匿名块,其中包含语句的嵌套表或语句的关联数组。嵌套表方法对现有脚本的更改要少一些,但存在数字不按顺序排列的风险。请注意,我正在使用替代引用机制,例如q'[character] ... [character]',以防你的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;
/

答案 4 :(得分:0)

执行此操作的一种方法是使用C预处理程序和#if指令来包含或不包含在命令行上定义的某些宏上的每个语句。然后运行预处理文件而不是原始文件。