比较使用不同编码存储的相同值
比较使用不同编码存储的相同值
这个问题不是PHP字符串比较两种不同编码类型的重复,因为我的问题需要一个SQL解决方案,而不是一个PHP解决方案。
背景 ► 一个博物馆有两个使用相同字符集和排序规则(engine=INNODB charset=utf8 collate=utf8_unicode_ci
)的数据库,由两个不同的PHP系统使用。每个PHP系统以不同的方式存储相同的数据,下面的图像是一个示例:
已经以这种方式存储了大量的数据,并且两个系统都正常工作,所以我不能更改PHP编码或数据库。其中一个系统处理售票处的销售,另一个系统处理网站的销售。
问题 ► 我需要比较右列(tipo_boleto_tipo
)和左列(tipo
),以便获取左表中另一列的值(图像中看不到),但是由于相同的值存储方式不同,我得不到结果,例如,当我搜索"Niños"时,找不到,因为它被存储为"Niños"(西班牙语中的"children")。我尝试通过PHP使用utf8_encode
和utf8_decode
来解决,但速度太慢,所以我认为最好只使用SQL。这些数据将用于变动时间段内的销售统一报告(售票处和网络销售),需要比较数十万行数据,这就是为什么使用PHP会如此缓慢的原因。
问题 ► 是否有类似于MYSQL的utf8_encode
或utf8_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")。
问题的原因是应用程序将数据存储到名为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偷来的)。非常非常感谢你,伙计!