sqlite / python - 没有引号的命名参数?
在使用SQLite的准备语句和命名参数时(特别是用Python的sqlite3模块 http://docs.python.org/library/sqlite3.html),有没有办法在不让字符串值被加上引号的情况下使用它们?
我现在有这个:
columnName = '''C1'''
cur = cur.execute('''SELECT DISTINCT(:colName) FROM T1''', {'colName': columnName})
结果生成的SQL看起来是这样的:
SELECT DISTINCT('C1') FROM T1
当然,这样并没有什么用,我真正想要的是:
SELECT DISTINCT(C1) FROM T1 .
有没有办法让执行方法处理提供的参数时,不在它们周围加上引号呢?
我写了一个小测试程序来深入探讨这个问题,所以这里分享一下:
import sys
import sqlite3
def getDatabaseConnection():
DEFAULTDBPATH = ':memory:'
conn = sqlite3.connect(DEFAULTDBPATH, detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
conn.text_factory = str
return conn
def initializeDBTables(conn):
conn.execute('''
CREATE TABLE T1(
id INTEGER PRIMARY KEY AUTOINCREMENT,
C1 STRING);''')
cur = conn.cursor()
cur.row_factory = sqlite3.Row # fields by name
for v in ['A','A','A','B','B','C']:
cur.execute('''INSERT INTO T1 values (NULL, ?)''', v)
columnName = '''C1'''
cur = cur.execute('''SELECT DISTINCT(:colName) FROM T1''', {'colName': columnName})
#Should end up with three output rows, in
#fact we end up with one
for row in cur:
print row
def main():
conn = getDatabaseConnection()
initializeDBTables(conn)
if __name__ == '__main__':
main()
我很想知道有没有办法调整执行方法,让它可以正常工作。
2 个回答
0
你正在使用绑定,而绑定只能用于值,不能用于表名或列名。你需要使用字符串插值或格式化来达到你想要的效果,但这样做会让你面临SQL注入攻击的风险,特别是当列名来自不可信的来源时。在这种情况下,你可以对字符串进行清理(比如只允许字母和数字),并使用授权接口来检查是否会发生意外的操作。
4
在 SELECT DISTINCT(C1) FROM T1
这条语句中,C1
不是一个字符串值,而是一段SQL代码。这里的参数(在 execute
中被转义)是用来插入值的,而不是用来插入代码的部分。