Що таке "партія", і чому використовується GO?


134

Я читав і читав через MSDN і т. Д. Добре, це сигналізує про закінчення партії.

Що визначає партію? Я не бачу, чому мені потрібно йти, коли я вставляю в купу сценаріїв, щоб запуститись все одночасно.

Я ніколи не розумів GO. Чи може хтось пояснити це краще, і коли мені потрібно використовувати його (після кількості або якого типу транзакцій)?

Наприклад, навіщо мені потрібно GO після кожного оновлення тут:

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

 GO

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


FWIW, здається, ніби goтакож скидає / очищає declare @fooдекларації змінних - я отримував вам потрібно оголошувати помилки @foo , поки я не прокоментував go.
JL Peyret

Відповіді:


107

GOце НЕ правильно команда TSQL.

Натомість це команда конкретній клієнтській програмі, яка підключається до сервера SQL (Sybase або Microsoft - не впевнений, що робить Oracle), сигналізуючи клієнтській програмі про те, що набір команд, які були введені до неї, до необхідності "йти" відправити на сервер для виконання.

Навіщо / коли це потрібно?

  • GO на сервері MS SQL має параметр "count" - тому ви можете використовувати його як ярлик "повторити N разів".

  • Надзвичайно великі оновлення можуть заповнити журнал SQL-сервера. Щоб цього уникнути, можливо, їх потрібно буде розділити на менші партії через go.

    У вашому прикладі, якщо оновлення для набору кодів країн має такий об'єм, що в ньому не вистачить простору журналу, рішення полягає в тому, щоб відокремити кожен код країни на окрему транзакцію - що можна зробити, розділивши їх на клієнта з go.

  • Деякі оператори SQL ОБОВ'ЯЗКОВО відокремити GO від наступних, щоб працювати.

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

> 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 без помилок будуть скоєні. Це щось хитро.
ТЗ

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 і двигун не розпізнається.

Це два конкретні приклади щоденного використання партій.

Редагувати: У вашому прикладі вам не потрібен GO ...

Редагуйте 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

Іноді виникає потреба виконувати одну і ту ж команду або набір команд знову і знову. Це може бути вставлення або оновлення тестових даних, або може бути навантаження на сервер для тестування продуктивності. Незалежно від необхідності, найпростіший спосіб зробити це - налаштувати цикл і виконувати свій код, але в 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 (наприклад, у збереженій процедурі) ... Це означає, що ви знову перебуваєте в "чистому" стані ... eG: Параметри, що використовуються в операторі до скидання коду ( більше не визначено)


Гаразд, так навіщо вам ГО. Отже, ви знаєте, що таблиця була створена до запуску оператора insert? Я досі не розумію.
PositiveGuy

Дивіться, як я думаю про це, це те, що якщо я не маю ГО у вашому прикладі, Таблиця створюється спочатку, вона є зараз, тому вставка повинна працювати. Я не розумію, що таке GO, якщо я створив таблицю ... вона доступна для наступної вставки, чи не так?!?!?!
PositiveGuy

2
@coffeeaddict: ні. "партія" аналізується і складається за один раз. Під час компіляції dbo.TEST не існує. Ви не створюєте об'єкт, і SQL не відповідає рядку процедурного коду
gbn

3

Як уже всі говорили, "GO" не є частиною T-SQL. "GO" - це пакетний роздільник у SSMS , клієнтська програма, яка використовується для подання запитів до бази даних. Це означає, що оголошені змінні та табличні змінні не зберігатимуться від коду до "GO" до коду, що слідує за ним.

Насправді GO - це просто слово за замовчуванням, яке використовується SSMS. Це можна змінити в опціях, якщо ви хочете. Щоб трохи розважитися, змініть параметр у чужій системі, щоб використовувати "SELECT" як сепаратор пакетів замість "GO". Пробач мою жорстоку посмішку.


1
Тут насправді слід серйозно сказати: Ви повинні ставитися до GO так, ніби це ключове слово, хоча це не так. Ви також ніколи не повинні її змінювати. Помилки, викликані повторним використанням спеціальних ідентифікаторів, можуть бути важкими для налагодження.
Jørgen Fogh

@ Dixie Flatline: ви впевнені, що заявлені змінні не зберігаються? У MSSQL 2016 я отримую помилку "змінна вже оголошена" при запуску: оголосити $ 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.