[英]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.