假设我有一个如下所示的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)
如果正则表达式不适用于此任务,则不必是正则表达式。我的最终目标是拆分每个语句并单独运行,这样我就可以捕获任何出现的错误并优雅地处理它们。
答案 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