【问题标题】:Groovy SQL named list parameterGroovy SQL 命名列表参数
【发布时间】:2018-03-10 06:27:09
【问题描述】:

我想在 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
}

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

map.keySet().join(',')
map.keySet().toListString()
map.keySet().toList()
map.keySet().toString()

地图使用字符串作为键

Map<String, String> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);

另外,我没有收到错误消息。我只是没有打印出任何结果集。

【问题讨论】:

  • 试试[spaceid: 1234, title: "'" + map.keySet().join("','") + "'" ]

标签: sql groovy named-parameters


【解决方案1】:

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

从逻辑上讲,您使用的是谓词,例如

 title = 'value1,value2,value3'

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

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

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

 title in (:key1, :key2, :key3)

无论如何,这样的工作都很好:

数据

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;

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
}

结果

select contentid from content where spaceid = :spaceid and title in (:key1,:key2)
1
2

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

注意

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

【讨论】:

  • 感谢您的帮助!我必须添加以从键中删除空格和破折号,以使您的解决方案对我有用 .replaceAll("\\s","").replaceAll("-","")
  • 这看起来只是在做花哨的字符串连接,而不是实际使用参数化的 SQL 语句,这样不会仍然容易受到 SQL 注入的攻击吗?
  • Nope @nbrooks 这种方法使用(动态创建的)绑定变量。在 Hybernate 中使用相同的概念。
【解决方案2】:

它对我进行了一些调整,我已将地图添加为第二个参数。

def sql = Sql.newInstance("jdbc:mysql://localhost/databaseName", "userid", "pass")
    Map<String,Long> mapProduitEnDelta = new HashMap<>()
    mapProduitEnDelta['key1'] = 1
    mapProduitEnDelta['key2'] = 2
    mapProduitEnDelta['key3'] = 3
    produits : sql.rows("""select id, reference from Produit where id IN (${mapProduitEnDelta.keySet().collect{":$it"}.join(',')})""",mapProduitEnDelta),

显示 id 为 1、2、3 的 3 个产品(列 + produit 表中的值)

【讨论】:

    猜你喜欢
    • 2012-10-26
    • 2011-11-16
    • 1970-01-01
    • 1970-01-01
    • 2014-07-31
    • 1970-01-01
    • 1970-01-01
    • 2013-08-02
    • 1970-01-01
    相关资源
    最近更新 更多