【问题标题】:ER_TRUNCATED_WRONG_VALUE_FOR_FIELD on saving some strings to mysqlER_TRUNCATED_WRONG_VALUE_FOR_FIELD 将一些字符串保存到 mysql
【发布时间】:2015-10-20 08:10:50
【问题描述】:

我正在使用 node.js,node-mysql npm 模块,在 mysql (sql_mode=STRICT_ALL_TABLES) 中有一个 utf8 列,并且可以正常存储“常规”utf8 字符,但是对于某些输入,它会抛出这个:

AssertionError: Error: ER_TRUNCATED_WRONG_VALUE_FOR_FIELD: Incorrect string value: '\xF3\xA5\xB5\xA5\xEF\xBF...'

我想这是因为utf8 之外的一些字符。我知道可以在 mysql 中使用 utf8mb 字符集,但在这种情况下,我不关心这些字符,只想从字符串中删除它们而不是更改 mysql 配置。

是否可以使用 node.js 删除此类字符?

【问题讨论】:

    标签: mysql regex node.js utf-8


    【解决方案1】:

    我知道这并不完全是您正在寻找的答案,但许多人实际上会对以正确的方式修复它感兴趣,所以:

    1.备份您的数据库:

    mysqldump -h HOSTNAME -u USERNAME -p DATABASE_NAME > PATH_TO_FILE
    

    例子:

    mysqldump -h 127.0.0.1 -u root -p music > ~/music-db-backup.sql
    

    这将询问您的数据库密码。如果您想在命令中包含密码 - 在 -p 之后添加密码,中间没有空格,例如-pJazzMusic.

    2。更改您的字段字符集 utf8mb4 和排序规则为utf8mb4_0900_ai_ci(Unicode v9 兼容)。此外,更新表和数据库本身也是一个好主意。

    更新数据库:

    ALTER DATABASE <database-name>
    CHARACTER SET utf8mb4
    COLLATE utf8mb4_0900_ai_ci
    

    更新表:

    一次性更新表及其字段:
    (请记住,在较大的表上,它可能会花费大量时间并产生显着的 IO 峰值)

    ALTER TABLE <table-name> CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
    

    或者,也可以根据具体情况更新表和字段:

    ALTER TABLE <table-name>
    CHARACTER SET utf8mb4
    COLLATE utf8mb4_0900_ai_ci
    

    这样预先存在的字段将保持其旧的字符集/排序规则。

    转换单个字段:

    ALTER TABLE <table-name>
    MODIFY COLUMN <column-name> varchar(64)
    CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci
    NOT NULL;
    

    3。建立连接以使用utf8mb4

    您可以在连接后立即将此查询发送到您的数据库:

    SET NAMES "utf8mb4"
    

    MySQL Documentation - Set Names

    或者查看您的数据库框架文档,了解如何以更简单的方式进行操作。
    例如 TypeOrm 有charset 连接属性:

    import { createConnection } from 'typeorm';
    
    const connection = await createConnection({
        type: 'mysql',
        host: '127.0.0.1',
        port: 3306,
        charset: 'utf8mb4'
        // ...
    });
    

    【讨论】:

      【解决方案2】:

      RFC here 具有 unicode 字符代码列表以及它们占用的字符数:

         Char. number range  |        UTF-8 octet sequence
            (hexadecimal)    |              (binary)
         --------------------+---------------------------------------------
         0000 0000-0000 007F | 0xxxxxxx
         0000 0080-0000 07FF | 110xxxxx 10xxxxxx
         0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
         0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
      

      虽然我提供的错误消息没有显示任何宽字符:

      node -e 'console.log("\xF3\xA5\xB5\xA5\xEF\xBF")'
      ó¥µ¥ï¿
      

      this 页面显示所有这些字符都是 2 字节字符,我仍然尝试使用 .replace(/[\u0800-\uFFFF]/g, '') 从字符串中删除宽(3 个或更多八位字节)字符,并且成功了!

      【讨论】:

      • 感谢您的回答。替换非常方便!
      • .replace(/[\u0800-\uFFFF]/g, '') - 太棒了!这解决了我所有存储到 LONGTEXT 列中的 JSON 问题,非常感谢!!!
      • 这是在剥离字符,对吧?就像我会丢失本应在文本中出现的字符。
      • 此解决方案省略了字符串中的所有撇号和连字符。有更好的解决方案吗?
      【解决方案3】:

      将列转换为 utf8mb4 字符集。utf8 字符集仅限于字符

      http://dev.mysql.com/doc/refman/5.6/en/charset-unicode-utf8mb4.html

      【讨论】:

      • @Fluffy 也许他没有。但他的解决方案对我来说效果很好。
      • 嗯,我仍然收到ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci 在桌子上的错误。
      猜你喜欢
      • 2015-02-07
      • 2013-03-27
      • 2014-07-02
      • 2012-07-04
      • 2012-09-28
      • 1970-01-01
      • 2011-03-05
      • 2016-10-22
      • 2019-05-16
      相关资源
      最近更新 更多