Apa itu “batch”, dan mengapa GO digunakan?

135

Saya telah membaca dan membaca MSDN, dll. Ok, jadi ini menandakan akhir dari sebuah batch.

Apa yang mendefinisikan batch? Saya tidak mengerti mengapa saya harus pergi ketika saya menempelkan banyak skrip untuk dijalankan pada saat yang bersamaan.

Saya tidak pernah mengerti GO. Adakah yang bisa menjelaskan hal ini dengan lebih baik dan kapan saya perlu menggunakannya (setelah berapa banyak atau jenis transaksi apa)?

Misalnya mengapa saya perlu GO setelah setiap pembaruan di sini:

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

 GO

 UPDATE [Country]
   SET [CountryCode] = 'PT'
 WHERE code = 'PT'
PositiveGuy
sumber
1
kemungkinan duplikat dari Apa gunanya GO di SQL Server Management Studio?
tvanfosson
FWIW, sepertinya gojuga me-reset / membersihkan declare @foodeklarasi variabel - Saya mendapatkan Anda perlu mendeklarasikan kesalahan @foo , sampai saya mengomentari go.
JL Peyret

Jawaban:

107

GOadalah tidak benar perintah TSQL.

Alih-alih itu adalah perintah ke program klien tertentu yang terhubung ke server SQL (Sybase atau Microsoft - tidak yakin tentang apa yang dilakukan Oracle), memberi isyarat ke program klien bahwa sekumpulan perintah yang dimasukkan ke dalamnya sampai kebutuhan "pergi" untuk dikirim ke server untuk dieksekusi.

Mengapa / kapan Anda membutuhkannya?

  • GO di server MS SQL memiliki parameter "hitungan" - sehingga Anda dapat menggunakannya sebagai pintasan "ulangi N kali".

  • Pembaruan yang sangat besar mungkin mengisi log server SQL. Untuk menghindarinya, mereka mungkin perlu dipisahkan menjadi beberapa bagian yang lebih kecil melalui go.

    Dalam contoh Anda, jika pembaruan untuk satu set kode negara memiliki volume yang akan kehabisan ruang log, solusinya adalah dengan memisahkan setiap kode negara menjadi transaksi terpisah - yang dapat dilakukan dengan memisahkannya pada klien dengan go.

  • Beberapa pernyataan SQL HARUS dipisahkan oleh GO dari pernyataan berikut agar berfungsi.

    Misalnya, Anda tidak dapat menghapus tabel dan membuat ulang tabel dengan nama yang sama dalam satu transaksi, setidaknya di Sybase (ditto untuk membuat prosedur / pemicu):

> 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
>
DVK
sumber
4
Pernyataan GO tidak menciptakan transaksi. Jika Anda menyertakan beberapa pernyataan GO dalam satu pernyataan BEGIN TRANSACTION dan pada akhirnya Anda akan melakukan ROLLBACK, semua GO akan dikembalikan. Dan jika dalam satu GO di tengah Anda akan mendapatkan error, dan pada akhirnya Anda akan melakukan COMMIT, semua GO tanpa error akan dikomit. Agak rumit.
TZ
7
GOtidak "membuat transaksi untuk Anda". Jika Anda tidak menjalankan transaksi eksplisit, setiap pernyataan akan tetap membuat transaksinya sendiri. Ini sepenuhnya ortogonal. Jika Anda ingin membagi pembaruan yang lebih besar menjadi langkah-langkah yang lebih kecil, Anda masih dapat melakukannya dalam satu kelompok seperti pada WHILE @@ROWCOUNT > 0pola umum .
Martin Smith
3
Jika Anda tidak menjalankan dalam transaksi eksplisit maka UPDATE T1 SET X =2;UPDATE T1 SET X =2;akan dijalankan sebagai dua transaksi yang terpisah pula . Penambahan GOsama sekali tidak ada bedanya. Dan juga jika Anda sedang menjalankan dalam transaksi eksplisit itu meliputi batch dan lagi GO tidak ada bedanya.
Martin Smith
4
Sama seperti klarifikasi bagi siapa pun yang membaca ini nanti ... GOsama sekali tidak ada hubungannya dengan transaksi sama sekali, dan membuat jawaban poin kedua tentang transaksi dan ukuran file log salah. GOtidak akan berpengaruh apapun. Jawaban pertama dan ketiga benar. Selain itu, ada kalanya Anda perlu memisahkan pernyataan ke dalam kumpulan terpisah, misalnya Anda tidak bisa menambahkan kolom ke tabel dan kemudian menggunakan kolom itu nanti dalam kumpulan yang sama. (lanjutan)
Robert McKee
4
Selain itu, karena beberapa kesalahan akan membatalkan batch (beberapa kesalahan hanya membatalkan pernyataan), ini juga berperan dalam deteksi dan pemulihan kesalahan. Dan pernyataan tertentu ( CREATE VIEW, dll) harus berada dalam kelompoknya sendiri.
Robert McKee
26

GO bukanlah pernyataan, itu pemisah batch.

Blok yang dipisahkan oleh GOdikirim oleh klien ke server untuk diproses dan klien menunggu hasilnya.

Misalnya, jika Anda menulis

DELETE FROM a
DELETE FROM b
DELETE FROM c

, ini akan dikirim ke server sebagai 3kueri satu baris.

Jika Anda menulis

DELETE FROM a
GO
DELETE FROM b
GO
DELETE FROM c

, ini akan dikirim ke server sebagai 3kueri satu baris.

GOsendiri tidak pergi ke server (tidak ada permainan kata-kata). Ini adalah kata khusus sisi klien yang murni dan hanya dikenali oleh SSMSdan osql.

