一次将SQL脚本执行到oracle db一个语句

时间:2012-12-06 14:31:04

标签: java python sql regex oracle

假设我有一个如下所示的sql脚本:

--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)如果字符串以create | alter | drop | declare开头,则从该字符串的开头到分号后面跟一个新行,然后是正斜杠(这里的键是在匿名阻止的情况下,我们必须忽略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 db)

如果正则表达式不适用于此任务,则不必是正则表达式。我的最终目标是拆分每个语句并单独运行,这样我就可以捕获任何出现的错误并优雅地处理它们。

2 个答案:

答案 0 :(得分:2)

Pseudeo-Code,未经测试,只是为了表明这个想法:

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
}

答案 1 :(得分:-2)

根据您的目标,您可以在每个语句末尾插入以下命令后将文件提供给SQL * Plus:

pause Press any key to proceed