如何在类似 PostgreSQL 的查询中正确转义双引号?

Posted

技术标签:

【中文标题】如何在类似 PostgreSQL 的查询中正确转义双引号?【英文标题】:How do I properly escape double quotes in a PostgreSQL like query? 【发布时间】:2021-11-11 18:44:22 【问题描述】:

我有一个 PostgreSQL 表,其中 YAML 数据存储在一个文本字段中。

我正在尝试查找密钥已从 false 更改为 true 的所有实例。

audited_changes: "hide_on_map"=>[false, true]

我可以通过对属性 hide_on_map 的类似查询轻松找到此键的所有实例

    [3] pry(main)> like_query = ActiveRecord::Base.send(:sanitize_sql_like, 'hide_on_map')
Audited::Audit.where(auditable_type: 'Lot').where('audited_changes like ?', "%#like_query%").count

   (245.8ms)  SELECT COUNT(*) FROM "audits" WHERE "audits"."auditable_type" = $1 AND (audited_changes like '%hide\_on\_map%')  [["auditable_type", "Lot"]]
=> 1710

但是,添加双引号会破坏这一点

[4] pry(main)> like_query = ActiveRecord::Base.send(:sanitize_sql_like, '"hide_on_map"')
Audited::Audit.where(auditable_type: 'Lot').where('audited_changes like ?', "%#like_query%").count

   (238.5ms)  SELECT COUNT(*) FROM "audits" WHERE "audits"."auditable_type" = $1 AND (audited_changes like '%"hide\_on\_map"%')  [["auditable_type", "Lot"]]
=> 0

更不用说完整的查询了

[5] pry(main)> like_query = ActiveRecord::Base.send(:sanitize_sql_like, '"hide_on_map"=>[false, true]')
Audited::Audit.where(auditable_type: 'Lot').where('audited_changes like ?', "%#like_query%").count

   (245.0ms)  SELECT COUNT(*) FROM "audits" WHERE "audits"."auditable_type" = $1 AND (audited_changes like '%"hide\_on\_map"=>[false, true]%')  [["auditable_type", "Lot"]]
=> 0

开始陷入转换为 JSONB 的困境,但这增加了一些我不想解决的额外复杂性。对格式正确的 LIKE 子句的建议?

对于那些询问,此查询的两个示例直接在 SQL 中的 psql 提示符下。

select count(*) from audits where audited_changes like '%"hide\_on\_map"%';

select count(*) from audits where audited_changes like '%\"hide\_on\_map\"%';

两者都产生 0 个结果。

【问题讨论】:

使用准备好的语句而不是 SQL 注入。 您在报价前尝试过使用 \ 吗? @TheImpaler 似乎没有什么不同。 @EmilienBaudet 我有。没有效果。我已经用 psql 直接在 SQL 中试过了,也没有用。 @max 这是我对存储数据的愚蠢误解。请参阅下面的答案和我的评论。 【参考方案1】:

问题是在 YAML 中没有一种独特的方式来表达该数据:

hide_on_map:
  - no
  - yes
"hide_on_map": [false, true]

都是您数据的有效 YAML 表示形式。

我担心您无法避免使用某些本机类型,或者至少是“压缩”JSON 文本(其中包含字面意义上的 '"hide_on_map":[false,true]'

【讨论】:

我觉得这里有两个选择;创建一个 JSON/JSONB 列并使用 YAML 解析器转换遗留数据并将其放回数据库中,或者接受数据不可查询的事实。 @rewritten 这是一个正确的答案,但我很愚蠢。在 Rails 控制台中查看数据时,它被转换为后来的表示形式,即我发布的那个,但存储的值处于您提到的状态。我没有正确检查原始审计数据是一个非常愚蠢的错误。感谢您的帮助,很抱歉浪费了您的时间!

以上是关于如何在类似 PostgreSQL 的查询中正确转义双引号?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 HTML 作为 PostgreSQL 插入查询中的值处理?

如何使用 Java 在 PostgreSQL 中安全地转义 SQL 的任意字符串

在没有 PreparedStatement 的情况下如何正确转义字符串?

如何转义 php mysqli 查询? [复制]

如何在 PostgreSQL JSONB 列中查询具有异构元素的嵌套数组

Postgresql 9.2 中在查询中调用函数的正确方法