我在使用带有UTF-8字符串的python的sqlite3库时遇到了很多麻烦。我需要这种编码,因为我在我的数据库中处理人们的名字。
我想要的表的SQL架构是:
CREATE TABLE senators (id integer, name char);
我想在Python中执行以下操作(忽略我编写select语句的非常丑陋的方式。我这样做是为了调试目的):
statement = u"select * from senators where name like '" + '%'+row[0]+'%'+"'"
c.execute(statement)
row [0]是具有此类条目的文件中每一行的名称:
Dário Berger,1
Edison Lobão,1
Eduardo Braga,1
虽然我对Eduardo Braga这样的名字有一个非空结果,但是当我的字符串有UTF-8字符时,我得到一个空结果。
我已经检查过我的文件实际上是用UTF-8编码保存的(Microsoft Notepad)。在Apple mac上,在终端中,我使用sqlite3 shell中的PRAGMA命令来检查编码:
sqlite> PRAGMA encoding;
UTF-8
有人知道我能在这做什么吗?
编辑 - 完整示例: Python脚本,用于创建数据库,并使用senators.csv(file)填充初始数据:
# -*- 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()
使用Q1.txt(file)填充民意调查表的脚本。
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.
如果要测试这些脚本,请注意文件路径。
答案 0 :(得分:1)
好的,
经过很多麻烦,我发现问题是编码虽然都被认为是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+'%',))
请参阅此article,了解有关此主题的一些优秀信息。
答案 1 :(得分:0)
来自SQLite docs:
重要说明:SQLite默认只能理解ASCII字符的大写/小写。对于超出ASCII范围的unicode字符,LIKE运算符默认区分大小写。例如,表达式
'a' LIKE 'A'
为TRUE,但'æ' LIKE 'Æ'
为FALSE。
另外,使用查询参数。您的查询容易受到SQL注入攻击。