亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在 sqlalchemy 范圍會話中執行 MySQL 存儲過程以返回單個數據結果集

如何在 sqlalchemy 范圍會話中執行 MySQL 存儲過程以返回單個數據結果集

喵喵時光機 2023-10-11 15:36:44
我發現調用 MySQL 存儲過程并在 python 中存儲結果的大多數示例都使用callproc帶有 a 的方法cursor,但該callproc方法不存在于scoped_session使用 sqlalchemy 創建的對象上。我使用 a 是scoped_session因為我正在構建一個 Flask 應用程序,它將在應用程序的不同部分使用會話(作用域會話適用于簡單的選擇語句)。存儲過程進行一項選擇并返回數據。我正在使用 mysql.connector 作為 mysql 驅動程序。我在燒瓶路線中嘗試了以下方法,但出現錯誤:mysql_engine = create_engine(conn_string)DbSession = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=mysql_engine))@app.route('/')def index():    # register session    DbSession()    sql = 'call myStoredProc(:param);'    # call stored procedure: getting error "Use multi=True when executing multiple statements"    result = DbSession.execute(sql, {'param': 'param value'})    data = [dict(r) for r in result]    # remove session from register    DbSession.remove()    # pass data to template to render    return render_template('index.html', data = data)如代碼所示,我收到此錯誤:“執行多個語句時使用 multi=True?!?我了解到 mysq.connector 假設存儲過程有一個 out 參數,因此默認情況下認為它是多語句,即使存儲過程只是運行單個選擇查詢。execute的方法不DbSession接受選項。錯誤中的建議是使用cmd_query_iter多個語句,但這在 DbSession 對象上也不存在。關于如何執行此操作有什么建議嗎?
查看完整描述

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())

最后一個觀察:在我看來,通過會話訪問的原始連接位于會話的事務上下文之外,因此使用會話所做的更改可能對使用連接所做的更改不可見,具體取決于事務隔離設置。


查看完整回答
反對 回復 2023-10-11
  • 1 回答
  • 0 關注
  • 152 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號