PERGI Setelah setiap pernyataan T-SQL


34

Apa alasan di balik penggunaan pernyataan GO setelah setiap pernyataan SQL? Saya mengerti bahwa GO menandakan akhir dari batch dan / atau memungkinkan reputasi pernyataan tetapi apa untungnya menggunakannya setelah setiap pernyataan.

Saya hanya ingin tahu karena banyak dokumentasi Microsoft dll telah mulai menggunakannya setelah setiap pernyataan atau mungkin saya baru saja mulai memperhatikan.

Juga apa yang dianggap praktik terbaik?

Jawaban:


51

Sebelum menjawab kapan menggunakannya dan mengapa, yang terpenting adalah memahami apa GOitu benar, dan apa yang tidak.

Kata kunci GOdigunakan oleh SQL Server Management Studio dan SQLCMD untuk menandakan satu hal dan hanya satu hal: Akhir dari sekelompok pernyataan. Bahkan, Anda bahkan dapat mengubah apa yang Anda gunakan untuk menghentikan batch menjadi sesuatu selain "GO":

masukkan deskripsi gambar di sini

Tangkapan layar di atas adalah opsi dalam SSMS yang dapat dikonfigurasi.

Tapi apa itu batch ?? Referensi BOL ini mengatakan yang terbaik:

Batch adalah sekelompok satu atau lebih pernyataan Transact-SQL yang dikirim secara bersamaan dari aplikasi ke SQL Server untuk dieksekusi.

Sederhana seperti itu. Itu hanya cara kustom aplikasi (ya ... aplikasi) mengirim pernyataan ke SQL Server. Mari kita lihat contoh aplikasi yang tampak ini. Saya akan menggunakan PowerShell untuk meniru apa yang akan dilakukan aplikasi untuk mengirim pernyataan dan kumpulan ke 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
}

Komentar memberikannya, tetapi Anda dapat melihat di atas bahwa kami secara terprogram mengirim dua batch ke SQL Server. Mari kita verifikasi itu. Pilihan saya di sini adalah menggunakan Acara yang Diperpanjang:

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

Semua sesi XEvents ini lakukan adalah menangkap pernyataan dan kumpulan yang dimulai dan selesai dari aplikasi bernama "BatchTesting"(jika Anda melihat string koneksi saya dalam contoh kode PowerShell saya, ini adalah cara cepat untuk melihat pencetus peristiwa tertentu dengan menggunakan aplikasi " name "parameter string koneksi dan memfilternya).

Setelah saya menjalankan kode PowerShell untuk mengirim kumpulan dan pernyataan itu, saya melihat hasil berikut:

masukkan deskripsi gambar di sini

Seperti yang dapat Anda lihat dari tangkapan layar, jelas bagaimana pernyataan dibagi menjadi dua kelompok berbeda, juga terbukti dengan cara yang kami gunakan untuk memanggil kumpulan. Dan jika kita melihat pada batch_textkemunculan pertama dari sql_batch_starting, kita dapat melihat semua pernyataan termasuk dalam kelompok itu:

    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;

Dengan penjelasan tentang apa itu batch, sekarang muncul jawaban untuk pertanyaan Anda kapan harus mengakhiri batch. Aturan untuk batch ditemukan pada referensi BOL ini mengenai batch :

BUAT DEFAULT, MENCIPTAKAN FUNGSI, MENCIPTAKAN PROSEDUR, MENCIPTAKAN ATURAN, MENCIPTAKAN SKEMA, MENCIPTAKAN PEMICU, dan CREATE VIEW pernyataan tidak dapat digabungkan dengan pernyataan lain dalam satu batch. Pernyataan CREATE harus memulai batch. Semua pernyataan lain yang mengikuti dalam kumpulan itu akan ditafsirkan sebagai bagian dari definisi pernyataan CREATE pertama.

Tabel tidak dapat diubah dan kemudian kolom baru direferensikan dalam batch yang sama.

Jika pernyataan EXECUTE adalah pernyataan pertama dalam suatu batch, kata kunci EXECUTE tidak diperlukan. Kata kunci EXECUTE diperlukan jika pernyataan EXECUTE bukan pernyataan pertama dalam batch.

Demikian juga, kesalahan runtime tertentu (kompilasi kesalahan tidak akan memungkinkan pelaksanaan batch untuk memulai) yang terjadi selama batch dapat menyebabkan perilaku yang berbeda: untuk membatalkan batch secara total, atau untuk melanjutkan batch dan hanya membatalkan pernyataan yang menyinggung (di atas tautan memberikan dua contoh yang sangat bagus: Kesalahan overflow aritmatika, misalnya, akan menghentikan eksekusi bets, sedangkan kesalahan pelanggaran kendala hanya akan mencegah penyelesaian pernyataan saat ini tetapi bets akan terus mengeksekusi).

Seperti banyak hal dalam profesi kita, preferensi pribadi akan menjadi kekuatan pendorong besar di belakang bagaimana Anda sebagai individu dan penulis kode T-SQL mengakhiri batch. Beberapa orang hanya secara eksplisit mendefinisikan kumpulan ketika mereka benar - benar harus (lihat di atas untuk persyaratan tersebut), dan yang lain mengakhiri batch secara terprogram 100% dari waktu , bahkan ketika mereka hanya menjalankan pernyataan tunggal di Jendela Kueri di SSMS. Kebanyakan orang biasanya jatuh di suatu tempat di tengah-tengah dua batas itu. Untuk apa nilainya, terminator pernyataan memiliki pengikut yang sama dengan persyaratan yang diberlakukan juga sangat sedikit. Sebagian besar dari semua ini adalah gaya kode , di mana itu tidak ditegakkan (dalam SSMS dan SQLCMD).


Mungkin komentar naif tetapi mengejutkan saya bahwa SQL Server bisa menentukan apa yang harus dijalankan dalam batch itu sendiri (dengan cara yang sama seperti banyak optimasi lainnya ditangani oleh mesin database). Misalnya menggunakan aturan yang telah Anda jelaskan daripada mengandalkan pengguna untuk membuat skrip, yang mungkin rentan kesalahan dan tampaknya menambah mengasapi skrip yang tidak perlu.
Steve Chambers

1
@SteveChambers sentimen saya persis. Jawabannya mengatakan "sesederhana itu" (Batch adalah sekelompok satu atau lebih pernyataan Transact-SQL yang dikirim secara bersamaan dari aplikasi ke SQL Server untuk dieksekusi.) Tetapi tidak. Ada kombinasi pernyataan yang bisa saya coba dan kirimkan dalam batch yang gagal. Pada akhirnya saya pikir Anda perlu memahami mengapa dan bagaimana mengirim batch berbeda dari mengirim serangkaian pernyataan individu - jadi saya akhirnya menyumbangkan jawaban saya sendiri untuk yang satu ini: stackoverflow.com/a/56370223/3714936 - yang juga berbicara pada komentar Anda .
youcantryreachingme
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.