Python Sqlite3无法正确查询UTF-8字符串?
我在使用带有UTF-8字符串的python sqlite3库时遇到了很多问题。我需要这种编码,因为我在数据库中处理人们的名字 所需表的SQL架构为:Python Sqlite3无法正确查询UTF-8字符串?,python,encoding,sqlite,Python,Encoding,Sqlite,我在使用带有UTF-8字符串的python sqlite3库时遇到了很多问题。我需要这种编码,因为我在数据库中处理人们的名字 所需表的SQL架构为: CREATE TABLE senators (id integer, name char); 我想在Python中执行以下操作(忽略我编写select语句的丑陋方式。我这样做是为了调试): 行[0]是文件中具有此类型项的每一行的名称: Dário Berger,1 Edison Lobão,1 Eduardo Braga,1 虽然像Eduard
CREATE TABLE senators (id integer, name char);
我想在Python中执行以下操作(忽略我编写select语句的丑陋方式。我这样做是为了调试):
行[0]是文件中具有此类型项的每一行的名称:
Dário Berger,1
Edison Lobão,1
Eduardo Braga,1
虽然像Eduardo Braga这样的名字有一个非空的结果,但每当我的字符串有UTF-8字符时,我都会得到一个空结果
我已经检查过我的文件实际上是用UTF-8编码(Microsoft记事本)保存的。在Apple mac上的终端中,我使用sqlite3 shell中的PRAGMA命令检查编码:
sqlite> PRAGMA encoding;
UTF-8
有人知道我在这里能做什么吗
编辑-完整示例:
创建数据库并使用senators.csv()中的初始数据填充的Python脚本:
使用Q1.txt()填充轮询表的脚本
如果要测试这些脚本,请注意文件路径。来自:
重要提示:默认情况下,SQLite只理解ASCII字符的大小写。对于超出ASCII范围的unicode字符,LIKE运算符默认情况下区分大小写。例如,表达式'a'LIKE'a'
为真,而'æ'LIKE'Æ'
为假
另外,使用查询参数。您的查询易受SQL注入攻击。好的,伙计们
在经历了很多麻烦之后,我发现问题在于编码虽然都被认为是UTF-8,但无论如何都是不同的。不同之处在于,当数据库被分解为UTF-8(ã=a+~)时,我的输入是预合成的形式(一个代码表示ã字符)
为了修复它,我必须将所有输入数据转换为分解的表单
from unicodedata import normalize
with open(poll, encoding='utf-8') as p:
f_csv = csv.reader(p)
for row in f_csv:
name = normalize("NFD",row[0])
c.execute(u'SELECT id FROM senators WHERE name LIKE ?', ('%'+name+'%',))
有关此主题的一些优秀信息,请参见此部分。不要在SQL查询中使用字符串操作!看看Python文档中的大警告框,改用查询参数。@ColonelThirtyTwo我是用参数来做的,这只是为了调试以确保我在字符串插值中没有犯错误,因为我过去和现在都得到了奇怪的结果。请参阅我对@ColonelThirtyTwo关于查询参数的评论。这不是区分大小写的情况。当我复制数据库中的值时:例如,Sérgio Petecão,查询工作,但当我收到相同的字符串,显然编码略有不同,Sérgio Peteão,它就不工作了@jhc
选择像“%Edison Lobão%”一样的“Edison Lobão%”
为我返回1。请创建准确的架构、测试数据、查询和结果。请参阅我刚刚发布的编辑。
# -*- coding: utf-8 -*-
import sqlite3
import csv
conn = sqlite3.connect('senators.db')
c = conn.cursor()
c.execute('''CREATE TABLE senators (id integer, name char)''')
c.execute('''CREATE TABLE polls (id integer, senator char, vote integer, FOREIGN KEY(senator) REFERENCES senators(name))''')
with open('senators.csv', encoding='utf-8') as f:
f_csv = csv.reader(f)
for row in f_csv:
c.execute(u"INSERT INTO senators VALUES(?,?)", (row[1], row[0]))
conn.commit()
conn.close()
import csv
import sqlite3
import re
import glob
conn = sqlite3.connect('senators.db')
c = conn.cursor()
POLLS = {
'senator': 'votes/senator/Q*.txt',
'deputee': 'votes/deputee/Q*.txt',
}
s_polls = glob.glob(POLLS['senator'])
d_polls = glob.glob(POLLS['deputee'])
for poll in s_polls:
m = re.match('.*Q(\d+)\.txt', poll)
poll_id = m.groups(0)
with open(poll, encoding='utf-8') as p:
f_csv = csv.reader(p)
for row in f_csv:
c.execute(u'SELECT id FROM senators WHERE name LIKE ?', ('%'+row[0]+'%',))
data = c.fetchone()
print(data) # I should not get None results here, but I do, exactly when the query has UTF-8 characters.
from unicodedata import normalize
with open(poll, encoding='utf-8') as p:
f_csv = csv.reader(p)
for row in f_csv:
name = normalize("NFD",row[0])
c.execute(u'SELECT id FROM senators WHERE name LIKE ?', ('%'+name+'%',))