4

假设我有一个如下所示的 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)

如果 regex 不能真正完成这项任务,这不一定是正则表达式。我的最终目标是拆分每个语句并单独运行它,这样我就可以捕获出现的任何错误并优雅地处理它们。

4

2 回答 2

2

伪代码,未经测试,只是为了展示这个想法:

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
}
于 2012-12-06T15:13:43.737 回答
-2

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

pause Press any key to proceed
于 2012-12-06T14:56:02.343 回答