2016-06-16 5 views
4

Я запускаю ряд сложных sql-запросов в python и включает временные таблицы. Мой метод автоматической фиксации, похоже, не работает для извлечения данных из таблицы temp. Фрагмент кода, я использую ниже, и это выход я получаю:Временная таблица SQL Server не доступна в коде pyobbc

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

ответ

2

Несмотря на то, что этот вопрос имеет «решение», то есть, используя глобальную таблицу темп вместо локальной таблицы темп, будущие читатели могут извлечь выгоду из понимания того, почему проблема произошла в первую очередь.

Временная таблица автоматически отбрасывается, когда последнее соединение, использующее указанную таблицу, закрывается. Разница между локальной таблицей temp (#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 без закрытия первого.

Второе соединение не может видеть локальную таблицу темп, создаваемую первым соединением. Обратите внимание, что локальная таблица temp все еще существует, потому что первое соединение никогда не было закрыто, но второе соединение не может его увидеть.

Однако второе соединение может видеть глобальную таблицу темп, поскольку первое соединение никогда не было закрыто, и поэтому глобальная таблица темпов продолжала существовать.

Этот тип поведения имеет последствия для ORM и других механизмов, которые могут неявно открывать и закрывать соединения с сервером для каждого выполняемого им оператора SQL.

1

Я спросил коллегу об этом в прямом эфире и его предложения работали. Поэтому я пошел и изменил testQuery, чтобы создать глобальную таблицу temp вместо локальной (## Temp1 вместо # Temp1). И отправился на сервер sql, чтобы проверить, действительно ли была создана таблица temp - это было. Поэтому я выделил, что проблема была второй инструкцией 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] 
+0

Вы также выяснили, почему глобальные таблицы temp работают, а локальные - нет? У меня также была аналогичная проблема, когда мне приходилось создавать несколько временных таблиц. Первая рабочая таблица работала, но в последующих не было. Использование метода создания глобальных временных таблиц сделало трюк – Alex

0

Лучший способ пойти об этом, чтобы начать свой SQL запрос с:

«SET NOCOUNT ON»

Это будет выводить нужные данные