2010-11-20 48 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你在命令行中定義了一些宏每個語句。然後運行預處理文件而不是原始文件。