簡體   English   中英

SQL Server臨時表在pyodbc代碼中不可用

[英]SQL Server temp table not available in pyodbc code

我在python中運行了一系列復雜的sql查詢,它涉及臨時表。 我的自動提交方法似乎無法從臨時表中檢索數據。 我在下面使用的代碼片段,這是我得到的輸出:

testQuery="""
    Select top 10 *
    INTO #Temp1
    FROM Table1 t1
    JOIN Table2 t2
    on t1.key=t2.key
"""
    cnxn=pyodbc.connect(r'DRIVER={SQL Server Native Client 11.0};SERVER=server;DATABASE=DB;UID=UID;PWD=PWD')
    cnxn.autocommit=True
    cursor=cnxn.cursor()
    cursor.execute(testQuery)
    cursor.execute("""Select top 10 * from #Temp1""")
    <pyodbc.Cursor at 0x8f78930>


cnxn=pyodbc.connect(r'DRIVER={SQL Server Native Client 11.0};SERVER=server;DATABASE=DB;UID=UID;PWD=PWD')
cnxn.autocommit=True
cursor=cnxn.cursor()
cursor.execute(testQuery)
cursor.execute("""Select top 10 * from #Temp1""")

即使這個問題有一個“解決方案”,即使用全局臨時表而不是本地臨時表,未來的讀者可能會從首先理解問題發生的原因中受益。

使用所述表的最后一個連接關閉時,將自動刪除臨時表。 本地臨時表( #Temp1 )和全局臨時表( ##Temp1 )之間的區別在於本地臨時表僅對創建它的連接可見,而現有的全局臨時表可用於任何連接。

因此,使用本地臨時表的以下代碼將失敗...

conn = pyodbc.connect(conn_str, autocommit=True)
crsr = conn.cursor()

sql = """\
SELECT 1 AS foo, 2 AS bar INTO #Temp1
"""
crsr.execute(sql)

conn = pyodbc.connect(conn_str, autocommit=True)
crsr = conn.cursor()

sql = """\
SELECT foo, bar FROM #Temp1
"""
crsr.execute(sql)
row = crsr.fetchone()
print(row)

...使用全局臨時表的完全相同的代碼將成功...

conn = pyodbc.connect(conn_str, autocommit=True)
crsr = conn.cursor()

sql = """\
SELECT 1 AS foo, 2 AS bar INTO ##Temp1
"""
crsr.execute(sql)

conn = pyodbc.connect(conn_str, autocommit=True)
crsr = conn.cursor()

sql = """\
SELECT foo, bar FROM ##Temp1
"""
crsr.execute(sql)
row = crsr.fetchone()
print(row)

...因為第二個pyodbc.connect調用打開一個單獨的第二個連接到SQL Server而不關閉第一個連接。

第二個連接無法看到第一個連接創建的本地臨時表。 請注意,本地臨時表仍然存在,因為第一個連接從未關閉,但第二個連接無法看到它。

但是,第二個連接可以看到全局臨時表,因為第一個連接從未關閉,因此全局臨時表繼續存在。

這種類型的行為會影響ORM和其他機制,這些機制可能會為其執行的每個SQL語句隱式打開和關閉與服務器的連接。

我向一位同事詢問了這次活動,他的建議也奏效了。 所以我去改變testQuery來創建一個全局臨時表而不是本地(## Temp1而不是#Temp1)。 然后去sql server測試臨時表是否真正被創建 - 它是。 所以我發現問題是第二個cursor.execute語句。 我修改了代碼以使用pandas read_sql_query而且一切都解決了! 以下是我使用的代碼:

testQuery="""
    Select top 10 *
    INTO ##Temp1
    FROM Table1 t1
    JOIN Table2 t2
    on t1.key=t2.key
"""
    cnxn=pyodbc.connect(r'DRIVER={SQL Server Native Client 11.0};SERVER=server;DATABASE=DB;UID=UID;PWD=PWD')
    cnxn.autocommit=True
    cursor=cnxn.cursor()
    cursor.execute(testQuery)
    cnxn.commit()
    query1="Select top 10 * from ##Temp1"
    data1=pd.read_sql_query(query1, cnxn)
    data1[:10]

最好的方法是使用以下命令啟動SQL查詢:

“設置NOCOUNT ON”

這將輸出所需的數據

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM