Sqlite3无法正确查询UTF-8字符串?

时间:2016-11-30 19:04:35

标签: python encoding sqlite

我在使用带有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.

如果要测试这些脚本,请注意文件路径。

2 个答案:

答案 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注入攻击。