Синтаксическая ошибка хранимой процедуры во время перекомпиляции перехватывается функцией Catch и возвращает пустой набор результатов

Я пытаюсь изолировать проблему (которая напоминает тему на stackoverflow.com/q/483787/537284). Проблема связана с хранимой процедурой и возникает «случайно» раз в неделю. Чтобы попытаться воспроизвести проблему, я создал разные версии процедуры, чтобы имитировать хорошие и плохие возможные результаты:

  • Хороший многострочный одиночный набор результатов.
  • Хороший многострочный однострочный набор результатов с информационным сообщением.
  • Хороший однострочный набор результатов с Raiserror (уровень ниже 11).
  • Хороший многострочный однострочный набор результатов с Print.
  • Хороший пустой одиночный набор результатов.
  • Плохая синтаксическая ошибка.
  • Неверная синтаксическая ошибка с try/catch.
  • Плохая ошибка с Raiserror (уровень 11).
  • Плохая ошибка с Raiserror (уровень 11) и try/catch.

Между этими тестами синтаксическая ошибка с версией try/catch вела себя не так, как я ожидал. Возвращаются два набора результатов (один пустой, а другой из инструкции catch).

Синтаксическая ошибка выполняется частично? Я ожидал результата блока catch, а не попытки. Я сравнил это с Raiserror и, используя серьезность 11, он запускает блок catch с возвратом только одного набора результатов. В чем разница между синтаксической ошибкой и Raiserror?

Вот моя процедура тестирования:

AS
BEGIN
    SET NOCOUNT ON
    SET ANSI_WARNINGS ON    
    SET IMPLICIT_TRANSACTIONS OFF 
    SET XACT_ABORT OFF 
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

BEGIN TRY
    --RAISERROR ('goes to message tab yes?', 11, 1) WITH NOWAIT
    SELECT '1' [myfield] FROM test_fulltext (nolock) WHERE CONTAINS(Command,'a monkey')
    RETURN 0
END TRY
BEGIN CATCH
    SELECT ERROR_NUMBER() [ErrorNumber]
END CATCH
RETURN -9999
END

Вот моя тестовая таблица (вырвана из других):

CREATE TABLE test_fulltext 
( 
    SPID INT NOT NULL, 
    Status VARCHAR(32) NULL, 
    Login SYSNAME NULL, 
    HostName SYSNAME NULL, 
    BlkBy SYSNAME NULL, 
    DBName SYSNAME NULL, 
    Command VARCHAR(32) NULL, 
    CPUTime INT NULL, 
    DiskIO INT NULL, 
    LastBatch VARCHAR(14) NULL, 
    ProgramName VARCHAR(32) NULL, 
    SPID2 INT 
)
CREATE UNIQUE INDEX fulltextui ON test_fulltext(SPID);
CREATE FULLTEXT CATALOG fulltextft AS DEFAULT;
CREATE FULLTEXT INDEX ON test_fulltext(Command) KEY INDEX fulltextui;

person patterns    schedule 10.12.2010    source источник


Ответы (1)


Обязательно полностью прочитайте раздел «Примечания» в TRY...CATCH в электронной документации. Это объясняет это поведение в болезненных деталях.

Чего я не понимаю, так это всей этой истории с «вызовом синтаксической ошибки»… Если это в хранимой процедуре, и у вас в ней есть синтаксическая ошибка, SP даже не будет создан. Может быть, вы на самом деле выполняете более старую версию хранимой процедуры?

person Dave Markle    schedule 10.12.2010
comment
Спасибо за статью. Это очень полезно. Он отвечает на вопрос о разнице между Raiserror и синтаксической ошибкой. Я считаю, что хранимая процедура компилируется и создается, потому что синтаксическая ошибка находится внутри строки соответствия шаблону, которая должна проходить во время создания. Я постараюсь написать туда со своим вопросом. Существует объяснение перекомпиляции и отложенного разрешения имен, которое кажется наиболее близким, но все же утверждает, что ошибка не будет перехвачена уловом и вернется на исходный уровень выполнения. То, что я наблюдаю, - это выполнение catch после синтаксической ошибки. - person patterns; 10.12.2010