【问题标题】:What's the easiest way to parse multi-line SQL statements in Java?在 Java 中解析多行 SQL 语句的最简单方法是什么?
【发布时间】:2009-10-27 15:48:03
【问题描述】:

我对 Java 很陌生,但我正在寻找可以采用多行 SQL 语句的 Java 代码,例如从平面文件中说这样的话:

CREATE OR REPLACE TRIGGER REQ.TR_INPT_STAY_DETAI_SQ_BI
  BEFORE INSERT ON REQ.INPT_STAY_DETAIL
  FOR EACH ROW
BEGIN
  SELECT REQ.SQ_INPT_DETAIL.nextval INTO :new.INPT_STAY_DETAIL_PID from DUAL;
END;

然后将这些多行语句转换成这样的一行 SQL 语句(可能包含在此显示中),作为针对 Oracle 数据库的单个 JDBC 语句执行:

CREATE OR REPLACE TRIGGER REQ.TR_INPT_STAY_DETAI_SQ_BI BEFORE INSERT ON REQ.INPT_STAY_DETAIL FOR EACH ROW BEGIN SELECT REQ.SQ_INPT_DETAIL.nextval INTO :new.INPT_STAY_DETAIL_PID from DUAL; END;

我尝试使用多个 BufferedReader 和/或使用 mark() 方法来执行此操作,但我似乎无法让它工作。

问题似乎是长语句末尾的分号和END;声明。

您认为最简单的方法是什么?


我想我取得了一些进展,但是如果同一个 SQL 输入文件也有更简单的 SQL 命令,比如:

DROP TABLE TABLE.NAME_HERE;

他们会在我这里的第一个条件下失败:

if ( !thisLine.startsWith("END;") && !thisLine.equals("/") ) {
    sqlBuf.append(thisLine).append(" ");
    statementReady = false;
}
else if (thisLine.startsWith("END;")) {
    sqlBuf.append(thisLine).append(" ");
    statementReady = true;
}
else if (thisLine.equals("/")) {
    statementReady = true;
}
else { }

我稍后会在运行 .execute 之前检查 statemendReady 变量。

【问题讨论】:

  • 你能贴出你尝试使用失败的代码吗?
  • 这就像 200 行左右的可怕 Java。可以吗?
  • 这可能有点多。只需显示您实际读取和连接数据的位置的 sn-ps
  • 如果你有一个充满sql命令的文件,并且你需要一次处理一个,这是一个非常不同的问题。您可能需要澄清此文件中的命令以及您需要的解决方案的通用性。
  • 我想我认为多行语句会更难理解,而 1 行语句会很容易...... SQL 文件可能包含带有 END 的触发器定义;和/,它也可能有简单的语句,就像上面一样。其中任何一个都可以在 1 行或多行。我不确定我是否可以严格执行给我的文件格式。我希望我能处理任何格式,但我想这是问题的症结所在......

标签: java sql oracle jdbc


【解决方案1】:

只需读入每一行,然后使用 StringBuilder 附加它们,但是,不要附加任何具有 End; 的行,因为您的查询不需要它。

如果文件中有Go,你也应该忽略它。

然后你可以把 StringBuilder 变成一个 String 就可以了。

记得在每行之间留一个空格。

有关从文件中读取多行的更多信息,您可以查看: http://www.roseindia.net/java/beginners/java-read-file-line-by-line.shtml

重要的部分是:

StringBuilder buf = new StringBuilder();
while ((strLine = br.readLine()) != null)   {
       if (!strLine.startsWith("End"))
          buf.append(strLine).append(" ");
    }

【讨论】:

  • +1 - rziegler72,我强烈推荐这种方法(我正打算这样做),因为它运行良好且非常有效。由于您是 Java 新手,请确保关闭所有作者或读者。
  • +1 - 这应该可以,但不要删除 'END;'线。如果有“BEGIN”行,则需要该行。 Oracle 中 GO 的等价物是一个带有单个“/”的行,如果存在,则必须将其删除。
  • 谢谢大家,我会试试这样的,看看我能得到什么。在这一点上,ANTLR 似乎有点超出我的想象。
  • @Vincent - 显然,我不知道发送'End;'会很重要。我在 SQL Server 上的使用时间太长了(因此使用了“GO”)。
  • 我在上面编辑了我的问题以显示我尝试过的内容,所以它越来越接近,但仍然没有抓住每一个案例......
【解决方案2】:

一种方法可能是使用 ANTLR。它有oracle SQL grammer,这肯定有助于解决 SQL 语法的许多极端情况。

【讨论】:

    【解决方案3】:

    您能否预处理文件,以便通过在换行符上使用搜索和替换并在语句末尾添加换行符来减少换行符,那么您读取的每一行都将是一个 sql陈述?

    (像sed 这样的Unix工具可以让这变得非常简单)

    否则,James 是对的(只要打败我就行了)。

    【讨论】:

      【解决方案4】:

      Oracle SQL 语句的语法相当复杂,不能用这种字符串匹配算法轻松地从脚本文件中获取 SQL 语句或 PLSQL 存储过程。您需要的是一个可以正确解析整个 SQL 脚本的完全正常工作的 SQL 解析器,这里是 an article 向您展示如何在 general sql parser 的帮助下做到这一点。

      【讨论】:

        猜你喜欢
        • 2011-12-22
        • 2022-02-04
        • 2023-03-17
        • 2012-07-28
        • 1970-01-01
        • 2011-02-08
        • 1970-01-01
        • 2013-07-06
        • 1970-01-01
        相关资源
        最近更新 更多