【问题标题】:groovy.sql.Sql.asSql In Groovy SQL please do not use quotes around dynamic expressionsgroovy.sql.Sql.asSql 在 Groovy SQL 中请不要在动态表达式周围使用引号
【发布时间】:2022-01-17 20:36:40
【问题描述】:

我在 Grails 中有这样的查询:

 def strQuery = """select date_trunc('${type}', range) as range, sum(total_count) as total_count from connector_message_statistic  
                where range >= '${startDate}' and range < '${endDate}'
                group by date_trunc('${type}', range)                
            order by 1 asc;"""

我在 catalina 日志中有这个警告:

groovy.sql.Sql.asSql In Groovy SQL please do not use quotes around dynamic expressions (which start with $) as this means we cannot use a JDBC PreparedStatement and so is a security hole. Groovy has worked around your mistake but the security hole is still there. The expression so far is: select date_trunc('?', range) as range, is_internal,direction, sum(total_count) as total_count, sum(total_message_size) as total_message_size

我应该如何摆脱它?问题是动态 date_trunc 参数。 当我尝试这样的事情时:

select date_trunc(:type, range) ....... group by date_trunc(:type, range)
sql.eachRow(strQuery, type: type)

然后我得到这个异常:

ERROR: column "connector_message_statistic.range" must appear in the GROUP BY clause or be used in an aggregate function Position: 23

如何重写这样的查询以避免这些警告?

【问题讨论】:

    标签: grails groovy


    【解决方案1】:

    一般来说,您应该使用参数化查询,而不是像您这样的查询。这样,Hibernate 或 Groovy SQL 可以根据参数类型正确地装箱。

    我会这样查询:

    def result = SomeDomain.executeQuery( 'select date_trunc(:type, range) as range, sum(total_count) as total_count from connector_message_statistic  
               where range >= :startDate and range < :endDate
               group by date_trunc( :type, range)                
               order by 1 asc", [ type:type, startDate:startDate, endDate:endDate ] )
    

    您也可以使用positional 参数:

    def result = SomeDomain.executeQuery( 'select date_trunc(?, range) as range, sum(total_count) as total_count from connector_message_statistic  
               where range >= ? and range < ?
               group by date_trunc( ?, range)                
               order by 1 asc", [ type, startDate, endDate, type ] )
    

    【讨论】:

    • 看起来这些查询将包含文字 'type''startDate''endDate' 等作为条件值,而不是具有这些名称的变量的值用于生成条件.是这个意图吗?
    • 自我之前的评论以来,答案已经更新。我还没有运行代码,但现在看起来可能更好。谢谢!
    • 当我尝试这个时:strQuery = """select date_trunc(:type, range) as range, is_internal,direction, sum(total_count) as total_count, sum(total_message_size) as total_message_size from connector_message_statistic where range >= '${startDate}' and range
    • 我收到异常:列“connector_message_statistic.range”必须出现在 GROUP BY 子句中或用于聚合函数中
    • 尝试将此处的 range 别名 date_trunc(:type, range) as range 重命名为 esle
    【解决方案2】:

    injecteer 的评论帮助了我,这段代码现在可以工作了:

      strQuery = """select date_trunc(:type, range) as rangenew, is_internal,direction, sum(total_count) as total_count, sum(total_message_size) as total_message_size 
                        from connector_message_statistic 
                        where range >= :startDate::timestamp and range < :endDate::timestamp 
                        group by rangenew, is_internal,direction
                        order by 1 asc;"""
        sql.eachRow(strQuery, [type: type, startDate: startDate, endDate: endDate]
    

    我重命名了 date_trunc 中的字段名,并在 group by 子句中添加了字段

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-28
      • 1970-01-01
      • 1970-01-01
      • 2011-06-18
      • 1970-01-01
      • 2017-07-09
      • 1970-01-01
      • 2013-09-08
      相关资源
      最近更新 更多