【发布时间】:2010-10-28 11:51:29
【问题描述】:
我有以下 Python 代码:
cursor.execute("INSERT INTO table VALUES var1, var2, var3,")
其中var1 是整数,var2 和var3 是字符串。
如何在没有 Python 的情况下编写变量名称作为查询文本的一部分?
【问题讨论】:
我有以下 Python 代码:
cursor.execute("INSERT INTO table VALUES var1, var2, var3,")
其中var1 是整数,var2 和var3 是字符串。
如何在没有 Python 的情况下编写变量名称作为查询文本的一部分?
【问题讨论】:
对于没有经验的 Python 用户来说,提供单个值的语法可能会让人感到困惑。
给定查询
INSERT INTO mytable (fruit) VALUES (%s)
通常*,传递给cursor.execute 的值必须仍然是tuple,即使它是单例,所以我们必须提供一个单元素元组,例如:(value,)。
cursor.execute("""INSERT INTO mytable (fruit) VALUES (%s)""", ('apple',))
传递单个字符串
cursor.execute("""INSERT INTO mytable (fruit) VALUES (%s)""", ('apple'))
将导致错误,例如因 DB-API 连接器而异
TypeError:字符串格式化期间并非所有参数都转换
sqlite3.ProgrammingError:提供的绑定数量不正确。当前语句使用 1,提供了 5 个
mysql.connector.errors.ProgrammingError: 1064 (42000): 你的 SQL 语法有错误;
* pymysql 连接器处理单个字符串参数而不会出错。但是最好将字符串包装在一个元组中,即使它是单个的,因为
【讨论】:
http://www.amk.ca/python/writing/DB-API.html
当您只是将变量的值附加到您的语句时要小心:
想象一个用户自称';DROP TABLE Users;'——
这就是为什么您需要使用 SQL 转义,当您以体面的方式使用 cursor.execute 时,Python 会为您提供这种转义。 URL 中的示例是:
cursor.execute("insert into Attendees values (?, ?, ?)", (name, seminar, paid))
【讨论】:
很多方法。 不要在实际代码中使用最明显的一个(%s 和%),它对attacks 开放。
这里复制粘贴from pydoc of sqlite3:
# Never do this -- insecure!
symbol = 'RHAT'
c.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol)
# Do this instead
t = ('RHAT',)
c.execute('SELECT * FROM stocks WHERE symbol=?', t)
print c.fetchone()
# Larger example that inserts many records at a time
purchases = [('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),
('2006-04-06', 'SELL', 'IBM', 500, 53.00),
]
c.executemany('INSERT INTO stocks VALUES (?,?,?,?,?)', purchases)
如果您需要更多示例:
# 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))
【讨论】:
cursor.execute("INSERT INTO table VALUES (%s, %s, %s)", (var1, var2, var3))
注意参数是作为元组传递的。
数据库 API 对变量进行正确的转义和引用。注意不要使用字符串格式化操作符(%),因为
【讨论】:
%。其实我在回答中也是这么说的。
%,但使用了三遍。更多解释会很棒。
% operator 来格式化字符串。字符串中的那些% 被cursor.execute 直接使用,因为它知道它正在生成SQL,它可以做更多的事情来保护你。
Python DB-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)。检查您正在使用的 DB API 模块中的 paramstyle 字符串常量,并在 http://www.python.org/dev/peps/pep-0249/ 中查找 paramstyle 以查看所有参数传递样式!
【讨论】: