比较使用不同编码存储的相同值

7 浏览
0 Comments

比较使用不同编码存储的相同值

这个问题不是PHP字符串比较两种不同编码类型的重复,因为我的问题需要一个SQL解决方案,而不是一个PHP解决方案。


背景 ► 一个博物馆有两个使用相同字符集和排序规则(engine=INNODB charset=utf8 collate=utf8_unicode_ci)的数据库,由两个不同的PHP系统使用。每个PHP系统以不同的方式存储相同的数据,下面的图像是一个示例:

enter image description here

已经以这种方式存储了大量的数据,并且两个系统都正常工作,所以我不能更改PHP编码或数据库。其中一个系统处理售票处的销售,另一个系统处理网站的销售。

问题 ► 我需要比较右列(tipo_boleto_tipo)和左列(tipo),以便获取左表中另一列的值(图像中看不到),但是由于相同的值存储方式不同,我得不到结果,例如,当我搜索"Niños"时,找不到,因为它被存储为"Niños"(西班牙语中的"children")。我尝试通过PHP使用utf8_encodeutf8_decode来解决,但速度太慢,所以我认为最好只使用SQL。这些数据将用于变动时间段内的销售统一报告(售票处和网络销售),需要比较数十万行数据,这就是为什么使用PHP会如此缓慢的原因。

问题 ► 是否有类似于MYSQL的utf8_encodeutf8_decode的东西,允许我匹配两个列的等价值?欢迎任何其他建议。

下面是我的当前代码(没有结果):

            数据库    表      列
               ▼          ▼          ▼
    SELECT boleteria.tipos_boletos.genero            ◄ 所需列。
      FROM boleteria.tipos_boletos                   ◄ 存在怪异字符的数据库。
INNER JOIN venta_en_linea.ventas_detalle             ◄ 存在正确字符的数据库。
        ON venta_en_linea.ventas_detalle.tipo_boleto_tipo = boleteria.tipos_boletos.tipo
     WHERE venta_en_linea.ventas_detalle.evento_id='1'
       AND venta_en_linea.ventas_detalle.tipo_boleto_tipo = 'Niños'

ON venta_en_linea.ventas_detalle.tipo_boleto_tipo = boleteria.tipos_boletos.tipo这一行永远不会起作用,因为两个值是不同的("Niños"对比"Niños")。

0
0 Comments

问题的原因是应用程序将数据存储到名为boleteria的数据库时,没有正确地使用UTF-8编码。数据库列的字符集指的是MySQL如何解释字符串,但是应用程序仍然可以使用其他字符集进行写入。

从您的示例中无法确定不正确的字符集是什么,但假设它是Latin-1,您可以将其转换为Latin-1(使其“正确”),然后再转换回“实际”的UTF-8:

SELECT 1
FROM tipos_boletos, ventas_detalle 
WHERE CONVERT(CAST(CONVERT(tipo USING latin1) AS binary) USING utf8) 
      = tipo_boleto_tipo COLLATE utf8_unicode_ci

我在PHP应用程序中经常遇到这个问题,这些应用程序从一开始就没有小心地使用UTF-8字符串。如果您发现性能太慢,并且需要频繁进行转换,并且无法更新错误写入数据的应用程序,您可以向tipos_boletos表添加一个新的列和触发器,并在添加或编辑记录时进行即时转换。

它起作用了,它起作用了,Matt,你是最棒的!!!只是为了未来来访者,我遇到了错误“Illegal mix of collations...”,我通过在where的末尾添加COLLATE utf8_unicode_ci来解决了这个问题(从stackoverflow.com/a/11770234/3298930偷来的)。非常非常感谢你,伙计!

0