Что такое «партия» и почему используется GO?


134

Я прочитал и прочитал через MSDN, и т. Д. Хорошо, таким образом, это сигнализирует об окончании пакета.

Что определяет партию? Я не понимаю, зачем мне идти, когда я вставляю в кучу скриптов, которые запускаются одновременно.

Я никогда не понимал GO. Кто-нибудь может объяснить это лучше и когда мне нужно это использовать (после того, сколько или какого типа транзакций)?

Например, зачем мне GO после каждого обновления здесь:

 UPDATE [Country]
   SET [CountryCode] = 'IL'
 WHERE code = 'IL'

 GO

 UPDATE [Country]
   SET [CountryCode] = 'PT'
 WHERE code = 'PT'


FWIW, похоже, что a goтакже сбрасывает / очищает declare @fooобъявления переменных - я получал, что вам нужно объявлять ошибки @foo , пока я не закомментировал go.
JL Peyret

Ответы:


107

GOне является правильно командой TSQL.

Это команда конкретной клиентской программы. которая подключается к SQL-серверу (Sybase или Microsoft - не уверен в том, что делает Oracle), сигнализируя клиентской программе, что набор команд, которые были введены в нее вплоть до «go», нужен быть отправленным на сервер для выполнения.

Зачем / когда тебе это нужно?

  • GO на сервере MS SQL имеет параметр «count» - так что вы можете использовать его как ярлык «повторить N раз».

  • Чрезвычайно большие обновления могут заполнить журнал сервера SQL. Чтобы избежать этого, их, возможно, нужно разделить на более мелкие партии через go.

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

  • Некоторые операторы SQL ДОЛЖНЫ быть отделены GO от следующих, чтобы работать.

    Например, вы не можете удалить таблицу и заново создать таблицу с тем же именем в одной транзакции, по крайней мере в Sybase (то же самое для создания процедур / триггеров):

> drop table tempdb.guest.x1          
> create table tempdb.guest.x1 (a int)
> go
  Msg 2714, Level 16, State 1
  Server 'SYBDEV', Line 2
  There is already an object named 'x1' in the database.   
  
> drop table tempdb.guest.x1          
> go
> create table tempdb.guest.x1 (a int)
> go
>

4
Оператор GO не создает транзакцию. Если вы включите несколько операторов GO в один оператор BEGIN TRANSACTION и, в конце концов, сделаете ROLLBACK, он откатит все GO. И если в одном GO посередине вы получите какую-то ошибку, и в конце концов вы выполните COMMIT, все GO без ошибок будут зафиксированы. Это немного сложно.
TZ

7
GOне "создать транзакцию для вас." Если вы не выполняете явную транзакцию, каждый оператор все равно создаст свою собственную транзакцию. Это полностью ортогонально. Если вы хотите разделить большее обновление на более мелкие этапы, вы все равно можете сделать это в одном пакете, как в общем WHILE @@ROWCOUNT > 0шаблоне.
Мартин Смит

3
Если вы не выполняете явную транзакцию, то UPDATE T1 SET X =2;UPDATE T1 SET X =2;все равно будете работать как две отдельные транзакции . Добавление не GOимеет абсолютно никакого значения. И точно так же , если вы будете работать в явной транзакции она охватывает партию и снова GO не имеет никакого значения.
Мартин Смит

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

4
Кроме того, поскольку некоторые ошибки прерывают пакет (некоторые ошибки только прерывают оператор), это также играет роль в обнаружении и восстановлении ошибок. И определенные заявления ( CREATE VIEWи т. Д.) Должны быть в их собственной партии.
Роберт Макки

26

GO это не утверждение, это разделитель пакетов.

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

Например, если вы пишете

DELETE FROM a
DELETE FROM b
DELETE FROM c

, он будет отправлен на сервер в виде однострочного 3запроса.

Если ты пишешь

DELETE FROM a
GO
DELETE FROM b
GO
DELETE FROM c

, это будет отправлено на сервер в виде 3однострочных запросов.

GOСам не идет на сервер (каламбур не предназначен). Это зарезервированное слово на стороне клиента и распознается толькоSSMS и osql.

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


4
Почему вы должны выпечки вообще ??
PositiveGuy

