16

我正在使用 sqlalchemy 创建我的数据库的架构。无论我尝试什么,我都没有成功强制使用 utf-8。

这是一个重现我的问题的最小 python 脚本:

from sqlalchemy import create_engine, Column, Unicode
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine('mysql+mysqldb://user:password@localhost/multidic?charset=utf8', echo=True)
Base = declarative_base()
class MyTableName(Base):
    __tablename__ = "mytablename"
    test_column = Column(Unicode(2),primary_key=True)
Base.metadata.create_all(engine)

运行此脚本后,当我查看数据库时,我看到编码是 latin1 而不是 utf-8:

mysql> SHOW FULL COLUMNS FROM mytablename;
+-------------+------------+-------------------+------+-----+---------+-------+---------------------------------+---------+
| Field       | Type       | Collation         | Null | Key | Default | Extra | Privileges                      | Comment |
+-------------+------------+-------------------+------+-----+---------+-------+---------------------------------+---------+
| test_column | varchar(2) | latin1_swedish_ci | NO   | PRI | NULL    |       | select,insert,update,references |         |
+-------------+------------+-------------------+------+-----+---------+-------+---------------------------------+---------+
1 row in set (0.00 sec)

我尝试更改创建的列的类型(String而不是Unicode),并尝试在对create_engine的调用中添加参数encoding = "utf8",但都没有奏效。

所以,我的问题是:

如何使用 sqlalchemy 在 MySQL 中强制使用给定的字符编码(在我的情况下为 utf-8)?

谢谢 :)

笔记:

我正在使用 sqlalchemy 0.7 和 python 2.7;我可以升级一个或两个,但前提是它是唯一的解决方案!

我有 mysql 5,它支持 utf-8:

mysql> show character set where charset="utf8";
+---------+---------------+-------------------+--------+
| Charset | Description   | Default collation | Maxlen |
+---------+---------------+-------------------+--------+
| utf8    | UTF-8 Unicode | utf8_general_ci   |      3 |
+---------+---------------+-------------------+--------+
1 row in set (0.00 sec)
4

2 回答 2

19

要为每列指定特定的排序规则,请collation在数据类型上使用参数:

class MyTableName(Base):
    __tablename__ = "mytablename2"
    test_column = Column(Unicode(2),
                         primary_key=True)
    test_column2 = Column(Unicode(2, collation='utf8_bin'))
#                                    ^^^^^^^^^^^^^^^^^^^^

请注意,MySQL 将其理解为描述文本的代码点集以及文本将被索引的排序顺序;MySQL 不会熟悉像 'utf8' 或 'utf-8' 这样的常见嫌疑人(用于SHOW COLLATION查看完整列表)

mysql> show full columns from mytablename2;
+--------------+------------+-------------------+------+-----+---------+-------+---------------------------------+---------+
| Field        | Type       | Collation         | Null | Key | Default | Extra | Privileges                      | Comment |
+--------------+------------+-------------------+------+-----+---------+-------+---------------------------------+---------+
| test_column  | varchar(2) | latin1_swedish_ci | NO   | PRI | NULL    |       | select,insert,update,references |         |
| test_column2 | varchar(2) | utf8_bin          | YES  |     | NULL    |       | select,insert,update,references |         |
+--------------+------------+-------------------+------+-----+---------+-------+---------------------------------+---------+
2 rows in set (0.00 sec)

mysql> 
于 2013-09-01T18:17:47.393 回答
5

对我来说,排序规则参数不起作用。

我的连接字符串是:

db = create_engine('mysql+pymysql://user:pass@dbhost/schema?charset=utf8')

Pymysql由于charset的原因执行set names utf8,而数据库正在将utf8转换为表的编码,导致数据丢失。

如果我将字符集排除在外,则字符集默认为 latin1,并且 pymysql 在将它们发送到数据库之前尝试将我的 utf8 字符串编码为 latin1,从而引发 UnicodeEncode 错误。

这对我有用:session.execute(text("SET NAMES latin1")) 让数据库假设我发送的 utf8 字符串不需要转换。

于 2015-07-31T08:05:04.620 回答