SQL-запрос останавливается при отправке из Access VBA - PullRequest
0 голосов
/ 31 октября 2018

У меня есть код доступа vba, который выполняет запрос в SQL Server 14.0. Однако он проходит около 20 минут, прежде чем просто остановить запрос и перейти к следующей строке моего кода VBA.

Если я копирую код прямо в SQL и запускаю его там, он работает без проблем. Первоначально я думал, что это связано с тайм-аутом соединения или команды, однако обычно это должно было генерировать сообщение об ошибке (и даже в этом случае я установил таймауты на 0, чтобы заставить их работать бесконечно).

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

Он завершает 3 цикла курсора, но затем запускает следующий, а затем просто останавливается.

Надеюсь, код имеет смысл, он довольно длинный, и мне пришлось разбить его на части, используя разрывы строк, чтобы облегчить расшифровку моей строки SQL и (попытку) ее отладки.

''...Declare all relevant variables above...

On Error GoTo 0

SQL_STR1 = "DECLARE @STRSQL AS Varchar(max) " & vbCrLf & _
           "DECLARE @TableName VARCHAR(50) " & vbCrLf & _
           "DECLARE LoopVal CURSOR FOR SELECT TableName_ FROM [DBASE_NAME].[dbo].[a_Base_Year_Matrices] " & vbCrLf & _
           "OPEN LoopVal " & vbCrLf & _
           "FETCH NEXT FROM LoopVal INTO @TableName " & vbCrLf & _
           "WHILE @@FETCH_STATUS = 0 " & vbCrLf & _
           "BEGIN " & vbCrLf & _


SQL_STR2 = "SET @STRSQL = " 

          '...Create Some Tables...

           "WHILE (@COUNTT < 1959 AND @COUNTTER < 150)" & vbCrLf & _
           "BEGIN" & vbCrLf & _

          '...Runs loops to meet conditions, once met drop unneeded tables and create final output...


SQL_STR3 = "EXEC(@STRSQL) " & vbCrLf & _
           "FETCH NEXT FROM LoopVal INTO @TableName " & vbCrLf & _
           "END " & vbCrLf & _
           "CLOSE LoopVal " & vbCrLf & _
           "DEALLOCATE LoopVal "

SQL_ALL = SQL_STR1 + SQL_STR2 + SQL_STR3

Set cnn = New ADODB.Connection
Set rs = New ADODB.Recordset

'Set SQL Server Location
cnn.ConnectionTimeout = 0
cnn.Open "Driver={SQL Server};Server=" & ServerName & ";Trusted_Connection=Yes;"
Set rs.ActiveConnection = cnn

DoCmd.SetWarnings False
cnn.CommandTimeout = 0

''Code to check to paste directly into SQL
''Debug.Print SQL_ALL

rs.Open SQL_ALL, cnn, adOpenForwardOnly

Next b

Next a

End Sub

1 Ответ

0 голосов
/ 31 октября 2018

Запустите ваш SQL-скрипт с помощью оператора SET NOCOUNT ON;;

Это подавит весь обмен сообщениями с сервером и разрешит набор результатов в открываемый вами набор записей.

....
SQL_STR1 = "SET NOCOUNT ON; " & vbCrLf & _
           "DECLARE @STRSQL AS Varchar(max) " & vbCrLf & _
           "DECLARE @TableName VARCHAR(50) " & vbCrLf & _
           "DECLARE LoopVal CURSOR FOR SELECT TableName_ FROM [DBASE_NAME].[dbo].[a_Base_Year_Matrices] " & vbCrLf & _
           "OPEN LoopVal " & vbCrLf & _
           "FETCH NEXT FROM LoopVal INTO @TableName " & vbCrLf & _
           "WHILE @@FETCH_STATUS = 0 " & vbCrLf & _
           "BEGIN " & vbCrLf & _
....

SET NOCOUNT ON подавляет сообщение «затронутые xx строки» после любого DML. Это набор результатов, и при отправке клиент (в данном случае ваш набор записей ADO) должен его обработать. Проще говоря, объект набора записей не обрабатывает эти серверные сообщения - он ожидает курсор, который представляет записи из базовой таблицы, результаты запроса или ранее сохраненный набор записей. Когда ваш набор записей вернет серверные сообщения, он просто даст вам пустой набор записей. Я предполагаю, что ваш VBA не ожидает пустой набор записей, и у вас есть какой-то блок кода, который застревает, когда возникает это условие? Трудно сказать, не видя ВСЕ VBA.

Установка NoCount ON заставляет сервер переходить к хорошей вещи - в данном случае к результатам запроса, - который должен обрабатывать объект набора записей.

...