Python与Sqlite

-1 投票
4 回答
4806 浏览
提问于 2025-04-16 14:46

我正在尝试用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 个回答

0

是的,看起来你需要添加一些参数。另外,把这一行 query += "(where patients.age >= :2) AND (patients.age <= :3) " 改成 query += "where (patients.age >= :2) AND (patients.age <= :3) " 可能会有帮助。

0

:2 是参数的占位符,但你没有提供这些参数。可以查看模块的文档,了解如何用一组参数来调用 execute 方法:

http://docs.python.org/library/sqlite3.html#sqlite3.Cursor.execute

2

你已经读取了多个查询参数,并把它们存储在 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() 的第二个参数。

撰写回答