Rails 应用程序的 utf8mb4 字符集

utf8mb4 character set for Rails application

我正在使用 MySQL 版本 5.7.12;我正在尝试在文本字段中添加表情符号支持。我找到了 this 篇文章。它声明更改 table 和列以启用 utf8mb4,它支持真正的 unicode,包括 4 字节 unicode 字符。我有一个 table 评论和文本字段内容,所以我执行以下操作:

class ConvertCommentsToUtf8mb4 < ActiveRecord::Migration
  def change
    # for each table that will store unicode execute:
    execute "ALTER TABLE comments CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin"
    # for each string/text column with unicode content execute:
    execute "ALTER TABLE comments CHANGE content TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin"
  end
end

当我尝试 运行 迁移时,出现以下错误:

Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SET utf8mb4 COLLATE utf8mb4_bin' at line 1: ALTER TABLE comments CHANGE content TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin/Users/myuser/.rvm/gems/ruby-2.1.2@core/gems/mysql2-0.3.21/lib/mysql2/client.rb:80:in `_query'

我可能做错了什么?

当你使用ALTER TABLE...CHANGE时你需要给列名两次,因为CHANGE允许你改变列名。

ALTER TABLE comments CHANGE content TEXT CHARACTER SET ...

在这种情况下,它认为您将列名称更改为 TEXT,数据类型为 CHARACTER(这是一种合法的数据类型,它是 CHAR(1) 的同义词),然后当它找到 SET.

这个词

因此您可以通过以下两种方式之一修复它:

ALTER TABLE comments CHANGE content content TEXT CHARACTER SET ...

ALTER TABLE comments MODIFY content TEXT CHARACTER SET ...

MODIFY 与 CHANGE 类似,但不能更改列名,因此您无需将列名拼写两次。

这是对语法错误的解释,但是 FWIW 在对整个 table 使用 CONVERT TO CHARACTER SET 后不需要修改文本列。 MySQL 自动更改 table.

中所有字符串列的字符集和排序规则

演示:

mysql> create table comments ( content text ) character set utf8;
Query OK, 0 rows affected (0.03 sec)

mysql> alter table comments convert to character set utf8mb4;
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> insert into comments set content = 0xF09F92A9;
Query OK, 1 row affected (0.01 sec)

mysql> select * from comments;
+---------+
| content |
+---------+
|         |
+---------+
sql = "ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4  
COLLATE utf8mb4_unicode_ci;"
records_array = ActiveRecord::Base.connection.execute(sql)