2015-12-09 4 views
6

Можем ли мы использовать инструкцию GO несколько раз в SQL Transaction. У меня длинный сценарий T-SQL, и я хочу запустить его в SQL Transaction. Если все пойдет хорошо, то я сделаю иначе, откат.Можем ли мы использовать «GO» несколько раз в транзакции SQL?

Но, выполняя этот запрос, я получил ошибку, например 'create function must be the only statement in the batch'. Поскольку я создаю и отбрасываю много функций и процедур в этом.

Я не использовал GO в любом месте сценария. Мой вопрос в том, что: могу ли я использовать несколько раз GO в этом длинном сценарии. Потому что GO создает партию, и если пакет запускается успешно в первый раз, но сбой в следующий раз, то оператор rollback transaction сможет выполнить фактический откат, который был выполнен?

Структура моего сценария выглядит следующим образом:

PRINT 'Transaction Started' 
BEGIN TRY 
    BEGIN TRAN 

    Drop Function 
    .... 
    .... 
    Create Function 
    .... 
    .... 
    Drop Procedure 
    .... 
    .... 
    Lots of statements 
    .... 
    .... 

    COMMIT TRAN 
    PRINT 'Transaction Succeeded' 
END TRY 
BEGIN CATCH 
    PRINT 'Transaction Failed' 
    IF(@@TRANCOUNT > 0) 
     ROLLBACK TRAN 
END CATCH 

Я создаю этот сценарий, чтобы перенести некоторые изменения из NEWDB в oldDB в одном сценарии.

+0

Вы создаете хранимую процедуру или функцию в этом сценарии? – Dane

+0

Я обновил свой ответ. В любом случае .. Я создаю и отбрасываю оба. Сначала проверьте, существуют они или нет. –

+0

Попробуйте этот ответ здесь: http://stackoverflow.com/a/11121382/249813 – JamesT

ответ

16

Вы смешиваете концепции. GO не является концепцией Transact-SQL, а не частью языка и не понимается SQL Server. GO - это инструменты разделитель партии. sqlcmd.exe и SSMS оба используют по умолчанию GO в качестве разделителя партии. Разделитель партии используется для идентификации отдельных пакетов внутри исходного файла SQL. Клиентский инструмент посылает серверу одну партию одновременно (разумеется, исключая разделитель).

Сделки могут охватывать партии. Блоки TRY/CATCH не могут. Операторы CREATE/ALTER должны быть единственным оператором в пакете (комментарии не являются инструкциями, а утверждения, содержащиеся в теле процедуры функции, содержатся, впрочем, содержатся).

Нечто похожее на то, что вы хотите сделать, может быть достигнут путем запуска транзакции и abortign выполнения на первые ошибках (-b в sqlcmd.exe начала, или использовать :on error exit in SSMS).

Но выполнение DDL внутри длинных транзакций не сработает. Специально, если вы планируете смешивать его с DML. Большинство коррупции, которые я должен был исследовать, пришли из этой комбинации (Xact, DDL + DML, rollback). Я категорически против этого.

Единственный способ безопасного развертывания обновлений схемы - это сделать резервную копию, развернуть, восстановить из резервной копии, если что-то пойдет не так.

Обратите внимание, что то, что рекомендует Dan (динамический SQL), потому что sp_executesql запускает новый, внутренний, пакетный. Эта партия будет удовлетворять ограничениям CREATE/ALTER.

+0

отличное объяснение. удивительные предложения. Большое спасибо @Remus !! –

1

GO - хорошее ключевое слово для использования. GO завершит последний блок кода и перейдет к следующему блоку. Да, вы можете использовать несколько GO в заявлении, чтобы разбить его на несколько партий. Но было бы лучше использовать логику try/catch с комбинацией GO, поскольку вы выполняете транзакционную логику. https://msdn.microsoft.com/en-us/library/ms175976.aspx Этот сайт дает вам несколько примеров использования мотыги для использования, и если вы столкнетесь с зацеплением, вы можете вывести эту ошибку и продолжить, если вы выберете.

2

Отметьте, что GO is not a SQL keyword. Это пакетный разделитель на стороне клиента, используемый SQL Server Management Studio и другими клиентскими инструментами.

GO не влияет на объем транзакции. BEGIN TRAN начнет транзакцию по текущему соединению. COMMIT и ROLLBACK прекратят транзакцию. Вы можете выполнить столько операторов, сколько хотите. GO будет выполнять инструкции отдельно.

Как указано MSDN:

попробовать ... CATCH конструкция не может охватывать несколько партий.

Таким образом, НАЧАТЬ TRY, END TRY, BEGIN CATCH и END CATCH не могут быть разделены на отдельные партии разделителем GO. Они должны появляться в одном запросе.

Если попытаться включить пакетный разделитель в TRY/CATCH заявление как недействительного SQL ниже:

begin try 
    go 
end try 
begin catch 
    go 
end catch 

Это будет выполнять 3 различных запросов, которые возвращают ошибки синтаксиса:

1) begin try

Msg 102, Level 15, State 1, Line 1 
Incorrect syntax near 'begin'. 

2) end try begin catch

Msg 102, Level 15, State 1, Line 3 
Incorrect syntax near 'try'. 

3) end catch

Msg 102, Level 15, State 1, Line 6 
Incorrect syntax near 'catch'. 
Смежные вопросы