Một lô hàng thế giới là gì và tại sao GO được sử dụng?


134

Tôi đã đọc và đọc qua MSDN, v.v ... Ok, vì vậy nó báo hiệu kết thúc một đợt.

Điều gì định nghĩa một lô? Tôi không thấy lý do tại sao tôi cần phải đi khi tôi dán một loạt các kịch bản để được chạy cùng một lúc.

Tôi chưa bao giờ hiểu GO. Bất cứ ai có thể giải thích điều này tốt hơn và khi tôi cần sử dụng nó (sau bao nhiêu hoặc loại giao dịch)?

Ví dụ tại sao tôi cần GO sau mỗi lần cập nhật tại đây:

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

 GO

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


FWIW, có vẻ như gocũng đặt lại / xóa declare @foocác khai báo biến - Tôi đã nhận được bạn cần phải khai báo lỗi @foo , cho đến khi tôi nhận xét go.
JL Peyret

Câu trả lời:


107

GOkhông đúng một lệnh TSQL.

Thay vào đó, nó là một lệnh cho chương trình máy khách cụ thể kết nối với máy chủ SQL (Sybase hoặc Microsoft - không chắc chắn về những gì Oracle làm), báo hiệu cho chương trình máy khách rằng tập hợp các lệnh được đưa vào cho đến khi cần "đi" được gửi đến máy chủ để được thực thi.

Tại sao / khi nào bạn cần nó?

  • GO trong MS SQL server có tham số "đếm" - vì vậy bạn có thể sử dụng nó làm phím tắt "lặp lại N lần".

  • Các bản cập nhật cực lớn có thể lấp đầy nhật ký của máy chủ SQL. Để tránh điều đó, chúng có thể cần được tách thành các lô nhỏ hơn thông qua go.

    Trong ví dụ của bạn, nếu cập nhật cho một bộ mã quốc gia có khối lượng lớn đến mức hết dung lượng nhật ký, giải pháp là tách từng mã quốc gia thành một giao dịch riêng - có thể được thực hiện bằng cách tách chúng trên máy khách go.

  • Một số câu lệnh SQL PHẢI được phân tách bằng GO khỏi các câu lệnh sau để hoạt động.

    Ví dụ: bạn không thể bỏ bảng và tạo lại bảng có cùng tên trong một giao dịch, ít nhất là trong Sybase (ditto để tạo thủ tục / trình kích hoạt):

> 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
Tuyên bố GO không tạo ra giao dịch. Nếu bạn bao gồm nhiều câu lệnh GO trong một câu lệnh BEGIN TRANSACTION và cuối cùng, bạn sẽ thực hiện ROLLBACK, nó sẽ quay ngược lại tất cả các câu lệnh GO. Và nếu trong một GO ở giữa, bạn sẽ gặp một số lỗi và cuối cùng, bạn sẽ thực hiện CAM KẾT, tất cả GO không có lỗi sẽ được cam kết. Là loại khó khăn.
TZ

7
GOkhông "tạo giao dịch cho bạn." Nếu bạn không chạy trong một giao dịch rõ ràng, mỗi câu lệnh sẽ tạo ra giao dịch của riêng nó. Nó hoàn toàn trực giao. Nếu bạn muốn chia một bản cập nhật lớn hơn thành các bước nhỏ hơn, bạn vẫn có thể thực hiện nó trong một đợt như trong WHILE @@ROWCOUNT > 0mẫu chung .
Martin Smith

3
Nếu bạn không chạy trong một giao dịch rõ ràng thì dù sao cũngUPDATE T1 SET X =2;UPDATE T1 SET X =2; sẽ chạy như hai giao dịch riêng biệt . Việc bổ sung làm cho hoàn toàn không có sự khác biệt. Và tương tự như vậy nếu bạn đang chạy trong một giao dịch rõ ràng, nó sẽ kéo dài các đợt và một lần nữa không có sự khác biệt. GOGO
Martin Smith

