如何在groovy中使用相同的代码执行查询和DML语句?

Jak*_*sel 12 sql groovy jdbc

我是SQL Fiddle的作者.这些知识可能有助于构建这个问题:

我正在尝试编写一些Groovy代码,它将在我的数据库中执行任意查询/ DML代码.基于我对Groovy Sql API的阅读,所有这些函数都需要非常特别的东西.例如,"eachRow"期望返回结果集; 如果没有返回(例如,在UPDATE语句的情况下),那么使用它将引发错误.我可以用任何类型的语句调用"execute",但是在使用它时我无法获取SELECT语句的结果集(这绝对是一个要求).

在这一点上,我想我可能不得不放弃Groovy的Sql库,转而采用一些低级的JDBC实现.我想这可能是一种耻辱,但如果有必要,我愿意去那里.不过,我非常希望尽可能保持Groovy-esqe.我该怎么做呢?

dma*_*tro 3

看一下execute()返回 的方法的种类boolean。根据文档返回类型:

true如果第一个结果是一个ResultSet对象;如果是更新计数或没有结果,则为 false

示例中已经提到了 CREATE、DROP 和 INSERT。我希望更新也能以同样的方式工作。

对于 SELECT,必须检查该标志是否存在ResultSet。如果是,则可以触发第二个查询来获取行。例如:

//If statement qualifies for select statements
//because .execute() will return true if there is a ResultSet
//present. It will be false for CREATE, UPDATE and DROP.
if( sql.execute("select name from Foo") ) {

    //Fire the second query to get the rows in case of SELECT query
    result = sql.rows "select name from Foo"
}

return result
Run Code Online (Sandbox Code Playgroud)

更新
如果出于性能原因担心执行查询两次,则可以尝试以下方法:

def queryString = "update Foo set name = 'hello' where name = 'baz'"

try {
    sql.query queryString, { ResultSet rs ->
        //Result set returned for select query only
        //For all other cases exception is thrown
    }
} catch( java.sql.SQLException ) {
    //Throws exception for any other type of query
    //By now you should be smart enough exception is not 
    //thrown for any other cause.

    sql.execute queryString
}
Run Code Online (Sandbox Code Playgroud)

  • @grantmc 例如公用表表达式(`WITH alias (....) SELECT`)(由 SQL Server 支持,[Firebird](http://www.firebirdsql.org/file/documentation/reference_manuals/reference_material/html/ langrefupd25-select.html#langrefupd25-select-cte)、Oracle、PostgreSQL 等) (4认同)
  • @dmahapatro 这是一个相当幼稚的解决方案:其他一些语句类型也能够返回行;并且并非所有 select 语句都以“SELECT”开头。 (3认同)