执行原生SQL语句
原生SQL语句可以通过Engine
、Connection
、Session
类实例中的.execute()
方法来执行。由于一般会需要将要执行的方法排入事务,所以建议在Session
类实例中执行SQL语句。
SQLAlchemy支持建立动态SQL语句,并在执行时动态绑定参数。要完成这个功能,首先要文本SQL模板,这是由sqlalchemy.sql
模块中的text()
函数提供的。文本SQL模板可以直接在.execute()
方法中执行,并使用一个字典来向其中传递参数。执行原生SQL语句时,要尽量使用文本SQL模板和绑定参数的方式,这种方式可以在一定程度上避免SQL注入攻击。
以下示例给了一个执行原生SQL语句的参考。
from sqlalchemy.sql import text
sql_cmd = text("SELECT user_id, user_name FROM users WHERE user_id=:id")
rows = db.session.execute(sql_cmd, {'id': 1})
文本SQL模板中使用“:param_name
”的格式来声明参数,注意在书写时不要丢掉冒号。在.execute()
方法传递参数时,参数名需要作为键名,但不要加入冒号。SQLAlchemy会在执行时自动判定传递参数的类型。
.execute()
方法会返回一个ResultProxy
类的实例,其中可以使用.fetchone()
、.fetchall()
、.fetchmany()
、.first()
等方法返回RowProxy
实例或者RowProxy
实例序列。RowProxy
实例可以直接通过使用数据表列名作为键名来访问其中的数据,也可以直接使用dict()
将其转换为字典实例,或者使用list()
、tuple()
来转换成值列表或者值元组。
例如继续上例的内容对返回的结果集进行处理。
# 将整个结果集转换为字典序列
results = [dict(row) for row in rows.fetchall()]
# 只将指定列的内容取出作为序列
usernames = [row["user_name"] for row in rows.fetchall()]
# 取出第一行结果,之后关闭结果集
# .scalar()在结果集为空的时候,会返回None
user = dict(rows.scalar())
ResultProxy
实例中是否包含数据库返回的记录,可以使用.returns_rows
属性判断,这个属性是只读的。ResultProxy
实例在使用完毕后,要记得使用.close()
方法关闭,直接关闭数据库连接或者会话并不能使ResultProxy
关闭,它还会继续返回空白结果集。