Published on

May 7, 2001

Понимание временных таблиц в SQL Server

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

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

Давайте ближе рассмотрим фрагмент кода, который вызвал проблему:


Sub Test()
    ' Код, который не выполняется ожидаемым образом, можете ли вы понять почему?
    ' Требуется ссылка на ADO 2.6 и локальный сервер с базой данных pubs
    
    Dim cn As ADODB.Connection
    Dim rs As ADODB.Recordset
    Dim lCount As Long
    
    On Error GoTo Handler
    
    Set cn = New ADODB.Connection
    cn.Open "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=pubs;Data Source=."
    
    ' Получаем список идентификаторов, которые нас интересуют, для этого примера
    ' только те, которые относятся к авторам с фамилией, начинающейся
    ' с буквы G
    cn.Execute "select au_id into #TempIDList from authors where au_lname like 'g%'", lCount
    
    Debug.Print "# of records in temp table: "; lCount
    
    ' Теперь открываем набор записей на основе идентификаторов во временной таблице
    ' Здесь мы просто будем печатать результаты,
    ' обычно мы бы делали какое-то обновление
    Set rs = New ADODB.Recordset
    rs.Open "Select * from #TempIDList", cn
    
    Do Until rs.EOF
        Debug.Print rs!Au_ID, rs!Au_Fname, rs!Au_Lname
        rs.MoveNext
    Loop
    
    rs.Close
    Set rs = Nothing
    
    Debug.Print "Done"
    Exit Sub
    
Handler:
    Debug.Print Err.Number, Err.Description
    Resume Next
End Sub

Проблема в этом коде возникает из-за того, что временная таблица, #TempIDList, создается в той же сессии, что и последующие запросы. Когда код сталкивается с ошибкой и переходит к обработчику ошибок, он обходит код очистки, который обычно удаляет временную таблицу. В результате временная таблица сохраняется в сессии, и последующие запросы не выполняются, потому что они не могут найти временную таблицу.

Чтобы решить эту проблему, нам нужно убедиться, что временная таблица правильно очищается, независимо от того, возникает ли ошибка или нет. Один из способов сделать это – использовать блок TRY…CATCH в SQL Server. Обернув код, который создает и использует временную таблицу, в блок TRY, мы можем включить оператор DROP TABLE в блок CATCH, чтобы гарантировать, что временная таблица всегда будет удалена.

Вот обновленная версия кода, которая включает блок TRY…CATCH:


Sub Test()
    ' Код, который выполняется ожидаемым образом
    
    Dim cn As ADODB.Connection
    Dim rs As ADODB.Recordset
    Dim lCount As Long
    
    On Error GoTo Handler
    
    Set cn = New ADODB.Connection
    cn.Open "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=pubs;Data Source=."
    
    ' Получаем список идентификаторов, которые нас интересуют, для этого примера
    ' только те, которые относятся к авторам с фамилией, начинающейся
    ' с буквы G
    cn.Execute "BEGIN TRY CREATE TABLE #TempIDList (au_id VARCHAR(10)) INSERT INTO #TempIDList SELECT au_id FROM authors WHERE au_lname LIKE 'g%' END TRY BEGIN CATCH DROP TABLE IF EXISTS #TempIDList END CATCH", lCount
    
    Debug.Print "# of records in temp table: "; lCount
    
    ' Теперь открываем набор записей на основе идентификаторов во временной таблице
    ' Здесь мы просто будем печатать результаты,
    ' обычно мы бы делали какое-то обновление
    Set rs = New ADODB.Recordset
    rs.Open "Select * from #TempIDList", cn
    
    Do Until rs.EOF
        Debug.Print rs!Au_ID, rs!Au_Fname, rs!Au_Lname
        rs.MoveNext
    Loop
    
    rs.Close
    Set rs = Nothing
    
    Debug.Print "Done"
    Exit Sub
    
Handler:
    Debug.Print Err.Number, Err.Description
    Resume Next
End Sub

Используя блок TRY…CATCH, мы гарантируем, что временная таблица всегда будет удалена, даже если возникнет ошибка. Это предотвращает конфликты или проблемы при использовании временной таблицы в последующих запросах.

Понимание того, как работают временные таблицы и как правильно управлять ими, является важным при работе с SQL Server. Следуя bewt практикам и используя техники обработки ошибок, вы можете избежать потенциальных проблем и обеспечить безупречное выполнение ваших запросов.

Я надеюсь, что вы найдете эту статью полезной для понимания концепции временных таблиц в SQL Server. Если у вас есть вопросы или комментарии, пожалуйста, не стесняйтесь обращаться ко мне.

Счастливого кодирования!

Click to rate this post!
[Total: 0 Average: 0]

Let's work together

Send us a message or book free introductory meeting with us using button below.