繁体   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