Python与Sqlite
我正在尝试用Python 3.1和Sqlite3创建一个程序。这个程序会打开一个文本文件,读取一些参数,然后用这些参数去执行一个查询,最后把结果输出到另一个文本文件里。不过,我在cursor.execute(query)
这一行卡住了。我可能做错了很多地方。希望能得到一些帮助。
import sqlite3
# Connect to database and test
#Make sure the database is in the same folder as the python script folder
conn = sqlite3.connect("nnhs.sqlite3")
if (conn):
print ("Connection successful")
else:
print ("Connection not successful")
# Create a cursor to execute SQL queries
cursor = conn.cursor()
# Read data from a file
data = []
infile = open ("patient_in.txt", "r")
for line in infile:
line = line.rstrip("\n")
line = line.strip()
seq = line.split(' ')
seq[5] = int(seq[5])
seq = tuple (seq)
data.append(seq)
infile.close()
# Check that the data has been read correctly
print
print ("Check that the data was read from file")
print (data)
# output file
outfile = open("patient_out.txt", "w")
# select statement
query = "SELECT DISTINCT patients.resnum, patients.facnum, patients.sex, patients.age, patients.rxmed, icd9_1.resnum, icd9_1.code "
query += "from patients "
query += "INNER JOIN icd9 as icd9_1 on (icd9_1.resnum = patients.resnum) AND (icd9_1.code LIKE ':6%') "
query += "INNER JOIN icd9 as icd9_2 on (icd9_2.resnum = patients.resnum) AND (icd9_2.code LIKE ':6%') "
query += "(where patients.age >= :2) AND (patients.age <= :3) "
query += "AND patients.sex = :1 "
query += "AND (patients.rxmed >= :4) AND (patients.rxmed <= :5) "
query += "ORDER BY patients.resnum;"
result = cursor.execute(query)
for row in result:
ResultNumber = row[0]
FacNumber = row[1]
Sex = row[2]
Age = row[3]
RxMed = row[4]
ICDResNum = row[5]
ICDCode = row[6]
outfile.write("Patient Id Number: " + str(ResultNumber) + "\t" + " ICD Res Num: " + str(ICDResNum) + "\t" + " Condition: " + str(ICDCode) + "\t" + " Fac ID Num: " + str(FacNumber) + "\t" + " Patient Sex: " + str(Sex) + "\t" + " Patient Age: " + str(Age) + "\t" +" Number of Medications: " + str(RxMed) + "\t" + "\n")
# Close the cursor
cursor.close()
# Close the connection
con.close()
4 个回答
是的,看起来你需要添加一些参数。另外,把这一行 query += "(where patients.age >= :2) AND (patients.age <= :3) " 改成 query += "where (patients.age >= :2) AND (patients.age <= :3) " 可能会有帮助。
:2
是参数的占位符,但你没有提供这些参数。可以查看模块的文档,了解如何用一组参数来调用 execute 方法:
http://docs.python.org/library/sqlite3.html#sqlite3.Cursor.execute
你已经读取了多个查询参数,并把它们存储在 data
里,然后……就没下文了。其实 data
这个名字有点误导,我们把它改成 queries
吧。
你大概是想遍历 queries
,对每一行数据执行一次查询。那么就这样做吧:for query_row in queries:
.....
另外,我们把 query
改成 sql
。
你需要用 result = cursor.execute(sql, query_row)
这行代码来执行查询。
你还需要决定是为每一行 query_row
创建一个不同的输出文件,还是只用一个文件,并在里面加个字段(或者小标题)来区分每行数据来自哪个 query_row
。
更新 关于用 sqlite3 传递参数
这似乎没有文档说明,但如果你使用 编号 占位符,你可以传递一个元组作为参数——不需要用字典。下面的例子假设有一个名为 blah.db
的数据库,里面有一个空表,是通过
create table foo (id int, name text, amt int);
创建的。
>>> import sqlite3
>>> conn = sqlite3.connect('blah.db')
>>> curs = conn.cursor()
>>> sql = 'insert into foo values(:1,:2,:1);'
>>> curs.execute(sql, (42, 'bar'))
<sqlite3.Cursor object at 0x01E3D520>
>>> result = curs.execute('select * from foo;')
>>> print list(result)
[(42, u'bar', 42)]
>>> curs.execute(sql, {'1':42, '2':'bar'})
<sqlite3.Cursor object at 0x01E3D520>
>>> result = curs.execute('select * from foo;')
>>> print list(result)
[(42, u'bar', 42), (42, u'bar', 42)]
>>> curs.execute(sql, {1:42, 2:'bar'})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
sqlite3.ProgrammingError: You did not supply a value for binding 1.
>>>
更新 2a 你在这行 SQL 代码(以及下一行)中有个错误:
INNER JOIN icd9 as icd9_1 on (icd9_1.resnum = patients.resnum) AND (icd9_1.code LIKE ':6%')
如果你的参数是 Python 字符串 "XYZ",那么生成的 SQL 会是 ... LIKE ''XYZ'%')
,这不是你想要的。数据库接口会自动给你提供的字符串加上引号。你想要的是 ... LIKE 'XYZ%')
。你应该在 SQL 中写成 ... LIKE :6)
,并传入比如 user_input[5].rstrip("%") + "%"
作为参数(确保后面有且只有一个 %
)。
更新 2b 当然,你可以使用字典来传递参数,正如文档所说,但如果用有意义的名字而不是数字,会让代码更容易理解。
例如,使用 ... LIKE :code)
而不是上面的方式,然后传入 {'code': user_input[5].rstrip("%"), .....}
作为 execute()
的第二个参数。