2010-11-20 46 views
4

我有了创建表的语句序列,这样的.sql文件:如何仅从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 

应该只创建表TAB3TAB67

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

+0

它必须是.sql文件吗?或者你可以使用shell脚本 - 因为这对我来说似乎是最简单的方法。 – Benubird 2010-11-29 13:16:17

回答

1

假设表结构相同,根据您的ll和ul,最好在循环中创建执行动态sql语句的&。例如(在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 

如果表结构不同,那么只需在每个create周围放一个if语句。

+0

表结构不同。这就是为什么我没有把他们放在首位的循环中。 – Lazer 2010-11-20 17:18:53

2
  1. 使用associative array, 和插入数组中的所有查询以下列方式:

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; 

我对任何语法错误的遗憾。

+0

-1不是很有帮助,这是甲骨文 – 2010-11-29 06:16:07

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; 
+0

我想你的意思是命名后,你的BEGIN all_tabs(1)... all_tabs(2)... all_tabs(3)等 – 2010-11-26 10:22:43

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; 
/
0

一个黑客的方法来做到这一点是使用C预处理器和#if指令包含或不baed你在命令行中定义了一些宏每个语句。然后运行预处理文件而不是原始文件。