Вы получали предупреждение, когда пытались создать такую хранимую процедуру. Было бы сказать:
Невозможно добавить строки в sysdepends для текущей хранимой процедуры, потому что это зависит от отсутствующего объекта 'dbo.nonexistenttable'. Хранимая процедура все равно будет создана.
По какой-то причине я не получаю его сейчас, я не уверен, было ли оно изменено или есть какая-то настройка, которая включает или выключает предупреждение. В любом случае, это должно дать вам подсказку о том, что здесь происходит.
SQL Server отслеживает зависимости, но только зависимости, которые действительно существуют . К сожалению, ни один из трюков с зависимостями, таких как sp_depends
или sp_MSdependencies
, работать не будет, потому что вы ищете отсутствующие зависимости.
Даже если бы мы могли гипотетически придумать способ проверки этих отсутствующих зависимостей, все равно было бы тривиально придумать что-то, чтобы победить проверку:
CREATE PROCEDURE usp_Broken
AS
DECLARE @sql nvarchar(4000)
SET @sql = N'SELECT * FROM NonExistentTable'
EXEC sp_executesql @sql
Вы также можете попробовать синтаксический анализ для выражений типа "FROM xxx", но это тоже легко победить:
CREATE PROCEDURE usp_Broken2
AS
SELECT *
FROM
NonExistentTable
На самом деле нет надежного способа проверки хранимой процедуры и проверки на отсутствие зависимостей без ее фактического запуска.
Вы можете использовать SET FMTONLY ON
, как упоминает Том Х, но имейте в виду, что это меняет способ "запуска" процедуры. Это не поймает некоторые вещи. Например, ничто не мешает вам написать такую процедуру:
CREATE PROCEDURE usp_Broken3
AS
DECLARE @TableName sysname
SELECT @TableName = Name
FROM SomeTable
WHERE ID = 1
DECLARE @sql nvarchar(4000)
SET @sql = N'SELECT * FROM ' + @TableName
EXEC sp_executesql @sql
Предположим, у вас есть реальная таблица с именем SomeTable
и реальная строка с ID = 1
, но с Name
, который не относится ни к одной таблице. Вы не получите никаких ошибок от этого, если вы поместите его в блок SET FMTONLY ON/OFF
.
Это может быть надуманной проблемой, но FMTONLY ON
делает другие странные вещи, такие как выполнение каждой ветви блока IF
/ THEN
/ ELSE
, что может вызвать другие непредвиденные ошибки, поэтому вы должны конкретно с вашей обработкой ошибок.
Единственный действительно надежный способ проверить процедуру - это запустить ее, например, так:
BEGIN TRAN
BEGIN TRY
EXEC usp_Broken
END TRY
BEGIN CATCH
PRINT 'Error'
END CATCH
ROLLBACK
Этот сценарий запустит процедуру в транзакции, предпримет некоторые действия в случае ошибки (в CATCH
) и немедленно откатит транзакцию. Конечно, даже у этого могут быть некоторые побочные эффекты, такие как изменение IDENTITY
семени, если оно вставляется в таблицу (успешно). Просто о чем стоит знать.
Если честно, я бы не стал касаться этой проблемы 50-футовым шестом.