GO Після кожного оператора T-SQL


34

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

Мені просто цікаво, як багато документації Майкрософт тощо почали використовувати її після кожного твердження або, можливо, я тільки почав помічати.

Також, що вважається найкращою практикою?

Відповіді:


51

Перш ніж відповісти, коли його використовувати і чому, перш за все важливо зрозуміти, що саме GOє, а що ні.

Ключове слово GOвикористовується SQL Server Management Studio і SQLCMD, щоб позначити одне і лише одне: Кінець групи висловлювань. Насправді ви навіть можете змінити те, що використовуєте для припинення пакетів, на щось інше, ніж "GO":

введіть тут опис зображення

Наведений вище скріншот - це параметр у SSMS, який можна налаштувати.

Але що таке партія ?? Ця посилання на BOL найкраще говорить:

Пакет - це група одного або декількох операторів Transact-SQL, що надсилаються одночасно з програми на SQL Server для виконання.

Просто як це. Це просто власний спосіб, коли програма (так ... додаток) надсилає заяви на SQL Server. Давайте подивимось приклад цього прикладу. Я використовую PowerShell, щоб імітувати те, що програма буде робити для надсилання заяв і пакетів на SQL Server:

$ConnectionString = "data source = SomeSQLInstance; initial catalog = AdventureWorks2012; trusted_connection = true; application name = BatchTesting;"

try {
    $SqlConnection = New-Object System.Data.SqlClient.SqlConnection($ConnectionString)
    $SqlCmd = New-Object System.Data.SqlClient.SqlCommand
    $SqlCmd.Connection = $SqlConnection

    # first batch of statements
    #
    $SqlCmd.CommandText = "
        select * from humanresources.department where departmentid = 1;
        select * from humanresources.department where departmentid = 2;
        select * from humanresources.department where departmentid = 3;
        select * from humanresources.department where departmentid = 4;"

    # execute the first batch
    #
    $SqlConnection.Open()
    $SqlCmd.ExecuteNonQuery()
    $SqlConnection.Close()

    # second batch of statements
    #
    $SqlCmd.CommandText = "
        select * from humanresources.department where departmentid = 5;
        select * from humanresources.department where departmentid = 6;
        select * from humanresources.department where departmentid = 7;
        select * from humanresources.department where departmentid = 8;"

    # execute the second batch
    #
    $SqlConnection.Open()
    $SqlCmd.ExecuteNonQuery()
    $SqlConnection.Close()
}
catch {
    $SqlCmd.Dispose()
    $SqlConnection.Dispose()
    Write-Error $_.Exception
}

Зауваження дають це, але ви бачите вище, що ми програмно надсилаємо дві партії на SQL Server. Проте перевіримо це. Мій вибір тут - використовувати розширені події:

create event session BatchTesting
on server
add event sqlserver.sql_batch_starting
(
    set
        collect_batch_text = 1
    where
    (
        sqlserver.client_app_name = N'BatchTesting'
    )
),
add event sqlserver.sql_batch_completed
(
    set
        collect_batch_text = 1
    where
    (
        sqlserver.client_app_name = N'BatchTesting'
    )
),
add event sqlserver.sql_statement_starting
(
    set
        collect_statement = 1
    where
    (
        sqlserver.client_app_name = N'BatchTesting'
    )
),
add event sqlserver.sql_statement_completed
(
    set
        collect_statement = 1
    where
    (
        sqlserver.client_app_name = N'BatchTesting'
    )
)
add target package0.event_file
(
    set
        filename = N'<MyXelLocation>\BatchTesting.xel'
);
go

alter event session BatchTesting
on server
state = start;
go

Весь цей сеанс XEvents - це захоплення операторів та пакетів, які починаються та завершуються з програми, названої "BatchTesting"(якщо ви помітили мою рядок з'єднання в прикладі коду PowerShell, це швидкий спосіб ознайомитися з певним джерелом подій за допомогою програми " name "параметр рядка з'єднання і відфільтрування цього).

Після виконання коду PowerShell для надсилання цих пакетів та заяв я бачу такі результати:

введіть тут опис зображення

Як видно із скріншоту, зрозуміло, як твердження поділяються на дві різні партії, що також очевидно за допомогою засобів, які ми звикли називати партіями. І якщо ми подивимось batch_textна перше виникнення sql_batch_starting, ми можемо побачити всі твердження, що входять до цієї групи:

    select * from humanresources.department where departmentid = 1;
    select * from humanresources.department where departmentid = 2;
    select * from humanresources.department where departmentid = 3;
    select * from humanresources.department where departmentid = 4;

З цим поясненням , що партія є, тепер приходить відповідь на своє питання про коли припинити партію. Правила партій містяться в цій довідці про BOL щодо партій :

Висловлювання CREATE DEFAULT, CREATE FUNCTION, CREATE PROCEDURE, CREATE RULE, CREATE SCHEMA, CREATE TRIGGER і CREATE VIEW не можуть поєднуватися з іншими твердженнями в партії. Оператор CREATE повинен запустити пакет. Усі інші твердження, що випливають із цієї партії, будуть інтерпретуватися як частина визначення першого оператора CREATE.

Таблицю неможливо змінити, і тоді нові стовпці посилаються на ту саму партію.

Якщо оператор EXECUTE є першим оператором у партії, ключове слово EXECUTE не потрібно. Ключове слово EXECUTE потрібно, якщо оператор EXECUTE не є першим оператором у пакеті.

Аналогічно, деякі помилки виконання (помилки компіляції не дозволяють запустити виконання пакету), які виникають під час вибору пакета, можуть спричинити різні поведінки: повністю перервати пакет або продовжити пакет і лише перервати заяву-порушення. Посилання дає два справді хороших приклади: наприклад, арифметична помилка переповнення зупинить виконання пакету, тоді як помилка порушення обмеження лише запобіжить завершенню поточного оператора, але пакет буде продовжувати виконувати).

Як і багато речей у нашій професії, однак особисті переваги стануть величезною рушійною силою того, як ви як людина та автор T-SQL-коду припиняєте партії. Деякі люди чітко визначають партії лише тоді, коли їм це потрібно (див. Вище для цих вимог), а інші завершують партії програмно в 100% часу , навіть коли вони виконують лише одне висловлення у вікні запитів у SSMS. Більшість людей зазвичай потрапляють десь посеред цих двох меж. Для чого варто, термінатори тверджень мають те саме, що також має дуже малі вимоги. Значну частину всього цього становить стиль коду , де він не застосовується (у SSMS та SQLCMD).


Можливо, наївне зауваження, але мені вражає, що SQL Server міг сам визначати, що потрібно запускати в партіях (так само, як і багато інших оптимізацій управляє двигуном бази даних). Наприклад, використовуючи описані вами правила, а не покладаючись на користувача, щоб їх скриптувати, що може бути схильним до помилок і, здається, додає зайві розриви сценаріям.
Стів Чемберс

1
@SteveChambers точно мій настрій. У відповіді сказано, що "це так просто" (Пакет - це група одного або декількох операторів Transact-SQL, що надсилаються одночасно з програми на SQL Server для виконання.) Але це не так. Існують комбінації висловлювань, які я можу спробувати надсилати в пакеті, які не вдається. Зрештою, я думаю, що вам потрібно зрозуміти, чому і як відправка партії відрізняється від того, як надсилати набір окремих заяв - тому я, нарешті, зробив свою власну відповідь на це: stackoverflow.com/a/56370223/3714936 - що також відповідає вашому коментарю .
youcantryreachingme
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.