Python中如何处理含单/双引号的字符串用于SQL查询?
Python构造SQL INSERT查询的引号冲突与标准解决方案
问题场景
用f-string直接拼接SQL INSERT语句时,遇到含特殊引号的字符串会触发MariaDB语法错误:
- 字段值含双引号(如
Someword "somename")时,双引号拼接方式会导致SQL语句引号嵌套冲突 - 切换为单引号拼接后,若字段值含单引号(如
Château La Chouette d'Or),又会出现单引号截断SQL语句的问题
错误示例代码
第一种双引号拼接写法
query_ = f'INSERT INTO {entity} (id, link, name, country_id) SELECT {key}, "{value}", "{row[0]}", id FROM countries WHERE name = "{row[1]}";'
拼接后触发错误的SQL语句:
INSERT INTO wineries (id, link, name, country_id) SELECT 30052, "someword-somename", "Someword "somename"", id FROM countries WHERE name = "France";
第二种单引号拼接写法
query_ = f"INSERT INTO {entity} (id, link, name, country_id) SELECT {key}, '{value}', '{row[0]}', id FROM countries WHERE name = '{row[1]}';"
当row[0]为Château La Chouette d'Or时,单引号会截断SQL语句,触发语法错误。
标准优雅解决方案:使用参数化查询
直接拼接字符串不仅会导致引号冲突,还存在SQL注入风险,**参数化查询(Prepared Statements)**是Python操作数据库的标准解决方案,由数据库驱动自动处理特殊字符转义。
实现步骤(以MariaDB驱动为例)
安全处理表名:表名不能用参数化占位符,需确保
entity是可信值(如预定义的常量列表),避免SQL注入# 预定义允许的表名,确保entity来源安全 allowed_tables = ['wineries', 'countries'] if entity not in allowed_tables: raise ValueError("非法的表名")构造带占位符的SQL语句:用
%s作为值的占位符(MariaDB驱动标准占位符)query_ = f'INSERT INTO {entity} (id, link, name, country_id) SELECT %s, %s, %s, id FROM countries WHERE name = %s;'传入参数执行查询:将变量以元组形式传入
execute()方法,驱动自动处理转义# 假设conn是已建立的MariaDB连接 cursor = conn.cursor() # 参数顺序与占位符一一对应:key, value, row[0], row[1] cursor.execute(query_, (key, value, row[0], row[1])) conn.commit()
优势
- 彻底解决引号、特殊字符导致的语法错误
- 从根源避免SQL注入风险,符合工业级代码规范
- 代码更简洁易维护,无需手动处理字符串转义
内容的提问来源于stack exchange,提问作者Andrey Starkov
相关产品推荐
相关产品推荐

