我想在flask_sqlalchemy中运行参数化的mysql UPDATE SET语句。由于我不知道应更新哪些列,因此我编写了一个辅助函数来帮助编写该语句。
我的模特
class User(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement= True)
username = db.Column(db.String(80), nullable=False)
email = db.Column(db.String(120), nullable=False)
def __repr__(self):
return '<User %r>' % self.username
助手功能
def run_sql(params):
# e.g: params = {'username': "testing", "email": "testing@testing.ts", "id": 1}
id = params.pop("id")
# params = {'username': "testing", "email": "testing@testing.ts"}
sets = list(map(lambda col: f"{col}=:{col}", params.keys()))
# sets = ["username=:username", "email=:email"]
sets = ", ".join(sets)
# sets = "username=:username, email=:email"
params["id"] = id
# params = {'username': "testing", "email": "testing@testing.ts", "id": 1}
sql_statement = f"""UPDATE User SET {sets} WHERE id=:id LIMIT 1"""
# sql_statement = UPDATE User SET username=:username, email=:email WHERE id=:id LIMIT 1
return sql_statement
调用助手功能
if __name__ == "__main__":
conn = engine.connect()
params = {'username': "testing", "email": "testing@testing.ts", "id": 1}
sql_statement = run_sql(params)
conn.execute(sql_statement, params)
运行前面的代码会生成以下异常
"sqlalchemy.exc.ProgrammingError: (pymysql.err.ProgrammingError) (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ':username, email=:email WHERE id=:id LIMIT 1' at line 1") [SQL: 'UPDATE User SET username=:username, email=:email WHERE id=:id LIMIT 1'] [parameters: {'username': 'testing', 'email': 'testing@testing.ts', 'id': 1}] (Background on this error at: http://sqlalche.me/e/f405)"
SQL语句对我来说很好,所以参数也不错。我想念什么吗?
答案 0 :(得分:2)
如果要对SQL语句使用:named_parameter
格式,则需要使用SQLAlchemy的text
方法,然后调用execute
对象的Engine
方法:
import sqlalchemy as sa
# ...
engine.execute("CREATE TEMPORARY TABLE temp (id varchar(10) PRIMARY KEY)")
sql = sa.text("INSERT INTO temp (id) VALUES (:id)")
params = {'id': 'foo'}
engine.execute(sql, params)
print(engine.execute("SELECT * FROM temp").fetchall()) # [('foo',)]
答案 1 :(得分:2)
绑定参数不是MySQL样式,当您将纯文本传递给engine.execute()
时,SQLAlchemy不会在执行查询之前将方言应用于查询。
尝试一下:
engine.execute("SELECT :val", {"val": 1}) # will fail, same as your query
...然后是这个
engine.execute("SELECT %(val)s", {"val": 1}) # will execute
用text()
包裹查询将使SQLAlchemy处理正确的绑定样式:
from sqlalchemy import text # or you can use db.text w/ flask-sqlalchemy
engine.execute(text("SELECT :val"), {"val": 1})
要注意的另一件事是,SQLAlchemy将自动为您处理UPDATE查询的构造,同时遵守参数dict中的值,例如:
id_ = 1
params = {'username': "testing", "email": "testing@testing.ts"}
User.__table__.update().values(params).where(id=id_)
# UPDATE user SET username=%(username)s, email=%(email)s WHERE user.id = %(id_1)s
params = {'username': "testing"}
User.__table__.update().values(params).where(id=id_)
# UPDATE user SET username=%(username)s WHERE user.id = %(id_1)s
params = {'username': "testing", "unexpected": "value"}
User.__table__.update().values(params).where(id=id_)
# sqlalchemy.exc.CompileError: Unconsumed column names: unexpected