【问题标题】:Getting result set from a statement block [duplicate]从语句块获取结果集[重复]
【发布时间】:2021-07-29 04:56:30
【问题描述】:

我有一个包含大量逻辑的庞大脚本,最后是 select statement,它返回最终结果。

许多人都知道 JDBC 不应该开箱即用地运行 SQL 脚本(带有多个语句),因此我将脚本包装到 begin ... end 块中,使其成为单个语句块,以便我可以一次性执行它。

一切似乎都很好......除了我无法从begin ... end 块中获取结果集(下面的代码打印“无数据”)。所以我不得不把脚本分成两部分——所有的逻辑(1)+最终的选择语句(2)。

val url = "jdbc:sqlserver://" + mssqlServer + ";integratedSecurity=true;"
val connMSSQL = java.sql.DriverManager.getConnection(url)

val qqq0 = """begin
             |
             |if object_id('tempdb..#ttt') is not null drop table #ttt
             |
             |create table #ttt(i int, v varchar(10))
             |
             |insert into #ttt
             |select 0, 'qwerty' union all select 1, 'hello'
             |
             |select 1 id, 0 value
             |
             |end""".stripMargin

val qqq = "select * from #ttt"

val stmt = connMSSQL.createStatement()
stmt.execute(qqq0)
if (stmt.getResultSet==null) println("No data")
val rs = stmt.executeQuery(qqq)

问题是 - 是否有任何方法可以从 begin ... end 块获取结果集?如果答案是否定的,那么我们将非常感谢您的解释。

PS。如果我将所有代码包装到过程 my_proc 中,我可以轻松获得结果,但在我的特定情况下,在 DB 中创建对象不是一个选项。

这样工作

val stmt1 = connMSSQL.createStatement()
stmt1.execute("my_db..my_proc")
val rs1 = stmt1.getResultSet

这样也行

val stmt2 = connMSSQL.createStatement()
val rs2 = stmt2.executeQuery("my_db..my_proc")

在这两种情况下,当代码与匿名块而不是过程一起使用时,记录集都等于 null。

PPS。不用说,如果将begin ... end块复制并粘贴到管理工作室并用F5运行它,它会毫无问题地返回结果。

更新

对我来说,这种行为仍然很奇怪,但幸运的是它只适用于 set nocount ongetMoreResults

但是...它仅适用于第一个语句。

因此,如果我将nocount 包含在原始 SQL 脚本中,那么对于下面的代码

val stmt1 = connMSSQL.createStatement()
println(stmt1.execute(qqq0))
println(stmt1.getMoreResults())
if (stmt1.getResultSet==null) println("No data") else println("Yes data")

val stmt2 = connMSSQL.createStatement()
println(stmt2.execute(qqq0))
println(stmt2.getMoreResults())
if (stmt2.getResultSet==null) println("No data") else println("Yes data")

输出如下

false
true
Yes data
false
false
No data

现在的问题是如何让它正常工作,而不仅仅是第一个语句。

更新 2

版主提供的链接均未解释 createStatement 的意外行为。

【问题讨论】:

  • 尝试将SET NOCOUNT ON; 添加为脚本中的第一条语句。

标签: java sql sql-server scala jdbc


【解决方案1】:

好吧,正如我在问题中所写,在createStatement 的情况下,它仅适用于第一个 JDBC 语句并且在调用 getMoreResults 之后。

对于prepareStatement,它适用于所有呼叫。我使用executeQueryexecute + getResultSet 也没关系。

val stmt1 = connMSSQL.prepareStatement(qqq0)
if (stmt1.executeQuery()==null) println("No data") else println("Yes data")

val stmt2 = connMSSQL.prepareStatement(qqq0)
println(stmt2.execute)
if (stmt2.getResultSet()==null) println("No data") else println("Yes data")

输出

Yes data
true
Yes data

所以解决方案是 - 使用 prepareStatementset nocount on

【讨论】:

    【解决方案2】:

    试试CallableStatementregisterOutParameter

    val url = "jdbc:sqlserver://" + mssqlServer + ";integratedSecurity=true;"
    val connMSSQL = java.sql.DriverManager.getConnection(url)
    
    val qqq0 = """begin
                 |
                 |if object_id('tempdb..#ttt') is not null drop table #ttt
                 |
                 |create table #ttt(i int, v varchar(10))
                 |
                 |insert into #ttt
                 |select 0, 'qwerty' union all select 1, 'hello'
                 |
                 |select 1 id, 0 value
                 |
                 | ? := 123;
                 |
                 |end""".stripMargin
    
    // val qqq = "select * from #ttt"
    
    // val stmt = connMSSQL.createStatement()
    // stmt.execute(qqq0)
    // if (stmt.getResultSet==null) println("No data")
    // val rs = stmt.executeQuery(qqq)
    
    try (CallableStatement stmt = connMSSQL.prepareCall(qqq0)) {
        stmt.registerOutParameter(1, Types.INTEGER);
        stmt.execute();
        System.out.println(stmt.getInt(1)); // Display "123";
    }
    

    【讨论】:

    • 因此我需要一个记录集。请检查原始问题的更新。我设法让它工作,但不幸的是它只适用于第一次执行。
    猜你喜欢
    • 1970-01-01
    • 2017-03-26
    • 2017-04-29
    • 2013-07-28
    • 2020-01-15
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 2013-11-03
    相关资源
    最近更新 更多