conn = _db.engine.raw_connection()
# do the call. The actual parameter does not matter, could be ['lala'] as well
results = conn.cursor().callproc('my_proc_with_one_out_param', [0])
conn.close() # commit
print(results) # will print (<out param result>)
# do the call and store the result in a local mysql variabl
# the name does not matter, as long as it is prefixed by @
_db.session.execute('CALL my_proc_with_one_out_param(@out)')
# do another query to get back the result
result = _db.session.execute('SELECT @out').fetchone()
import sqlalchemy as sql
def execute_db_store_procedure(database, types, sql_store_procedure, *sp_args):
""" Execute the store procedure and return the response table.
Attention: No injection checking!!!
Does work with the CALL syntax as of yet (TODO: other databases).
Attributes:
database -- the database
types -- tuple of strings of SQLAlchemy type names.
Each type describes the type of the argument
with the same number.
List: http://docs.sqlalchemy.org/en/rel_0_7/core/types.html
sql_store_procudure -- string of the stored procedure to be executed
sp_args -- arguments passed to the stored procedure
"""
if not len(types) == len(sp_args):
raise ValueError("types tuple must be the length of the sp args.")
# Construch the type list for the given types
# See
# http://docs.sqlalchemy.org/en/latest/core/sqlelement.html?highlight=expression.text#sqlalchemy.sql.expression.text
# sp_args (and their types) are numbered from 0 to len(sp_args)-1
type_list = [sql.sql.expression.bindparam(
str(no), type_=getattr(sql.types, typ)())
for no, typ in zip(range(len(types)), types)]
try:
# Adapts to the number of arguments given to the function
sp_call = sql.text("CALL `%s`(%s)" % (
sql_store_procedure,
", ".join([":%s" % n for n in range(len(sp_args))])),
bindparams=type_list
)
#raise ValueError("%s\n%s" % (sp_call, type_list))
with database.engine.begin() as connection:
return connection.execute(
sp_call,
# Don't do this at home, kids...
**dict((str(no), arg)
for (no, arg) in zip(range(len(sp_args)), sp_args)))
except sql.exc.DatabaseError:
raise
8条答案
按热度按时间7gcisfzg1#
引擎和连接具有可用于任意SQL语句的
execute()
方法,会话也是如此。例如:如果需要,可以使用
outparam()
创建输出参数(或者对于绑定参数,使用bindparam()
和isoutparam=True
选项)oxf4rvwz2#
不支持调用现成的存储过程:
callproc
不是通用的,而是特定于mysql连接器的。对于没有out参数的存储过程,可以执行如下查询
像往常一样。当你有out params时事情会变得更复杂...
使用out参数的一种方法是通过
engine.raw_connection()
访问底层连接器。这很好,因为我们可以访问out参数,但是这个连接不是由flask会话管理的。这意味着它不会像其他托管查询一样被提交/中止...(只有当您的过程有副作用时才有问题)。
最后,我终于做到了:
result
将是具有一个值的元组:out param。这不是理想的,但危险性最小:如果在会话期间另一个查询失败,则过程调用也将被中止(回滚)。r8uurelv3#
仅执行使用
func
创建的程序对象:fafcakar4#
在MySQL中使用SQLAlchemy调用存储过程的最简单方法是使用
Engine.raw_connection()
的callproc
方法。call_proc
需要调用存储过程所需的过程名和参数。bnl4lu3b5#
假设您已经使用sessionmaker()创建了会话,您可以使用以下函数:
现在,您可以使用如下所示的参数执行存储过程'MyProc':
8qgya5xd6#
出于对我的一个项目的迫切需要,我编写了一个处理存储过程调用的函数。
给你:
它使用的是CALL语法,所以MySQL应该能像预期的那样工作。我猜MSSQL使用EXEC而不是call,语法也有一点不同。所以让它与服务器无关取决于你,但应该不难。
ozxc1zmp7#
另一种解决方案:
2sbarzqh8#
我有一个postgresql的存储过程,签名如下-
在经历了许多错误和尝试之后,我发现这就是如何从python3调用该过程。