4
Cũng giống như làm rõ cho bất cứ ai đọc điều này sau này ... GOhoàn toàn không liên quan gì đến giao dịch, và làm cho câu trả lời thứ hai về giao dịch và kích thước của tệp nhật ký không chính xác. GOsẽ không có tác dụng gì. Câu trả lời đầu tiên và thứ ba là chính xác. Ngoài ra, có những lúc bạn cần tách các câu lệnh thành các lô riêng biệt, ví dụ: bạn không thể thêm một cột vào một bảng và sau đó sử dụng cột đó sau đó trong cùng một đợt. (còn tiếp)
Robert McKee

4
Ngoài ra, vì một số lỗi sẽ hủy bỏ một lô (một số lỗi chỉ hủy bỏ một câu lệnh), nên nó cũng đóng vai trò trong việc phát hiện và phục hồi lỗi. Và một số tuyên bố nhất định ( CREATE VIEW, v.v.) cần phải nằm trong lô riêng của chúng.
Robert McKee

26

GO không phải là một tuyên bố, nó là một phân tách hàng loạt.

Các khối được phân tách bằng GOđược gửi bởi máy khách đến máy chủ để xử lý và máy khách chờ kết quả của chúng.

Ví dụ, nếu bạn viết

DELETE FROM a
DELETE FROM b
DELETE FROM c

, điều này sẽ được gửi đến máy chủ dưới dạng 3truy vấn một dòng.

Nếu bạn viết

DELETE FROM a
GO
DELETE FROM b
GO
DELETE FROM c

, điều này sẽ được gửi đến máy chủ dưới dạng 3truy vấn một dòng.

GObản thân nó không đi đến máy chủ (không có ý định chơi chữ). Đó là một từ dành riêng phía khách hàng thuần túy và chỉ được công nhận bởi SSMSosql .

Nếu bạn sẽ sử dụng một công cụ truy vấn tùy chỉnh để gửi nó qua kết nối, máy chủ thậm chí sẽ không nhận ra nó và báo lỗi.


4
Tại sao bạn phải hàng loạt?
positiveGuy

3
Vì vậy, GO có nghĩa là gửi nó và sau đó không chạy đợt tiếp theo cho đến khi khách hàng nhận được "OK, đợt đó đã hoàn thành và thành công" về cơ bản là những gì GO làm để đợt tiếp theo có thể được chạy thành công và khách hàng biết chắc chắn lô trước khi nó được thực hiện phía máy chủ.
positiveGuy

3
@coffeeaddict: về cơ bản, vâng. Ngoài ra, một số báo cáo yêu cầu phải là đầu tiên trong lô của họ (như CREATE SCHEMA); khác yêu cầu là báo cáo duy nhất trong lô của họ (như SET SHOWPLAN_XML ON)
Quassnoi

19

Nhiều lệnh cần phải nằm trong lô riêng của chúng, như CREATE PROCEDURE

Hoặc, nếu bạn thêm một cột vào một bảng, thì nó sẽ nằm trong lô riêng của nó. Nếu bạn cố gắng CHỌN cột mới trong cùng một đợt thì sẽ thất bại vì tại thời điểm phân tích / biên dịch, cột không tồn tại.

GO được sử dụng bởi các công cụ SQL để thực hiện điều này từ một tập lệnh: nó không phải là từ khóa SQL và không được công cụ nhận ra.

Đây là 2 ví dụ cụ thể về việc sử dụng hàng ngày của các đợt.

Chỉnh sửa: Trong ví dụ của bạn, bạn không cần GO ...

Chỉnh sửa 2, ví dụ. Bạn không thể thả, tạo và cấp phép trong một đợt ... không nhất thiết, phần cuối của thủ tục được lưu trữ ở đâu?

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

