1 回答

TA貢獻1802條經驗 獲得超5個贊
據我所知,SQLAlchemy不支持直接調用存儲過程。文檔建議使用原始 DB-API 連接的callproc方法。
可以從引擎訪問該連接;也可以通過會話訪問它,但這仍然是通過引擎進行的。
下面的示例代碼顯示了這兩種方法。請注意,訪問調用過程結果的方法可能會有所不同,具體取決于所使用的參數和連接器 。
import mysql.connector
import sqlalchemy as sa
from sqlalchemy import orm
# Setup the database
DATA = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
DDL1 = """\
CREATE TABLE IF NOT EXISTS test_table (
? id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
? a INT,
? b INT,
? c INT)
"""
DDL2 = """\
CREATE PROCEDURE IF NOT EXISTS test_procedure (IN p1 INT)
? BEGIN
? ? SELECT a, b, c FROM test_table
? ? WHERE a > p1;
? END
"""
DML1 = """DELETE FROM test_table"""
DML2 = """INSERT INTO test_table (a, b, c) VALUES (%s, %s, %s)"""
CALL1 = """CALL test_procedure(:param)"""
conn = mysql.connector.connect(database='test')
cur = conn.cursor()
cur.execute(DDL1)
cur.execute(DDL2)
cur.execute(DML1)
for row in DATA:
? ? cur.execute(DML2, row)
conn.commit()
conn.close()
# Call the procedure
engine = sa.create_engine('mysql+mysqlconnector:///test')
Session = orm.scoped_session(orm.sessionmaker(autocommit=False, autoflush=False, bind=engine))
session = Session()
raw_conn = session.connection().engine.raw_connection()
cur = raw_conn.cursor()
cur.callproc('test_procedure', [1])
print('Using session')
for result in cur.stored_results():
? ? print(result.fetchall())
Session.remove()
print('Using engine directly')
raw_conn = engine.raw_connection()
cur = raw_conn.cursor()
cur.callproc('test_procedure', [1])
for result in cur.stored_results():
? ? print(result.fetchall())
最后一個觀察:在我看來,通過會話訪問的原始連接位于會話的事務上下文之外,因此使用會話所做的更改可能對使用連接所做的更改不可見,具體取決于事務隔離設置。
添加回答
舉報