错误 1366:将字符串插入 MariaDB 时字符串值不正确
Error 1366: Incorrect string value when inserting strings into MariaDB
我有具有索引 VARCHAR(10) NOT NULL COLLATE 'utf8mb3_general_ci'
类型的 MariaDB table。我在 Go 中有一个字符串,我将其切成 10 个字符,如果它更长,则插入 into/update 这个 table。我将字符串剪切为:
if len(value) > 10 {
value = value[:10]
}
现在我遇到了以 š
字符结尾的字符串的问题。 MariaDB 抛出错误:Error 1366: Incorrect string value: '\xC5'
。查找 unicode tables,这个字符表示为 \xc5\xa1
这让我相信字符串的切割不知何故使数据库无法消化字符串?
我想避免在我的代码中处理 utf8/unicode,因为这需要遍历所有数据库方法并处理所有字符串。而且我不认为这是必要的,因为我以前从未需要过它。所以我认为问题出在其他地方,但不确定在哪里。
我尝试将排序规则切换为 utf8mb4_general_ci
,但这也无济于事。
有趣的是,如果我直接使用 HeidiSQL 编辑该列,则字符串仅保存 fine.Which 让我相信这可能是驱动程序问题。我一如既往地使用 github.com/go-sql-driver/mysql
。所以我不希望出现问题,但谁知道呢...
which makes me believe the cutting of the string somehow makes the string indigestible for the database?
通过细分为 value[:10]
来切割字符串(并使用 len
测量长度)总是 如果您的程序有任何错误处理多字节字符的机会。这是因为对字符串进行索引操作是对其字节进行操作,这可能是也可能不是多字节编码的一部分。
如您所见,字符 š
在 UTF-8 中编码为 \xc5\xa1
。如果这两个字节出现在 value
字符串中索引 9
和 10
处,您的索引表达式 [:10]
会破坏数据。
字符集utf8mb3
和utf8mb4
仅将允许的UTF-8范围分别限制为3字节和4字节字符,但\xc5
不是有效的UTF- 8 开始,所以无论哪种方式都会被拒绝。
在 MariaDB 中,数据类型为 VARCHAR(N)
的列计数 个字符 (由排序规则指定)。您想要在第十个字符而不是第十个字节处剪切 value
字符串。
I would like to avoid handling utf8/unicode in my code
您已经通过将 MariaDB 归类声明为 utf8mb3
来承认 UTF-8。将代码中的输入数据正确处理为 UTF-8 是合乎逻辑的。要在第 n 个字符(或 rune
,在 Go 中代表一个 Unicode 代码点)处剪切,您可以使用类似的东西:
// count the runes
if utf8.RuneCountInString(value) > 10 {
// convert string to rune slice
chars := []rune(value)
// index the rune slice and convert back to string
value = string(chars[:10])
}
这不会破坏 UTF-8 编码,但是请记住,它会执行更多分配并且不考虑组合字符,例如当涉及到加入者 200D
时。
我有具有索引 VARCHAR(10) NOT NULL COLLATE 'utf8mb3_general_ci'
类型的 MariaDB table。我在 Go 中有一个字符串,我将其切成 10 个字符,如果它更长,则插入 into/update 这个 table。我将字符串剪切为:
if len(value) > 10 {
value = value[:10]
}
现在我遇到了以 š
字符结尾的字符串的问题。 MariaDB 抛出错误:Error 1366: Incorrect string value: '\xC5'
。查找 unicode tables,这个字符表示为 \xc5\xa1
这让我相信字符串的切割不知何故使数据库无法消化字符串?
我想避免在我的代码中处理 utf8/unicode,因为这需要遍历所有数据库方法并处理所有字符串。而且我不认为这是必要的,因为我以前从未需要过它。所以我认为问题出在其他地方,但不确定在哪里。
我尝试将排序规则切换为 utf8mb4_general_ci
,但这也无济于事。
有趣的是,如果我直接使用 HeidiSQL 编辑该列,则字符串仅保存 fine.Which 让我相信这可能是驱动程序问题。我一如既往地使用 github.com/go-sql-driver/mysql
。所以我不希望出现问题,但谁知道呢...
which makes me believe the cutting of the string somehow makes the string indigestible for the database?
通过细分为 value[:10]
来切割字符串(并使用 len
测量长度)总是 如果您的程序有任何错误处理多字节字符的机会。这是因为对字符串进行索引操作是对其字节进行操作,这可能是也可能不是多字节编码的一部分。
如您所见,字符 š
在 UTF-8 中编码为 \xc5\xa1
。如果这两个字节出现在 value
字符串中索引 9
和 10
处,您的索引表达式 [:10]
会破坏数据。
字符集utf8mb3
和utf8mb4
仅将允许的UTF-8范围分别限制为3字节和4字节字符,但\xc5
不是有效的UTF- 8 开始,所以无论哪种方式都会被拒绝。
在 MariaDB 中,数据类型为 VARCHAR(N)
的列计数 个字符 (由排序规则指定)。您想要在第十个字符而不是第十个字节处剪切 value
字符串。
I would like to avoid handling utf8/unicode in my code
您已经通过将 MariaDB 归类声明为 utf8mb3
来承认 UTF-8。将代码中的输入数据正确处理为 UTF-8 是合乎逻辑的。要在第 n 个字符(或 rune
,在 Go 中代表一个 Unicode 代码点)处剪切,您可以使用类似的东西:
// count the runes
if utf8.RuneCountInString(value) > 10 {
// convert string to rune slice
chars := []rune(value)
// index the rune slice and convert back to string
value = string(chars[:10])
}
这不会破坏 UTF-8 编码,但是请记住,它会执行更多分配并且不考虑组合字符,例如当涉及到加入者 200D
时。