【问题标题】:Error 1366: Incorrect string value when inserting strings into MariaDB错误 1366:将字符串插入 MariaDB 时字符串值不正确
【发布时间】:2022-01-20 16:34:32
【问题描述】:

我的 MariaDB 表具有索引 VARCHAR(10) NOT NULL COLLATE 'utf8mb3_general_ci' 类型。我在 Go 中有一个字符串,如果它更长,我将其剪切为 10 个字符,以插入/更新此表。我把字符串剪成:

if len(value) > 10 {
  value = value[:10]
}

现在我遇到了一个以š 字符结尾的字符串的问题。 MariaDB 抛出错误:Error 1366: Incorrect string value: '\\xC5'。查找 unicode 表,这个字符表示为 \xc5\xa1,这让我相信字符串的切割会以某种方式使字符串无法被数据库消化?

我想避免在我的代码中处理 utf8/unicode,因为这需要遍历所有数据库方法并处理所有字符串。而且我不认为这是必要的,因为我以前从未需要它。所以我认为问题出在其他地方,但不确定在哪里。

我尝试将排序规则切换为 utf8mb4_general_ci,但这也无济于事。

有趣的是,如果我直接使用 HeidiSQL 编辑列,则字符串保存得很好。这让我相信这可能是驱动程序问题。我一如既往地使用github.com/go-sql-driver/mysql。所以我不会期待问题,但是,谁知道......

【问题讨论】:

  • 不正确的字符集。检查字符集设置 (show variables like 'char%';)。
  • @Akina character_set_client、character_set_connection、character_set_results 是 utf8mb4 和 character_set_database、character_set_server、character_set_system 是 utf8mb3。这是正式的 mariadb 安装,一个月大,有一个 dev db。
  • Go 提供了另一种字符集,而不是 UTFx。更正 Go 设置或将 CONVERT() 应用于提供的数据。
  • @Akina Go 的字符串是 UTF8。没有什么可以转换的。
  • 第一个字节为0c5h的UTF8字符串?韩文音节?

标签: mysql go mariadb


【解决方案1】:

这让我相信字符串的切割以某种方式使数据库无法消化字符串?

如果您的程序有机会处理多字节字符,则

将字符串分割为value[:10](并使用len 测量长度)总是错误。这是因为对字符串进行索引是对其字节进行操作,这可能是也可能不是多字节编码的一部分。

如您所见,字符 š 在 UTF-8 中编码为 \xc5\xa1。如果这两个字节出现在您的 value 字符串中的索引 910 您的索引表达式 [:10] 会损坏数据。

utf8mb3utf8mb4 字符集仅将允许的 UTF-8 范围分别限制为 3 字节和 4 字节字符,但 \xc5 不是有效的 UTF-8 开头,所以它得到无论哪种方式都被拒绝。

在 MariaDB 中,数据类型为 VARCHAR(N) 的列计数 字符(由排序规则指定)。您想在第十个字符处剪切您的 value 字符串,而不是在第十个字节处。

我想避免在我的代码中处理 utf8/unicode

您已经通过将 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参与时。

【讨论】:

    猜你喜欢
    • 2020-06-07
    • 2015-03-29
    • 2017-03-18
    • 1970-01-01
    • 2018-03-29
    • 1970-01-01
    • 2019-05-27
    • 1970-01-01
    相关资源
    最近更新 更多