当前位置: 首页 > 面试题库 >

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

郭浩穰
2023-03-14
问题内容

假设我有一个看起来像这样的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做到这一点(我想,鉴于这是一个Oracle数据库,实际上应该首选Java)

如果regex不能真正满足此任务,则不必是正则表达式。我的最终目标是分解每个语句并单独运行它,以便我可以捕获出现的任何错误并妥善处理它们。


问题答案:

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

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
}


 类似资料:
  • 问题内容: 我需要初始化一个常量HashMap,并希望在一行语句中完成它。避免这样的事情: 类似于目标C: 看了这么多,我还没有找到任何显示如何做到这一点的例子。 问题答案: 您可以使用 Double Brace初始化 ,如下所示: 作为警告,请参阅Java的效率效率“ Double BraceInitialization”,了解它可能带来的性能影响。

  • 我有一个对我来说很奇怪的问题。我实现了,将使用执行。问题是,它只执行一次。。。 下面是有用的代码(是一个枚举): 有趣的是,如果我用一些if-else语句替换这个开关,它工作得很好,这意味着这个Runnable按照我的要求每50毫秒执行一次。。! 下面是调度设置: 为什么用if-else语句每50ms调用一次Runnable,为什么用switch只调用一次?? 编辑:因为你问,这里是MenuEve

  • 问题内容: 如何将这些多个查询合并为一个(可以吗?) 顺便问一下,如果在完成所有查询后再执行mysql_close($ db),那会更好吗? 问题答案: 传递到作为第五个参数。 例: 当您使用mysql_fetch_ *或mysql_num_rows或mysql_affected_rows时,仅第一条语句有效。 例如,以下代码,第一个语句为INSERT,则无法执行mysql_num_rows和my

  • 本文向大家介绍oracle中得到一条SQL语句的执行时间的两种方式,包括了oracle中得到一条SQL语句的执行时间的两种方式的使用技巧和注意事项,需要的朋友参考一下 oracle中如果需要得到一条SQL语句的执行时间可以用如下2种方式

  • 问题内容: 在Oracle SQL Developer中输入SQL语句时,我注意到我有两个选择。我可以选择“运行语句”或“运行脚本”。尽管命名为“ Execute query”和“ Execute as script”,但在SQL Maestro中似乎也可以使用类似的选择。 两者之间到底有什么区别? 问题答案: 将在可排序的表格中为您提供所有结果的列表。它还将仅在光标(或突出显示)下运行该语句。运

  • 我正在将select查询传递给准备好的语句以获取记录列表。问题是,如果我将查询追加到insert或truncate table中,那么准备好的语句将执行所有查询。示例 如何限制sql查询只执行select查询,或者在Java中一次至少只执行一个查询。