我有一个带有VARCHAR(100)
列的MySQL表,使用utf8_general_ci
归类。
我可以看到此列包含任意字节序列的行(即包含无效UTF8字符序列的数据),但我无法弄清楚如何编写允许此类数据的UPDATE或INSERT语句输入
例如,我尝试过以下方法:
UPDATE DataTable SET Data = CAST(BINARY(X'16d7a4fca7442dda3ad93c9a726597e4') AS CHAR(100)) WHERE Id = 1;
但我收到错误:
Incorrect string value: '\xFC\xA7D-\xDA:...' for column 'Data' at row 1
如何编写绕过目标列排序规则的INSERT或UPDATE语句,允许我插入任意字节序列?
答案 0 :(得分:0)
您是否考虑过使用其中一种Blob数据类型而不是varchar?我相信这会从你的用例中消除很多痛苦。
编辑:或者,有HEX and UNHEX函数,MySQL支持。十六进制采用str或numeric参数,并将参数的十六进制表示形式返回为字符串。 Unhex做反过来;取十六进制字符串并返回二进制字符串。
答案 1 :(得分:0)
简短的回答是,不应该将具有无效UTF8字符的值插入声明为使用UTF8字符集的VARCHAR列中。
这是MySQL的设计目标,禁止无效值。当试图这样做时,MySQL将返回错误或警告,或者(更宽松地?)在遇到的第一个无效字符时静默截断提供的值。
更常见的各种字符问题是MySQL在不需要字符集转换时执行字符集转换。
但您报告的问题是无效字符已插入UTF8列。就好像提供了latin1(ISO-8859)编码,并且需要进行字符集转换,但不执行。
至于解决这个问题......我相信在早期版本的MySQL中它是可能的。我相信可以将值转换为BINARY,然后在CONVERT( ... USING UTF8)
中转换,并且MySQL不会对字符集进行验证。我不知道当前的MySQL连接器是否还可以。
如果可能的话,那就是(IMO)连接器中的一个错误。
我能想到绕过字符集检查/验证的唯一方法是让MySQL服务器信任客户端,并确定不需要检查字符集。 (这也意味着MySQL服务器不会进行字符集转换,客户端对服务器说谎,客户端告诉服务器它正在提供有效的UTF8字符。
基本上,客户端会告诉服务器“嘿服务器,我将发送UTF8字符编码”。
服务器说“好的。我不会做任何字符转换,因为我们匹配。而且我只相信你发送的是有效的UTF8”。
然后客户端顽皮地笑了起来,“嘿,嘿,我撒谎。我实际上发送的字符编码是无效的UTF8”。
而且我认为使用旧学校的MySQL C API(mysql_stmt_prepare
,mysql_stmt_execute
)使用预先准备好的语句更有可能实现这样的恶作剧,提供无效的UTF8编码作为字符串绑定的值参数。 (客户端的责任实际上是为绑定参数提供有效值。)
答案 2 :(得分:-2)
您应该事先对您的值进行base64编码,这样您就可以用它生成一个有效的SQL:
UPDATE DataTable SET Data = from_base64('mybase64-encoded-representation-of-my-value') WHERE Id = 1;