在使用 sqlalchemy
执行原生 sql
语句时,项目开发的同事遇到一个问题,在插入数据时,如果数据中含有单引号,会报错导致插入失败,伪代码大概是这样的:
from sqlalchemy import create_engine
name = "Maoming People's Hospital"
addr = '茂名市为民路101号'
h_num = 102
sql = "insert into info (h_num, name, addr) values ({h_num}, '{name}', '{addr}')".format(h_num=h_num, name=name, addr=addr)
engine = create_engine('mysql+mysqlconnector://xxx:yyy@localhost:3306/database')
engine.execute(sql)
大部分时候,这样写也可以写入数据,但是显然这样直接拼接的 sql
来执行起码存在两个问题:
1. 可能会出现 SQL注入攻击
,实际使用中变量是不可信的,恶意代码会来带风险;
2. 如果变量字符串中带有特殊字符,比如上面 name
中的 '
单引号,会直接导致执行失败;
实际上,无论什么语言什么 sql
操作库,都不应该直接拼接 sql
直接执行,这里的 sqlalchemy
也提供了相应的参数绑定来执行,参数绑定不仅可以防止 SQL注入攻击
,还可以自动处理特殊字符(如单引号)。
以下是使用 sqlalchemy
和参数绑定后的使用:
from sqlalchemy import create_engine
from sqlalchemy.sql import text
params = {
"name": "Maoming People's Hospital",
"addr": '茂名市为民路101号',
"h_num": 102
}
sql = "insert into info (h_num, name, addr) values (:h_num, :name, :addr)"
engine = create_engine('mysql+mysqlconnector://xxx:yyy@localhost:3306/database')
engine.execute(sql, **params)