提问人:user111606 提问时间:5/24/2009 最后编辑:snakecharmerbuser111606 更新时间:9/8/2023 访问量:474080
如何在Python的SQL语句中使用变量?
How to use variables in SQL statement in Python?
问:
我有以下 Python 代码:
cursor.execute("INSERT INTO table VALUES var1, var2, var3,")
其中是整数,是字符串。var1
var2
var3
如何在没有 Python 的情况下编写变量名称作为查询文本的一部分?
答:
cursor.execute("INSERT INTO table VALUES (%s, %s, %s)", (var1, var2, var3))
请注意,参数是作为元组传递的。如果要传递单个参数,则元组需要以逗号结尾。(a, b, c)
(a,)
数据库 API 对变量进行适当的转义和引用。注意不要使用字符串格式运算符 (),因为%
- 它不会进行任何转义或引用。
- 它容易受到不受控制的字符串格式攻击,例如SQL注入。
评论
%
%
%
%
cursor.execute
http://www.amk.ca/python/writing/DB-API.html
当您简单地将变量的值附加到语句中时要小心:
想象一下,一个用户给自己起名字——
这就是为什么你需要使用 SQL 转义,当你以体面的方式使用时,Python 会为你提供转义。URL 中的示例是:';DROP TABLE Users;'
cursor.execute
cursor.execute("insert into Attendees values (?, ?, ?)", (name, seminar, paid))
评论
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))
或其他(在您可能拥有 或“命名样式”之后,或者您将字典而不是映射作为第二个参数传递给 )。检查您正在使用的数据库 API 模块中的字符串常量,并在 http://www.python.org/dev/peps/pep-0249/ 中查找 paramstyle,看看所有参数传递样式是什么!VALUES
(:1, :2, :3)
(:fee, :fie, :fo)
(%(fee)s, %(fie)s, %(fo)s)
execute
paramstyle
很多方式。不要在实际代码中使用最明显的一个(与),它很容易受到攻击。%s
%
这里是从 sqlite3 的 pydoc 复制粘贴的:
...谨防使用 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))
评论
对于没有经验的 Python 用户来说,提供单个值的语法可能会令人困惑。
给定查询
INSERT INTO mytable (fruit) VALUES (%s)
通常*,即使值本身是单例,传递给的值也必须包装在有序序列中,例如元组或列表,因此我们必须提供单个元素元组,如下所示: .cursor.execute
(value,)
cursor.execute("""INSERT INTO mytable (fruit) VALUES (%s)""", ('apple',))
传递单个字符串
cursor.execute("""INSERT INTO mytable (fruit) VALUES (%s)""", ('apple'))
将导致错误,该错误因 DB-API 连接器而异,例如
- psycopg2:
TypeError:并非所有参数在字符串格式设置期间转换
- SQLITE3的
sqlite3 中。ProgrammingError:提供的绑定数不正确。当前语句使用 1,并提供了 5
- mysql.连接器
mysql.connector.errors.ProgrammingError: 1064 (42000):SQL语法中有错误;
* pymysql 连接器处理单个字符串参数而不会出错。但是,最好将字符串包装在元组中,即使它是单个,因为
- 如果切换连接器包,则无需更改代码
- 将查询参数的一致思维模型保持为一系列对象,而不是单个对象。
将您的数据加载为自动规范化表,我建议使用这个库来推断模式、键入数据并具有模式演变 https://pypi.org/project/dlt/
你甚至可以使用这个库在之后对你的结构化数据进行更新插入,下面是一个例子,我们使用 json 中的 id 来更新在目标位置生成的 sql 表
data = [{'id': 1, 'name': 'John'}]
# open connection
pipe = dlt.pipeline(destination='postgres',
dataset_name='raw_data')
# Upsert/merge: Update old records, insert new
# Capture the outcome in load info
load_info = pipe.run(data,
write_disposition="merge",
primary_key="id",
table_name="users")
上一个:如何为从数据库获取的变量赋值?
评论