【问题标题】:Ruby: compare two strings in terms of database collation utf8_general_ciRuby:根据数据库排序规则比较两个字符串 utf8_general_ci
【发布时间】:2016-04-05 05:23:40
【问题描述】:

我也有类似here 的问题。但由于没有足够的学分所以无法在那里发表评论,所以产生了新的问题。

不管怎样,问题是:

我想比较 ruby​​ 中的两个字符串,方法与 mysql 类似 将两个字符串与排序规则 utf_general_ci 进行比较。

详细来说,当在 db 中选择排序规则 utf_general_ci 时,在执行查询时,mysql 对待 'a' and 'ä'same。由于我想要批量插入,因此我将所有名称(带有 utf_general_ci 排序规则的列)拉入 ruby​​ 脚本,并在不存在名称的情况下进行插入语句。但是在ruby 的比较过程中,'a' and 'ä' 这样的字符会被处理为different。但我希望在 utf_general_ci 排序规则的情况下,以类似 mysql 的方式实现比较。

在旧问题中,有一个使用 'iconv' 的答案,在 1.9.3 之后已弃用。所以我认为应该使用String#encode 来做同样的事情。但找不到复制该行为的确切方法。

【问题讨论】:

  • 为什么不简单地发出一个 MySQL 命令来进行比较?
  • @RickJames 是的,我可以发出 MySQL 命令首先搜索表中是否存在,如果不存在则插入。但这需要很多时间,因为我有大量数据。所以这就是为什么我试图形成一批插入语句然后上传到 MySQL 数据库。
  • INSERT ... ON DUPLICATE KEY UPDATE ... 避免了在插入之前检查行是否存在的需要。
  • 但是对于每个条目,我都想避免“插入”查询,因为它需要很多时间。
  • 但是SELECT 必须花时间进行检查。通过结合检查和插入/更新,它实际上节省了时间。如果您可以显示您现在的查询,也许我可以更清楚(或可能是错误的)。

标签: mysql ruby-on-rails ruby database collation


【解决方案1】:

AFAIK,目前在 ruby​​ 中没有直接的方法。另一方面,人们可以简单地用手来做。忍者的方法是为此使用icu 库。

结果你可能想要最简单的方法,唯一的目标是比较字符串,可以从摆脱重音开始。有两种可能的重音符号:combining diacriticallatin supplement。后者是 Latin1/ISO-8859-1 编码的遗留物。

摆脱组合变音符号很容易:

▶ "lätin1, cömbined".gsub(Regexp.new(("\u0300".."\u036f").to_a.join('|')), '')
#⇒ "lätin1, combined"

好的,这是最简单的部分。不幸的是,没有直接的方法可以将传统的 latin1 字符映射到它们的非重音等价物,因此需要自己介绍它:

▶ substs = "ÀÁÂÃÄÅ".split(//).product(['A']).to_h
# for the sake of focusing on the problem, the other symbols are dropped

现在可以这样比较:

▶  "lÄtin1, cömbined".gsub(Regexp.new(("\u0300".."\u036f").to_a.join('|')), '')
                     .gsub(Regexp.new(substs.keys.join('|')), substs)
#⇒ "lAtin1, combined"

因此,两个字符串可能会被“dediacritized”,然后进行比较。

请注意,我承认这种方法是错误的。应该使用与icu library 的正确绑定,但是当您了解自己在做什么并以最小的努力开箱即用时,上述方法就可以解决问题。

【讨论】:

    猜你喜欢
    • 2011-07-18
    • 1970-01-01
    • 2011-02-07
    • 1970-01-01
    • 2011-05-11
    • 1970-01-01
    • 2012-09-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多