如何在Python中使用SQL语句中的变量?

135 投票
5 回答
489615 浏览
提问于 2025-04-15 11:47

我有以下的Python代码:

cursor.execute("INSERT INTO table VALUES var1, var2, var3,")

其中 var1 是一个整数,var2var3 是字符串。

我该如何写变量名,让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会正确处理变量的转义和引号。要小心不要使用字符串格式化操作符 %,因为:

  1. 它不会进行任何转义或引号处理。
  2. 它容易受到不受控制的字符串格式攻击,比如说 SQL注入

撰写回答