3
Итак, GO означает отправить его, а затем не запускать следующий пакет, пока клиент не получит «ОК, этот пакет завершен и был успешным», в основном это то, что делает GO, чтобы следующий пакет мог быть успешно запущен, и клиент знает, убедитесь, что пакет, прежде чем это делается на стороне сервера.
PositiveGuy

3
@coffeeaddict: в основном да. Кроме того, некоторые операторы должны быть первыми в своих пакетах (например CREATE SCHEMA); другие требуют быть единственными утверждениями в своих партиях (вроде SET SHOWPLAN_XML ON)
Quassnoi,

19

Многие команды должны быть в их собственной партии, как CREATE PROCEDURE

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

GO используется инструментами SQL для решения этой задачи из одного скрипта: это не ключевое слово SQL и не распознается механизмом.

Это 2 конкретных примера ежедневного использования партий.

Редактировать: в вашем примере вам не нужно идти ...

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

IF OBJECT_ID ('dbo.uspDoStuff') IS NOT NULL
    DROP PROCEDURE dbo.uspDoStuff
GO
CREATE PROCEDURE dbo.uspDoStuff
AS
SELECT Something From ATable
GO
GRANT EXECUTE ON dbo.uspDoStuff TO RoleSomeOne
GO

4

Иногда возникает необходимость выполнять одну и ту же команду или набор команд снова и снова. Это может быть вставка или обновление тестовых данных, или это может быть нагрузка на ваш сервер для тестирования производительности. Как бы то ни было, самый простой способ сделать это - настроить цикл while и выполнить ваш код, но в SQL 2005 есть еще более простой способ сделать это.

Допустим, вы хотите создать тестовую таблицу и загрузить ее с 1000 записями. Вы можете выполнить следующую команду, и она будет выполняться одну и ту же команду 1000 раз:

CREATE TABLE dbo.TEST (ID INT IDENTITY (1,1), ROWID uniqueidentifier)
GO
INSERT INTO dbo.TEST (ROWID) VALUES (NEWID()) 
GO 1000

источник: http://www.mssqltips.com/tip.asp?tip=1216

Кроме того, он отмечает «конец» блока SQL (например, в хранимой процедуре) ... Это означает, что вы снова в "чистом" состоянии ... Например: параметры, использованные в операторе до сброса кода ( больше не определяется)


Итак, зачем вам GO. Чтобы вы знали, что таблица была создана до выполнения оператора вставки? Я до сих пор не понимаю.
PositiveGuy

См. То, как я думаю об этом, заключается в том, что если в вашем примере у меня нет GO, сначала создается таблица, она сейчас там, поэтому вставка должна работать. Я не понимаю, для чего нужен GO, если я создал таблицу ... она доступна для следующей вставки, не так ли?!?!?!
PositiveGuy

2
@coffeeaddict: нет. «партия» анализируется и компилируется за один раз. Во время компиляции dbo.TEST не существует. Вы не создаете экземпляр объекта, а SQL не является построчным процедурным кодом
gbn

3

Как все уже говорили, «GO» не является частью T-SQL. «GO» - это пакетный разделитель в SSMS , клиентском приложении, используемом для отправки запросов в базу данных. Это означает, что объявленные переменные и табличные переменные не будут сохраняться в коде до того, как "GO" будет кодировать после него.

Фактически, GO - это просто слово по умолчанию, используемое SSMS. Это можно изменить в настройках, если хотите. Для забавы измените параметр в чужой системе, чтобы использовать «SELECT» в качестве разделителя пакетов вместо «GO». Прости мой жестокий смешок.


1
Здесь на самом деле следует сделать серьезное замечание: вы должны относиться к GO, как к ключевому слову, даже если это не так. Вы также никогда не должны менять это. Ошибки, вызванные повторным использованием специальных идентификаторов, могут быть очень сложными для отладки.
Йорген Фог

@ The Dixie Flatline: вы уверены, что объявленные переменные не сохраняются? В MSSQL 2016 я получаю ошибку «переменная уже объявлена» при запуске: Declare $ test int; установить $ test = 5; выберите $ test go; объявить $ test int; - Заменить $ на <at>, нельзя использовать несколько <at> в комментариях SE.
Wouter

0

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

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

Пытаться:

exec sp_who2  
go 2

Некоторое утверждение должно быть разграничено GO:

use DB
create view thisViewCreationWillFail
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.