Вам нужно TRY CATCH
вне динамического SQL.
Отображаемое сообщение об ошибке: разбор раз, еще до того, как оно выполнится (для этого оператора EXEC
).В этот момент механизм проверяет, существуют ли таблицы и объекты, и если нет, то возвращается ошибка.Выполнение никогда не начинается, поэтому оно никогда не попадет в раздел CATCH
.Вот почему TRY CATCH
должен находиться за пределами динамического SQL, потому что весь динамический SQL будет отклонен после синтаксического анализа.
Полученное сообщение об ошибке исходит из запроса, подобного следующему:
EXEC('SELECT * FROM [SomeLinkedServer].DatabaseName.SchemaName.NonExistingTable')
Сообщение 7314, уровень 16, состояние 1, строка 1 Поставщик OLE DB "SQLNCLI11" для связанного сервера "SomeLinkedServer" не содержит таблицу "" DatabaseName "." SchemaName "."NonExistingTable"».Таблица либо не существует, либо текущий пользователь не имеет разрешений для этой таблицы.
Если вы можете обернуть это в TRY CATCH
, поток управления перейдет к улову, так как серьезностьошибки достаточно высоки:
BEGIN TRY
EXEC('SELECT * FROM [SomeLinkedServer].DatabaseName.SchemaName.NonExistingTable')
END TRY
BEGIN CATCH
SELECT 'This is the catch section'
END CATCH
Обратите внимание на разницу по сравнению со следующим примером без динамического SQL:
BEGIN TRY
SELECT 1 FROM [SomeLinkedServer].DatabaseName.SchemaName.NonExistingTable
END TRY
BEGIN CATCH
SELECT 1
END CATCH
Сообщение 208, Уровень 16, Состояние 1, Строка 3 Неверное имя объекта 'DatabaseName.SchemaName.NonExistingTable'.
Это происходит потому, что весь пакет отклоняется после анализа, поэтомуон не может перейти на CATCH
, так как он никогда не начинал выполнение.Когда вы используете динамический SQL, анализ, компиляция и выполнение динамической части происходит в точке EXEC
(и именно поэтому она является динамической), задерживая выдачу ошибки, чтобы ее можно было перехватить.
Я не могу предоставить полный фиксированный код, потому что то, что вы опубликовали, не завершено.Но вы должны быть в состоянии игнорировать ошибки, если вы будете следовать этому руководству:
DECLARE @Variable ...
DECLARE MyCursor CURSOR FOR ...
FETCH NEXT FROM MyCursor INTO @Variable
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRY
DECLARE @DynamicSQL VARCHAR(MAX) = ... -- The DynamicSQL may have another TRY CATCH inside
EXEC(@DynamicSQL)
END TRY
BEGIN CATCH
-- Do your catch operation here, you can leave this section empty if you want (not recommended)
END CATCH
FETCH NEXT FROM MyCursor INTO @Variable
END