Groovy SQL 命名列表参数

Cap*_*ngo 0 sql groovy named-parameters

我想在 SQL 查询中使用 Map 的键集作为列表参数:

query = "select contentid from content where spaceid = :spaceid and title in (:title)"
sql.eachRow(query, [spaceid: 1234, title: map.keySet().join(',')]) {
    rs ->
        println rs.contentid
}
Run Code Online (Sandbox Code Playgroud)

我可以使用单个值,但不能使用集合或列表。这是我到目前为止所尝试过的:

map.keySet().join(',')
map.keySet().toListString()
map.keySet().toList()
map.keySet().toString()
Run Code Online (Sandbox Code Playgroud)

地图使用字符串作为键

Map<String, String> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
Run Code Online (Sandbox Code Playgroud)

另外,我没有收到错误。我只是没有打印任何内容,就像有一个空结果集一样。

Mar*_*ber 5

你的方法不会给出预期的结果。

从逻辑上讲,您正在使用诸如

 title = 'value1,value2,value3'
Run Code Online (Sandbox Code Playgroud)

这就是为什么你没有得到异常但也没有数据的原因。

快速搜索提供了一些证据,表明在 Groovy SQL 中可以将集合映射到 IN 列表。请检查这里和这里

因此,您很可能必须以适当的长度定义 IN 列表并分配数组中的值。

 title in (:key1, :key2, :key3)
Run Code Online (Sandbox Code Playgroud)

不管怎样,像这样的东西工作得很好:

数据

create table content as 
select 1 contentid, 1 spaceid, 'AAA' title from dual union all
select 2 contentid, 1 spaceid, 'BBB' title from dual union all
select 3 contentid, 2 spaceid, 'AAA' title from dual;
Run Code Online (Sandbox Code Playgroud)

Groovy 脚本

map['key1'] = 'AAA'
map['key2'] = 'BBB'

query = "select contentid from content where spaceid = :spaceid and title in (${map.keySet().collect{":$it"}.join(',')})"
println query
map['spaceid'] = 1
sql.eachRow(query, map) {
    rs ->
        println rs.contentid
}
Run Code Online (Sandbox Code Playgroud)

结果

select contentid from content where spaceid = :spaceid and title in (:key1,:key2)
1
2
Run Code Online (Sandbox Code Playgroud)

关键步骤是使用表达式动态准备具有绑定变量的正确名称的 IN 列表map.keySet().collect{":$it"}.join(',')

笔记

您可能还需要检查映射的大小并处理大于 1000 的情况,这是 Oracle 对单个 IN 列表的限制。

  • 不@nbrooks这种方法使用(动态创建的)绑定变量。Hybernate 中也使用了相同的概念。 (2认同)