执行原生SQL语句

原生SQL语句可以通过EngineConnectionSession类实例中的.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关闭,它还会继续返回空白结果集。