TSQL - создать сохраненный процесс внутри оператора транзакции - PullRequest
7 голосов
/ 26 апреля 2010

У меня есть сценарий sql, который настроен на запуск в производство. Я обернул различные проекты в отдельные транзакции. В каждой из транзакций мы создали хранимые процедуры. Я получаю сообщения об ошибках

Сообщение 156, Уровень 15, Состояние 1, Строка 4 Неверный синтаксис рядом с ключевым словом «процедура».

Я создал этот пример сценария для иллюстрации

Begin Try
Begin Transaction 
    -- do a bunch of add/alter tables here
    -- do a bunch of data manipulation/population here

    -- create a stored proc
  create procedure dbo.test
  as
  begin
    select * from some_table
  end
Commit  
End Try
Begin Catch
    Rollback  
    Declare @Msg nvarchar(max)
    Select @Msg=Error_Message();
    RaisError('Error Occured: %s', 20, 101,@Msg) With Log;
End Catch

Ошибка, по-видимому, означает, что я не могу создать хранимые процы внутри транзакции, но я не нахожу никаких документов, которые говорят иначе (возможно, Google не дружелюбный сегодня).

Ответы [ 4 ]

12 голосов
/ 26 апреля 2010

попробуйте выполнить create procedure in EXEC('...'), например:

Begin Try
Begin Transaction 
    -- do a bunch of add/alter tables here
    -- do a bunch of data manipulation/population here

    -- create a stored proc
  EXEC ('create procedure dbo.test
  as
  begin
    select * from some_table
  end')
Commit  
End Try
Begin Catch
    Rollback  
    Declare @Msg nvarchar(max)
    Select @Msg=Error_Message();
    RaisError('Error Occured: %s', 20, 101,@Msg) With Log;
End Catch

GO
10 голосов
/ 26 апреля 2010

Вы не можете написать свой сценарий таким образом, так как есть много операторов, которые должны выполняться в их собственном пакете. Вместо этого я бы порекомендовал сделать что-то похожее на то, как SQL Compare в Red-Gate строит свои скрипты:

Set Xact_Abort On
GO
Begin Transaction 
GO
If object_id('tempdb..#tmpErrors') is not null
    Drop Table #tmpErrors
GO
Create Table #tmpErrors( [Error] int not null )
GO
Create Procedure dbo.Test
As
Begin
    --....
End
GO
If @@Error <> 0 AND @@TranCount >0 Rollback Transaction
GO
IF @@TranCount = 0 Begin Insert #tmpErrors (Error) Select 1 Begin Transaction End
GO

-- more statements

GO
If @@Error <> 0 AND @@TranCount >0 Rollback Transaction
GO
IF @@TranCount = 0 Begin Insert #tmpErrors (Error) Select 1 Begin Transaction End
GO

--.....

IF NOT EXISTS(SELECT * FROM #tmpErrors)
    BEGIN
        PRINT 'The database update succeeded'
        IF @@TRANCOUNT > 0 COMMIT TRANSACTION
    END
ELSE 
    BEGIN
        PRINT 'The database update failed'
        IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION
    END
GO

DROP TABLE #tmpErrors
GO
2 голосов
/ 08 ноября 2011

Существуют различные проблемы с решением, предложенным KM:

  • Если содержимое того, что вы вводите в вызов EXEC (), семантически неверно (например, вы помещаете несуществующую таблицу в FROM внутри хранимой процедуры), эта ошибка не всплывает и транзакция не откатывается.

  • Если содержимое того, что вы указали в вызове EXEC (), синтаксически неверно (например, вы помещаете SELECTT вместо SELECT в хранимую процедуру), транзакция, похоже, откатывается, но пузыри с полной загадкой до:

    A transport-level error has occurred when receiving results from the server. (provider: TCP Provider, error: 0 - The specified network name is no longer available.)
    

Так что я все еще не знаю, как создать процедуру внутри транзакции, но транзакция и try-catch будут полезны.

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

Кажется, я помню, что вы не можете делать такие вещи, как создание, изменение или удаление объектов схемы базы данных & mdash; в том числе хранимые процедуры & mdash; внутри транзакции (поскольку такие структурные изменения не являются транзакциями: вы не можете откатить их с изменениями данных).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...