Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL-Python-Sortierungsproblem:Wie erzwinge ich den Unicode-Datentyp?

Es stellt sich heraus, dass das Problem ziemlich umständlich ist. Kurz gesagt, die meisten Varianten und Arten in MySQL-String-Datentypen auf einen einzelnen Datentyp in der MySQL-Schnittstelle mit einem zusätzlichen BINARY-Flag abbilden.

Also MySQLs VARCHAR , VARBINARY , und ein Zeichenfolgenliteral wird demselben MySQLdb.constants.FIELD_TYPE.VAR_STRING zugeordnet Geben Sie Spaltentypdefinitionen ein, aber mit einem zusätzlichen MySQLdb.constants.FLAG.BINARY Flag, wenn der Typ VARBINARY ist oder eine Zeichenfolge, die mit einem *_bin sortiert ist Sortierung.

Obwohl es eine MySQLdb.constants.FIELD_TYPE.VARCHAR gibt Typ, ich konnte nicht herausfinden, wann es verwendet wird. Wie gesagt, MySQL VARCHAR Spalten werden FIELD_TYPE.VAR_STRING zugeordnet .

Die Lösung wird ziemlich anfällig, wenn Ihre Anwendung echte Binärzeichenfolgen verwendet (Sie speichern beispielsweise Bilder und rufen sie mit derselben Verbindung wie Text ab), da sie davon ausgeht, dass alle Binärzeichenfolgen in Unicode decodiert werden. Es funktioniert aber.

Als offizielle Dokumentation Zustände:

In der Praxis könnte der Prozess der Erstellung Ihres eigenen Konverter-Wörterbuchs ein echter Schmerz im Arsch sein. Aber Sie können die Standarddatei aus MySQLdb.converters.conversions importieren und patchen oder sogar auf einer Instanz der Connection patchen. Der Trick besteht darin, einen speziellen Konverter für eine FLAG.BINARY zu entfernen kennzeichnen und für alle Fälle einen Decoder hinzufügen. Wenn Sie explizit einen charset angeben Parameter für MySQLdb.connect , erzwingt es use_unicode=1 Parameter, der den Decoder für Sie hinzufügt, aber Sie können es selbst tun:

>>> con = MySQLdb.connect(**params)
>>> con.converter[FIELD_TYPE.VAR_STRING]
[(128, <type 'str'>), (None, <function string_decoder at 0x01FFA130>)]
>>> con.converter[FIELD_TYPE.VAR_STRING] = [(None, con.string_decoder)]
>>> c = con.cursor()
>>> c.execute("SELECT %s COLLATE utf8_bin", u'м')
1L
>>> c.fetchone()
(u'\u043c',)

Möglicherweise müssen Sie denselben Hack für FIELD_TYPE.STRING durchführen falls erforderlich.

Eine andere Lösung besteht darin, explizit use_unicode=0 zu übergeben zu MySQLdb.connect und alle Dekodierungen in Ihrem Code vornehmen, aber ich würde es nicht tun.

Hoffe, das könnte für jemanden nützlich sein.