Когда мне нужно использовать Begin/End Blocks и ключевое слово Go в SQL Server?

Может ли кто-нибудь сказать мне, когда и где мне нужно использовать блоки begin и end в SQL Server?

Кроме того, что именно делает ключевое слово Go?

Ответ 1

GO похож на конец script.

У вас может быть несколько операторов CREATE TABLE, разделенных GO. Это способ изолировать одну часть script от другой, но передать ее все в один блок.


BEGIN и END похожи на {и} в C/++/#, Java и т.д.

Они связали логический блок кода. Я стараюсь использовать BEGIN и END в начале и в конце хранимой процедуры, но это не является строго необходимым. Там, где это необходимо, для циклов и операторов IF и т.д., Где вам нужно больше одного шага...

IF EXISTS (SELECT * FROM my_table WHERE id = @id)
BEGIN
   INSERT INTO Log SELECT @id, 'deleted'
   DELETE my_table WHERE id = @id
END

Ответ 2

Вам нужно BEGIN... END, чтобы создать блок, охватывающий более одного оператора. Итак, если вы хотите сделать 2 вещи в одной "ноге" оператора IF, или если вы хотите сделать больше, чем одну вещь в теле цикла WHILE, вам нужно скопировать эти утверждения с помощью BEGIN... END.

Ключевое слово GO не является частью SQL. Он используется только Query Analyzer для разделения скриптов на "партии", которые выполняются независимо.

Ответ 3

GO не является ключевым словом в SQL Server; это пакетный разделитель. GO завершает пакет заявлений. Это особенно полезно, если вы используете что-то вроде SQLCMD. Представьте, что вы вводите инструкции SQL в командной строке. Вы не обязательно хотите, чтобы вещь выполнялась каждый раз, когда вы заканчиваете утверждение, поэтому SQL Server ничего не делает, пока вы не введете "GO".

Аналогично, перед запуском партии вам часто нужно иметь видимые объекты. Например, предположим, что вы создаете базу данных, а затем запрашиваете ее. Вы не можете писать:

CREATE DATABASE foo;
USE foo;
CREATE TABLE bar;

потому что foo не существует для партии, которая выполняет CREATE TABLE. Вам нужно будет сделать это:

CREATE DATABASE foo;
GO
USE foo;
CREATE TABLE bar;

Ответ 4

BEGIN и END хорошо ответили другими.

Как указывает Гэри, GO - это разделитель пакетов, используемый большинством поставляемых Майкрософт клиентских инструментов, таких как isql, sqlcmd, анализатор запросов и студия управления SQL Server. (По крайней мере, некоторые из инструментов позволяют менять разделитель партии. Я никогда не видел использования для изменения разделителя партий.)

Чтобы ответить на вопрос о том, когда использовать GO, нужно знать, когда SQL должен быть разделен на партии.

Некоторые утверждения должны быть первым выражением партии.

select 1
create procedure #Zero as
    return 0

В SQL Server 2000 ошибка:

Msg 111, Level 15, State 1, Line 3
'CREATE PROCEDURE' must be the first statement in a query batch.
Msg 178, Level 15, State 1, Line 4
A RETURN statement with a return value cannot be used in this context.

В SQL Server 2005 ошибка менее полезна:

Msg 178, Level 15, State 1, Procedure #Zero, Line 5
A RETURN statement with a return value cannot be used in this context.

Итак, используйте GO для разделения операторов, которые должны быть началом пакета из операторов, предшествующих ему в script.

При запуске script многие ошибки заставят выполнение пакета останавливаться, но тогда клиент просто отправит следующую партию, выполнение script не прекратится. Я часто использую это при тестировании. Я запустил script с началом транзакции и закончил с откатом, выполнив все тестирование посередине:

begin transaction
go
... test code here ...
go
rollback transaction

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

Кроме того, если вы выполняете установку script и имеете несколько партий в одном файле, ошибка в одной партии не приведет к продолжению работы script, что может привести к беспорядку. (Всегда создавайте резервную копию перед установкой.)

В связи с тем, что указал Дэйв Маркел, бывают случаи, когда синтаксический анализ завершится неудачей, поскольку SQL Server ищет словарь данных для объектов, созданных ранее в пакете, но разбор может произойти до того, как будут запущены какие-либо операторы. Иногда это проблема, иногда нет. Я не могу придумать хороший пример. Но если вы когда-либо получаете ошибку "X не существует", когда она явно будет существовать, этот оператор разбивается на партии.

И последнее замечание. Транзакция может охватывать партии. (См. Выше.) Переменные не охватывают партии.

declare @i int
set @i = 0
go
print @i

Msg 137, Level 15, State 2, Line 1
Must declare the scalar variable "@i".

Ответ 5

GO заканчивает партию, вам очень редко нужно будет использовать ее в коде. Имейте в виду, что если вы используете его в сохраненной процедуре, после выполнения процесса не будет выполняться код после GO.

BEGIN и END необходимы для любых инструкций процедурного типа с многопрофильными строками кода для обработки. Вы будете нуждаться в них для циклов WHILE и курсоров (которых вы, конечно, избегаете, если это вообще возможно) и IF-операторов (ну, в принципе, вам не нужны они для IF-статута, который имеет только одну строку кода, но легче поддерживайте код, если вы всегда вводите его после IF). Операторы CASE также используют END, но не имеют BEGIN.

Ответ 6

После борьбы с этой проблемой сегодня мое мнение таково: BEGIN... END скобки, такие же, как {....} на языках C, например. блоки кода для if... else и циклов

GO (должно быть) используется, когда последующие утверждения полагаются на объект, определенный предыдущим оператором. База данных USE является хорошим примером выше, но следующее также укусит вас:

alter table foo add bar varchar(8);
-- if you don't put GO here then the following line will error as it doesn't know what bar is.
update foo set bar = 'bacon';
-- need a GO here to tell the interpreter to execute this statement, otherwise the Parser will lump it together with all successive statements.

Мне кажется, что проблема заключается в том, что SQL Parser SQL Server, в отличие от Oracle, не может понять, что вы определяете новый символ в первой строке и что это нормально для ссылки в следующих строках. Он не "видит" символ до тех пор, пока не встретит маркер GO, который сообщает ему, чтобы он выполнял предыдущий SQL с последнего GO, после чего символ применяется к базе данных и становится видимым для синтаксического анализатора.

Почему он не просто обрабатывает семантику как семантический разрыв и применяет заявления отдельно, я не знаю и желаю этого. Только бонус, который я вижу, заключается в том, что вы можете поместить инструкцию print() непосредственно перед GO, и если какое-либо из утверждений не будет выполнено, печать не будет выполнена. Много проблем для незначительной выгоды, хотя.