SQL Server Temp Tabl在PYODBC代码中没有可用



我在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的独立第二个连接。

第二个连接看不到第一个连接创建的本地临时表。请注意,本地临时表仍然存在,因为第一个连接从未关闭,但是第二个连接看不到。

但是,第二个连接 can 请参阅全局温度表,因为第一个连接从未关闭,因此全局温度表继续存在。

这种类型的行为对ORM和其他机制具有启示,这些机制可能会隐式打开并关闭与服务器的连接,以执行每个SQL语句。

我向同事询问了这个现场,他的建议奏效了。因此,我去了测试问题以创建一个全局温度表,而不是本地(## temp1而不是#temp1)。然后去SQL Server测试是否实际创建了临时表。因此,我隔离了问题是第二个光标。我修改了代码以使用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"

这将输出所需的数据

SET NOCOUNT ON对我有用。

执行方法()-SQL Server的JDBC驱动程序|微软文档

返回值

  • 是的,如果语句返回结果集。
  • false,如果返回更新计数或没有结果。

如果您想要结果集,则设置SET NOCOUNT ON S在语句中所需的设置。

最新更新