2012-12-06 42 views
4

比方說,我有一個SQL腳本,看起來像這樣:執行SQL腳本到Oracle數據庫一個聲明同時

--split statement 1 
ALTER TABLE abs 
    ADD (make VARCHAR2(2 byte), 
    model varCHAR2(12 BYTE), 
    built_on DATE, 
    serial varchar2(123 BYTE)); 
    /

    --split statement 2 
    declare 
    begin 
     null; 
    end; 
    /

    --split statement 3 
    insert into test (v,a,c) 
    values ('1','jjoe;','232'); 

    --split statement 4 
    create or replace function BLAH_BLAH(i_in varchar2) 
    as 
     l_one varchar2(12); 
     l_two varchar2(12); 
     l_three varchar2(12); 
    begin 
     l_one := 1; 
     l_two := 3; 

     insert into test (v,a,b) 
     values ('1','jjoee;','232'); 


    exception when no_data_found then 
     l_three := 3; 


    end; 
    /

基本上腳本可以有DML,DCL,DDL和匿名塊。我希望能夠分開每個陳述並單獨執行它們,但當然爲了它們的出現。

我想用正則表達式的,我相信邏輯必須是這樣的:

1)如果字符串以創建開始|修改|下降|宣佈,從開始得到一切該字符串到分號後面跟着一個換行符,然後是一個正斜槓(這裏的關鍵是在匿名塊的情況下,我們必須忽略DML直到我們到達最後)。

2)如果字符串以insert | delete | update | merge開始(如果我們已經在適用於需求1的塊中,則再次忽略),從該字符串的開頭向下到分號接着是一條沒有斜線的新線。

到目前爲止,我想出這個在Python:

sql_commands = re.split('(?i)(((create|alter|drop|merge)+)(?m);(\s*)\n(\s*))|(;(\s*)\n(\s*)/)',sql_script) 

,但每次我嘗試與其他要求的正則表達式開始到不行前進(實際上輸出是一種時髦因爲它是),並變得足夠複雜,讓我迷路英寸

我想這樣做在Python或Java(Java,我想,實際上是首選,因爲這是一個Oracle數據庫)

這並不一定是一個常規表達式,如果正則表達式不是真的完成這個任務。我的最終目標是拆分每條語句並單獨運行,以便捕捉出現並正常處理它們的任何錯誤。

+0

因此,您將腳本作爲輸入,其中有多個調用,並且您想將它拆分,並分別調用每個部分? –

+0

完全正確。這裏的目標是,如果腳本的一部分失敗,我想要閃回更改或繼續運行腳本,具體取決於失敗。 –

回答

2

Pseudeo碼,沒有測試,只是爲了顯示這個想法:

while (line = readLine()) { 
    String cmdString = null; 
    if (line.beginsWith("create" || line.beginsWith("alter") ...) { 
     String previousLine = line; 
     while (line = readLine()) { 
      if (line.equals("/") && previousLine.endsWith(";")) { 
      executeSQL(cmdString); 
      break; 
      } 
      previousLine = line; 
      cmdString = cmdString + line; 
     } 
    } 
    if (line.beginsWith("insert" || line.beginsWith("update") ...) { 
     String previousLine = line; 
     while (line = readLine()) { 
      if (line.equals("\n") && previousLine.endsWith(";")) { 
      executeSQL(cmdString); 
      break; 
      } 
      previousLine = line; 
      cmdString = cmdString + line; 
     } 
    } 
    // skip others 
} 
+0

看起來很有希望,我已經把自己的頭埋在正則表達式中,所以我沒有想到這樣一個簡單的循環就能解決這個問題。我會測試這個並回復你 –

+0

這是很棒的東西,我將它轉換爲Python,並且它非常符合預期。需要剝離空白和製表符。還需要添加「cmdString = cmdString +行;」在「String previousLine = line;」下面捕捉進入第二個循環之前記錄的第一行。謝謝你。 –

+0

不客氣。我喜歡這種解決方案。比你嘗試的諸如Regex惡夢更可讀和更易維護。我敢打賭,執行速度更快。我前幾天看了一個很好的編程技巧:Allways代碼就好像維護你的代碼的人是一個知道你住在哪裏的連環殺手。 –

-2

根據你的目標,你可以在每個語句結尾插入了下面的命令後喂文件到SQL * Plus:

pause Press any key to proceed 
+0

恩,這並不能解決發現個人陳述的問題,這是他試圖解決的問題。 –

+0

非常正確的jschoen,我們已經使用SQL * Plus,但問題是sql * plus將繼續執行整個腳本,即使一個部分失敗。 –

+0

@Patrick 如果這是問題,那麼使用WHENEVER SQLERROR EXIT SQL.SQLCODE – colemar

相關問題