Đôi khi cần phải thực hiện cùng một lệnh hoặc tập hợp các lệnh lặp đi lặp lại. Điều này có thể là để chèn hoặc cập nhật dữ liệu kiểm tra hoặc có thể là để tải lên máy chủ của bạn để kiểm tra hiệu suất. Bất cứ điều gì cần cách dễ nhất để làm điều này là thiết lập một vòng lặp while và thực thi mã của bạn, nhưng trong SQL 2005 có một cách thậm chí còn dễ dàng hơn để làm điều này.

Giả sử bạn muốn tạo một bảng thử nghiệm và tải nó với 1000 bản ghi. Bạn có thể đưa ra lệnh sau và nó sẽ chạy cùng một lệnh 1000 lần:

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

nguồn: http://www.mssqltips.com/tip.asp?tip=1216

Ngoài ra, nó đánh dấu "kết thúc" của khối SQL (ví dụ: trong quy trình được lưu trữ) ... Có nghĩa là bạn lại ở trạng thái "sạch" ... eG: Tham số được sử dụng trong câu lệnh trước khi mã được đặt lại ( không xác định nữa)


Ok, vậy tại sao bạn cần GO. Vì vậy, bạn biết bảng đã được tạo trước khi câu lệnh chèn được chạy? Tôi vẫn không hiểu.
positiveGuy

Xem Cách tôi nghĩ về điều này, là nếu tôi không có GO trong ví dụ của bạn, Bảng được tạo trước, bây giờ nó ở đó, vì vậy, phần chèn sẽ hoạt động. Tôi không hiểu GO là gì nếu tôi tạo bảng ... nó có sẵn cho lần chèn tiếp theo không?!?!?!
positiveGuy

2
@coffeeaddict: không. "lô" được phân tích cú pháp và biên dịch trong một lần. Tại thời điểm biên dịch, dbo.TEST không tồn tại. Bạn không khởi tạo một đối tượng và SQL không phải là dòng mã thủ tục
gbn

3

Như mọi người đã nói, "GO" không phải là một phần của T-SQL. "GO" là một trình phân tách hàng loạt trong SSMS , một ứng dụng khách được sử dụng để gửi truy vấn đến cơ sở dữ liệu. Điều này có nghĩa là các biến được khai báo và biến bảng sẽ không tồn tại từ mã trước "GO" để mã theo sau nó.

Trên thực tế, GO chỉ đơn giản là từ mặc định được SSMS sử dụng. Điều này có thể được thay đổi trong các tùy chọn nếu bạn muốn. Để giải trí, hãy thay đổi tùy chọn trên hệ thống của người khác để sử dụng "CHỌN" làm công cụ tách hàng loạt thay vì "GO". Tha thứ cho tiếng cười độc ác của tôi.


1
Thực sự có một điểm nghiêm trọng cần được thực hiện ở đây: Bạn nên coi GO như thể đó là một từ khóa mặc dù nó không phải là một từ khóa. Bạn cũng không bao giờ nên thay đổi nó. Lỗi gây ra bởi việc sử dụng lại các định danh đặc biệt có thể rất khó gỡ lỗi.
Jørgen Fogh

@The Dixie Flatline: bạn có chắc chắn về các biến được khai báo không tồn tại không? Trong MSSQL 2016 tôi gặp lỗi "biến đã được khai báo" khi chạy: khai báo $ test int; đặt $ test = 5; chọn $ test đi; khai báo $ test int; - Thay thế $ bằng <at>, không thể sử dụng nhiều <at> trong các nhận xét SE.
Wouter

0

Nó được sử dụng để phân chia các khối logic. Mã của bạn được hiểu thành dòng lệnh sql và điều này cho biết khối mã tiếp theo.

Nhưng nó có thể được sử dụng như một tuyên bố đệ quy với số lượng cụ thể.

Thử:

exec sp_who2  
go 2

Một số tuyên bố phải được phân định bởi GO:

use DB
create view thisViewCreationWillFail
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.