Jika Anda akan menggunakan alat kueri khusus untuk mengirimkannya melalui koneksi, server bahkan tidak akan mengenalinya dan mengeluarkan kesalahan.

Quassnoi
sumber
4
Kenapa harus batch sama sekali ??
PositiveGuy
3
Jadi GO berarti mengirimnya dan kemudian tidak menjalankan batch berikutnya sampai klien menerima "OK, batch itu selesai dan berhasil" pada dasarnya adalah apa yang GO lakukan sehingga batch berikutnya dapat dijalankan dengan sukses dan klien tahu untuk pastikan batch sebelum dilakukan di sisi server.
PositiveGuy
3
@coffeeaddict: pada dasarnya, ya. Selain itu, beberapa pernyataan harus menjadi yang pertama dalam kelompoknya (seperti CREATE SCHEMA); lain membutuhkan menjadi satu - satunya pernyataan dalam kelompok mereka (seperti SET SHOWPLAN_XML ON)
Quassnoi
19

Banyak perintah harus berada dalam kelompoknya sendiri, seperti CREATE PROCEDURE

Atau, jika Anda menambahkan kolom ke tabel, maka kolom tersebut harus berada dalam kelompoknya sendiri. Jika Anda mencoba untuk PILIH kolom baru dalam batch yang sama gagal karena pada waktu parse / kompilasi kolom tidak ada.

GO digunakan oleh alat SQL untuk menyelesaikan ini dari satu skrip: ini bukan kata kunci SQL dan tidak dikenali oleh mesin.

Ini adalah 2 contoh konkret penggunaan batch sehari-hari.

Edit: Dalam contoh Anda, Anda tidak perlu GO ...

Edit 2, misalnya. Anda tidak dapat melepaskan, membuat, dan memberi izin dalam satu batch ... paling tidak, di mana akhir dari prosedur yang tersimpan?

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
gbn
sumber
4

Terkadang ada kebutuhan untuk menjalankan perintah yang sama atau sekumpulan perintah berulang kali. Ini mungkin untuk memasukkan atau memperbarui data pengujian atau mungkin untuk membebani server Anda untuk pengujian kinerja. Apa pun kebutuhan, cara termudah untuk melakukannya adalah dengan menyiapkan loop sementara dan menjalankan kode Anda, tetapi di SQL 2005 ada cara yang lebih mudah untuk melakukannya.

Misalkan Anda ingin membuat tabel uji dan memuatnya dengan 1000 catatan. Anda dapat mengeluarkan perintah berikut dan itu akan menjalankan perintah yang sama 1000 kali:

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

sumber: http://www.mssqltips.com/tip.asp?tip=1216

Selain itu, ini menandai "akhir" dari blok SQL (misalnya dalam prosedur tersimpan) ... Berarti Anda berada dalam status "bersih" lagi ... eG: Parameter yang digunakan dalam pernyataan sebelum kode disetel ulang ( tidak ditentukan lagi)

Steav
sumber
Oke, jadi mengapa Anda membutuhkan GO. Agar Anda tahu bahwa tabel dibuat sebelum pernyataan sisipkan dijalankan? Saya masih belum mengerti.
PositiveGuy
Lihat Cara saya memikirkan hal ini, adalah jika saya tidak memiliki GO dalam contoh Anda, Tabel dibuat terlebih dahulu, sekarang sudah ada, jadi penyisipan harus berfungsi. Saya tidak mengerti untuk apa GO itu jika saya membuat tabel ... itu tersedia untuk sisipan berikutnya bukan?!?!?!
PositiveGuy
2
@coffeeaddict: tidak. "batch" diurai dan dikompilasi sekaligus. Pada waktu kompilasi, dbo.TEST tidak ada. Anda tidak membuat instance objek dan SQL bukan kode prosedural baris demi baris
gbn
3

Seperti yang sudah dikatakan semua orang, "GO" bukanlah bagian dari T-SQL. "GO" adalah pemisah batch di SSMS , aplikasi klien yang digunakan untuk mengirimkan kueri ke database. Ini berarti bahwa variabel yang dideklarasikan dan variabel tabel tidak akan bertahan dari kode sebelum "GO" ke kode yang mengikutinya.

Faktanya, GO hanyalah kata default yang digunakan oleh SSMS. Ini dapat diubah dalam opsi jika Anda mau. Untuk sedikit kesenangan, ubah opsi di sistem orang lain untuk menggunakan "PILIH" sebagai pemisah batch, bukan "GO". Maafkan tawa kejam saya.

Garis Datar Dixie
sumber
1
Sebenarnya ada poin serius yang harus dibuat di sini: Anda harus memperlakukan GO seolah-olah itu adalah kata kunci meskipun sebenarnya bukan. Anda juga tidak boleh mengubahnya. Bug yang disebabkan oleh penggunaan kembali pengenal khusus bisa sangat sulit untuk di-debug.
Jørgen Fogh
@ The Dixie Flatline: apakah Anda yakin tentang variabel yang dideklarasikan tidak ada? Di MSSQL 2016 saya mendapatkan kesalahan "variabel sudah dideklarasikan" saat menjalankan: menyatakan $ test int; set $ test = 5; pilih $ test go; nyatakan $ test int; - Ganti $ dengan <at>, tidak bisa menggunakan beberapa <at> di komentar SE.
Wouter
0

Ini digunakan untuk membagi blok logika. Kode Anda diinterpretasikan ke dalam baris perintah sql dan ini menunjukkan blok kode berikutnya.

Tetapi bisa juga digunakan sebagai pernyataan rekursif dengan nomor tertentu.

Mencoba:

exec sp_who2  
go 2

Beberapa pernyataan harus dibatasi oleh GO:

use DB
create view thisViewCreationWillFail
Deadsheep39
sumber