【问题标题】:SQL query to select strings that contain a "Unit Separator" character用于选择包含“单位分隔符”字符的字符串的 SQL 查询
【发布时间】:2016-12-15 21:28:41
【问题描述】:

我有这样的桌子

我想获取那些记录哪些内容单元分隔符

我尝试了很多事情,但没有得到结果。我尝试了 char(31)0x1f 以及许多其他方法,但没有得到想要的结果。这是我尝试的查询

SELECT * FROM `submissions_answers` WHERE `question_id`=90 AND `answer` like '%0x1f%'

我该怎么做?请帮帮我..

【问题讨论】:

  • 我认为您需要在引号之外使用十六进制表示法,这就是dev.mysql.com/doc/refman/5.7/en/hexadecimal-literals.html 的建议。试试... LIKE CONCAT('%', 0x1f, '%')... LIKE CONCAT('%', x'1f', '%')
  • 该数据库列的字符集是什么?这与客户端的字符集相同吗?如果没有,可能会有一些字符集翻译正在进行。为了弄清楚该字符存储在数据库中的内容,我将使用 HEX 函数。
  • @spencer7593 列类型为文本,字符集为答案列的 utf8mb4_unicode_ci。

标签: mysql sql select character-encoding ascii


【解决方案1】:

问题

您尝试的表达式不起作用,因为 answer LIKE '%0x1f%' 正在寻找一个字面为 '0x1f' 的字符串 - 它不会转换为 ASCII 代码。

解决方案

应该起作用的这部分表达式的一些替代方案是:-

  1. answer LIKE CONCAT('%', 0x1F, '%')
  2. answer REGEXP 0x1F
  3. INSTR(answer, 0x1F) > 0

进一步考虑

如果这些都不起作用,那么可能还有其他可能性。您确定字符串中看到的字符实际上是0x1F 吗?我只是问,因为我尝试的第一件事是粘贴 ␟ 但事实证明 MySQL 将其视为 226 而不是 31 的十进制字符代码。不确定您使用的是哪个客户端,但如果 0x1F 字符在字符串中,它实际上可能不会出现在输出中。

演示

一些测试证明了上述几点:SQL Fiddle demo

【讨论】:

  • 答案列的列类型为文本,字符集为utf8mb4_unicode_ci。
  • 当我看你的 sql 演示时,它看起来不错,但是当我尝试“SELECT * FROM submits_answers WHERE ROUND ((LENGTH(answer) - LENGTH(REPLACE ( answer,REGEXP 0x1F, '') ) ) / LENGTH(REGEXP 0x1F) ) > 2" 它不起作用
  • REGEXP 0x1F 本身没有意义 - REGEXP 是一个采用 expression REGEXP pattern 形式的运算符,并返回一个布尔值,指示是否在表达式中找到指定的模式。试试这个:ROUND ( (LENGTH(answer) - LENGTH( REPLACE ( answer, 0x1F, '') ) ) / LENGTH(0x1F) )。但认为它应该是> 1 而不是> 2,除非您在答案中寻找两个这样的字符?请参阅this updated fiddle,这也解决了您的第一条评论。
【解决方案2】:

你可以使用:

SELECT * FROM submissions_answers WHERE question_id=90 AND instr(answer,char(31))>0

这里的关键字是INSTR MySQL 函数,which you can read about here。此函数返回子字符串 (char(31)) 在字符串 (answer) 中第一次出现的位置。

【讨论】:

  • 您能解释一下INSTR 的作用以及它是如何解决问题的吗?
  • @BillKarwin 如果人们查看手册,大多数 StackOverflow 问题都不会出现在这里,我可以并且很容易地研究手册,但我希望 Luis 添加一两句话来描述他所做的事情,如关于为什么此代码有效,仅代码答案相当无用,也没有传达任何学习信息
  • @Martin,很公平。我以为您是在问,因为您是众多不想查看文档的人之一。
  • @Luis Siquot 我尝试了您的查询,它可以工作,但是当我尝试这样做时,它不起作用-“SELECT * FROM submits_answers WHERE ROUND ( (LENGTH(answer) - LENGTH( REPLACE ( answer,char(31 ), '') ) ) / LENGTH(char(31)) ) > 2".
【解决方案3】:

另一种方式...

SELECT * FROM `submissions_answers`
    WHERE `question_id`=90
      AND HEX(`answer`) REGEXP '^(..)*1F'

正则表达式的解释:

  • ^ - 从开头开始匹配(answer
  • (..)* -- 匹配任意数量 (*) 的 2 字节事物 (..)
  • 然后匹配1F,美国的十六进制。

【讨论】:

  • 作为最有创意(非正统)的回答,我愿意 +1
【解决方案4】:

您可以将答案列转换为十六进制值,然后查找包含该十六进制字符串的值。

SELECT * FROM `submissions_answers`
WHERE HEX(`answer`) LIKE '%E2909F%'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多