这不是安全问题(除非您不清理查询字符串本身)。
这是一个维护问题:
- 您正在传递“所有内容”,因此编写不佳的查询(即您的拼写错误)可能会从 locals() 中获取意外值。通过更明确,您更有可能抓住这一点。
- 您并没有准确地告诉“未来的程序员”您正在使用什么进行查询,因此有人可能会在您的 SQL 调用之前更改参数的值,从而导致意外行为。
在简短的查询(例如您的示例)中,使用locals()
并不是这样的悲剧。使用更复杂的查询,例如(我从最近的 emacs 缓冲区中抓取的东西):
WITH RECURSIVE
include_parents(a_id, parent_id, uid, distance) AS (
SELECT accounts.a_id,
CASE WHEN admin_can_add THEN NULL
ELSE accounts.parent_id END AS parent_id,
uid, 0 AS distance
FROM accounts LEFT OUTER JOIN account_users
ON (accounts.a_id = account_users.a_id AND admin_can_add)
WHERE accounts.a_id = $a_id
UNION ALL
SELECT accounts.a_id,
CASE WHEN admin_can_add THEN NULL
ELSE accounts.parent_id END as parent_id,
account_users.uid, distance + 1 as distance
FROM accounts LEFT OUTER JOIN account_users
ON (accounts.a_id = account_users.a_id AND admin_can_add),
include_parents
WHERE accounts.a_id = include_parents.parent_id
)
SELECT a_id, uid, distance from include_parents
WHERE uid IS NOT NULL
在这种情况下,{'a_id': 14}
通过而不是locals()
. 另外,如果我的查询因寻找我忘记传递的另一个参数而爆炸(可能是因为我从另一个用法稍微改变了这个查询),它将迫使我更仔细地查看我的代码。如果我通过locals()
了,查询可能会以我不希望的方式“成功”。