如何将任意二进制数据插入VARCHAR列?

时间:2016-06-15 20:51:02

标签: mysql sql

我有一个带有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语句,允许我插入任意字节序列?

3 个答案:

答案 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_preparemysql_stmt_execute)使用预先准备好的语句更有可能实现这样的恶作剧,提供无效的UTF8编码作为字符串绑定的值参数。 (客户端的责任实际上是为绑定参数提供有效值。)

答案 2 :(得分:-2)

您应该事先对您的值进行base64编码,这样您就可以用它生成一个有效的SQL:

UPDATE DataTable SET Data = from_base64('mybase64-encoded-representation-of-my-value') WHERE Id = 1;