Есть ли способ заставить SQL-сервер проверять ссылки на объекты в хранимых процессах? - PullRequest
3 голосов
/ 06 января 2010

Следующий код прекрасно работает в SQL Server

create proc IamBrokenAndDontKnowIt as
select * from tablewhichdoesnotexist

Конечно, если я попытаюсь запустить его, произойдет сбой с

Неверное имя объекта 'tablewhichdoesnotexist'.

Есть ли способ скомпилировать или проверить, что сохраненный процесс действителен?

Ответы [ 7 ]

1 голос
/ 06 января 2010

Нет (но читайте дальше, см. Последнюю строку)

Это дизайн: Отложенное разрешение имен

Эрланд Соммарског поднял MS Connect для SET STRICT_CHECKS ON

Запрос на подключение имеет обходной путь (сам не пробовал):

Использовать план выполнения проверки. Единственный Слабость в том, что вам может понадобиться разрешения, чтобы увидеть план выполнения первый

1 голос
/ 06 января 2010

Вы получали предупреждение, когда пытались создать такую ​​хранимую процедуру. Было бы сказать:

Невозможно добавить строки в 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-футовым шестом.

1 голос
/ 06 января 2010

Вы можете использовать

SET FMTONLY ON
EXEC dbo.My_Proc
SET FMTONLY OFF

Вам нужно каким-то образом фиксировать ошибки, но не нужно много времени, чтобы собрать быстрое служебное приложение, которое использует это для поиска недопустимых хранимых процедур.

Я не использовал это широко, поэтому я не знаю, есть ли какие-либо побочные эффекты, на которые стоит обратить внимание.

0 голосов
/ 17 апреля 2010

Я только что обнаружил, что VS2010 с проектами баз данных будет выполнять проверку синтаксиса и ссылок на имена. Похоже, лучший вариант.

0 голосов
/ 06 января 2010

В SQL 2005 или выше вы можете протестировать хранимую процедуру с помощью транзакций и попробовать / перехватить:

BEGIN TRANSACTION

BEGIN TRY
  EXEC (@storedproc)
  ROLLBACK TRANSACTION
END TRY
BEGIN CATCH
  WHILE @@TRANCOUNT > 0
    ROLLBACK
END CATCH

Алгоритм тестирования всех хранимых процедур в базе данных немного сложнее, так как вам нужно обойти ограничения SSMS, если у вас много SP, которые возвращают множество наборов результатов. Смотрите мой блог для полного решения .

0 голосов
/ 06 января 2010

Вы можете проверить information_schema.tables, чтобы проверить, существует ли таблица или нет, а затем выполнить код

вот быстро переключаемая функция для проверки

 create function fnTableExist(@TableName varchar(64)) returns int as
    begin
        return (select count(*) from information_schema.tables where table_name=@tableName and Table_type='Base_Table')
    end

go        

    if dbo.fnTableExist('eObjects') = 0 
        print 'Table exist'
    else
        print 'no suchTable'

также можно проверить наличие сохраненных процедур / функций в

.INFORMATION_SCHEMA.ROUTINES.Routine_name для имени хранимой процедуры / функции

0 голосов
/ 06 января 2010

Вы можете запустить sp_depends (см. http://msdn.microsoft.com/en-us/library/ms189487.aspx) и использовать эту информацию для запроса информационной схемы (http://msdn.microsoft.com/en-us/library/ms186778.aspx), чтобы увидеть, существуют ли все объекты. Из того, что я прочитал здесь (http://msdn.microsoft.com/en-us/library/aa214346(SQL.80).aspx) вам нужно только проверить ссылочные таблицы, что выполнимо.

...