使用cursor.execute重命名列报错,求科普SQL注入及参数化差异
问题解答
为什么第二种写法报错?
参数化查询的%s(或?)只能用来替换SQL语句中的数据值(比如WHERE子句里的条件值),不能用来替换SQL的语法标识符——像列别名、表名、列名这类属于SQL语法结构的部分,没法用参数化来处理。你想用它设置列别名,MySQL会把?当成语法的一部分,自然就报语法错误了。
参数化查询 vs 字符串拼接的差异
- 参数化查询:
- 把SQL语句的固定结构和要传递的数据完全分开,先把SQL结构发给数据库编译,再单独传递数据。
- 数据库会把传入的数据当成纯数据处理,不会解析成SQL语法的一部分。
- 字符串拼接:
- 直接把数据和SQL语句拼在一起,生成完整字符串后再发给数据库编译。
- 数据库会把整个拼接后的字符串当成完整SQL解析,数据里的特殊字符可能会破坏原有SQL结构。
什么是SQL注入?
举个简单例子:假设你写了个登录查询用字符串拼接:
query = f"SELECT * FROM users WHERE username='{input_username}' AND password='{input_pwd}'"
如果有人输入username为' OR '1'='1,拼接后的SQL就变成:
SELECT * FROM users WHERE username='' OR '1'='1' AND password='xxx'
这时候条件永远为真,不用密码就能登录——攻击者通过构造恶意输入,篡改原有SQL逻辑,获取非法权限或数据,这就是SQL注入。
第一种写法是不是需要避免的字符串拼接?
得看new_name的来源:
- 如果
new_name是代码里写死的固定值(比如你例子里的'Company Name'),这种拼接不会有SQL注入风险,完全没问题。 - 如果
new_name来自用户输入、外部接口这类不可信来源,就要小心。这时候需要先对标识符做校验:比如检查是否包含特殊字符,或者用MySQL的标识符转义规则(用反引号把别名包起来,比如AS{new_name}`),避免恶意输入破坏SQL语法。
另外,你的第一种写法里别名带空格,实际执行的SQL应该写成AS Company Name``才对,不然也会报语法错误。正确的拼接应该是:
query = f"SELECT company_name AS `{new_name}` from company_directory"
用反引号把别名括起来,MySQL才能识别带空格的标识符。
内容的提问来源于stack exchange,提问作者novawaly
相关产品推荐
相关产品推荐

