如何在Python中使用SQL语句中的变量?
我有以下的Python代码:
cursor.execute("INSERT INTO table VALUES var1, var2, var3,")
其中 var1
是一个整数,var2
和 var3
是字符串。
我该如何写变量名,让Python不把它们当作查询文本的一部分呢?
5 个回答
68
有很多方法。不要在实际代码中使用最明显的方法(%s
和 %
),因为这样容易受到攻击。
这里复制粘贴了来自sqlite3的官方文档:
... 小心使用Python的字符串操作来拼接查询,因为这样容易受到SQL注入攻击。举个例子,攻击者可以简单地关闭单引号,然后注入OR TRUE,从而选择所有行:
# Never do this -- insecure!
symbol = input()
sql = "SELECT * FROM stocks WHERE symbol = '%s'" % symbol
print(sql)
cur.execute(sql)
如果你需要更多例子:
# Multiple values single statement/execution
c.execute('SELECT * FROM stocks WHERE symbol=? OR symbol=?', ('RHAT', 'MSO'))
print c.fetchall()
c.execute('SELECT * FROM stocks WHERE symbol IN (?, ?)', ('RHAT', 'MSO'))
print c.fetchall()
# This also works, though ones above are better as a habit as it's inline with syntax of executemany().. but your choice.
c.execute('SELECT * FROM stocks WHERE symbol=? OR symbol=?', 'RHAT', 'MSO')
print c.fetchall()
# Insert a single item
c.execute('INSERT INTO stocks VALUES (?,?,?,?,?)', ('2006-03-28', 'BUY', 'IBM', 1000, 45.00))
90
不同的Python数据库API实现可以使用不同的占位符,所以你需要弄清楚你正在使用的是哪一种。例如,如果你用的是MySQLdb,可能会是:
cursor.execute("INSERT INTO table VALUES (%s, %s, %s)", (var1, var2, var3))
或者如果你用的是Python标准库中的sqlite3,可能会是:
cursor.execute("INSERT INTO table VALUES (?, ?, ?)", (var1, var2, var3))
还有其他的方式(在VALUES
后面,你可能会看到(:1, :2, :3)
,或者叫“命名样式”的(:fee, :fie, :fo)
,或者(%(fee)s, %(fie)s, %(fo)s)
,在这种情况下,你需要把一个字典传给execute
的第二个参数)。你可以查看你使用的数据库API模块中的paramstyle
字符串常量,或者访问http://www.python.org/dev/peps/pep-0249/来了解所有的参数传递样式!
159
cursor.execute("INSERT INTO table VALUES (%s, %s, %s)", (var1, var2, var3))
注意,参数是以元组的形式传递的,比如说 (a, b, c)
。如果你只传一个参数,元组的结尾需要加个逗号,像这样 (a,)
。
数据库的API会正确处理变量的转义和引号。要小心不要使用字符串格式化操作符 %
,因为:
- 它不会进行任何转义或引号处理。
- 它容易受到不受控制的字符串格式攻击,比如说 SQL注入。