SQL Server'da Begin / End Blocks ve Go anahtar sözcüğünü ne zaman kullanmam gerekir?


103

Birisi bana SQL Server'ı ne zaman ve nerede kullanmam beginve endengellemem gerektiğini söyleyebilir mi?
Ayrıca, Goanahtar kelime tam olarak ne yapar ?

Yanıtlar:


116

GO bir senaryonun sonu gibidir.

GO ile ayrılmış birden çok CREATE TABLE deyiminiz olabilir. Bu, komut dosyasının bir bölümünü diğerinden ayırmanın, ancak hepsini tek bir blokta göndermenin bir yoludur.


BEGIN ve END, C / ++ / #, Java vb .'deki {and} gibidir.

Mantıksal bir kod bloğu bağladılar. BEGIN ve END'i saklı yordamın başında ve sonunda kullanma eğilimindeyim, ancak burada kesinlikle gerekli değil. Gerekli olduğu yerde, birden fazla adıma ihtiyaç duyduğunuz döngüler ve EĞER ifadeleri vb.

IF EXISTS (SELECT * FROM my_table WHERE id = @id)
BEGIN
   INSERT INTO Log SELECT @id, 'deleted'
   DELETE my_table WHERE id = @id
END

BEGIN ve END içermeyen bir SP oluşturmayı denediniz mi? IIRC, sadece ilk satır SP'ye dahil edilir, geri kalanı orada çalıştırılır ve sonra ...
cjk

2
Bu kesinlikle benim SQL Server 2000'den sonraki deneyimim değil.
MatBailie

1
BEGIN ve END de yeni bir kapsam tanımlıyor mu?
samis

2
Evet. Dışarıda beyan edilen her şey içeride görülebilir, ancak içeride beyan edilen herhangi bir şey END'de kapsam dışı kalacaktır.
MatBailie

36

Birden fazla ifadeyi kapsayan bir blok oluşturmak için BEGIN ... END gerekir. Öyleyse, bir IF ifadesinin bir 'ayağında' 2 şey yapmak istiyorsanız veya bir WHILE döngüsünün gövdesinde birden fazla şey yapmak istiyorsanız, bu ifadeleri BEGIN ile parantez içinde tutmanız gerekir ... SON.

GO anahtar sözcüğü SQL'in bir parçası değildir. Yalnızca Query Analyzer tarafından komut dosyalarını bağımsız olarak yürütülen "toplu işlere" bölmek için kullanılır.


28

GO, SQL Server'da bir anahtar sözcük değildir; bu bir toplu ayırıcıdır. GO, bir grup deyimi sonlandırır. Bu, özellikle SQLCMD gibi bir şey kullanırken kullanışlıdır. Komut satırında SQL ifadeleri girdiğinizi hayal edin. Bir ifadeyi her sonlandırdığınızda bir şeyin yürütülmesini istemezsiniz, bu nedenle SQL Server siz "GO" girene kadar hiçbir şey yapmaz.

Aynı şekilde, grubunuz başlamadan önce, genellikle bazı nesnelerin görünür olması gerekir. Diyelim ki bir veritabanı oluşturuyorsunuz ve ardından sorguluyorsunuz. Yazamazsın:

CREATE DATABASE foo;
USE foo;
CREATE TABLE bar;

çünkü CREATE TABLE oluşturan toplu iş için foo mevcut değildir. Bunu yapmanız gerekir:

CREATE DATABASE foo;
GO
USE foo;
CREATE TABLE bar;

13

BEGIN ve END diğerleri tarafından iyi yanıtlanmıştır.

Gary'nin belirttiği gibi GO, isql, sqlcmd, sorgu analizörü ve SQL Server Management stüdyosu gibi Microsoft tarafından sağlanan istemci araçlarının çoğu tarafından kullanılan bir toplu ayırıcıdır. (Araçlardan en azından bazıları parti ayırıcının değiştirilmesine izin veriyor. Parti ayırıcıyı değiştirmek için hiç bir kullanım görmedim.)

GO'nun ne zaman kullanılacağı sorusuna cevap vermek için, SQL'in ne zaman gruplara ayrılması gerektiğini bilmek gerekir.

Bazı ifadeler bir grubun ilk ifadesi olmalıdır.

select 1
create procedure #Zero as
    return 0

SQL Server 2000'de hata şudur:

Msg 111, Level 15, State 1, Line 3
'CREATE PROCEDURE' must be the first statement in a query batch.
Msg 178, Level 15, State 1, Line 4
A RETURN statement with a return value cannot be used in this context.

SQL Server 2005'te hata daha az yararlıdır:

Msg 178, Level 15, State 1, Procedure #Zero, Line 5
A RETURN statement with a return value cannot be used in this context.

Bu nedenle, bir GOgrubun başlangıcı olması gereken ifadeleri bir komut dosyasında kendisinden önce gelen ifadelerden ayırmak için kullanın.

Bir komut dosyası çalıştırırken, birçok hata toplu işin yürütülmesinin durmasına neden olur, ancak daha sonra istemci bir sonraki toplu işi gönderir, komut dosyasının yürütülmesi durmaz. Bunu genellikle test ederken kullanırım. Betiğe işlem başlangıcıyla başlayıp geri alma ile bitireceğim, tüm testleri ortada yapacağım:

begin transaction
go
... test code here ...
go
rollback transaction

Bu şekilde, her zaman başlangıç ​​durumuna geri dönüyorum, test kodunda bir hata olsa bile, ayrı bir partinin parçası olan başlama ve geri alma işlem ifadeleri hala devam ediyor. Ayrı gruplar halinde değillerse, bir sözdizimi hatası, bir toplu iş bir birim olarak ayrıştırıldığından, işlemin başlamasını engeller. Ve bir çalışma zamanı hatası, geri dönüşün gerçekleşmesini engeller.

Ayrıca, bir yükleme betiği yapıyorsanız ve bir dosyada birden fazla toplu iş varsa, bir toplu işteki bir hata, betiğin çalışmaya devam etmesini engellemez ve bu da karışıklığa neden olabilir. (Yüklemeden önce daima yedekleyin.)

Dave Markel'in işaret ettiği şeyle ilgili olarak, SQL Server toplu işin başında oluşturulmuş nesneler için veri sözlüğüne baktığı için ayrıştırmanın başarısız olacağı durumlar vardır, ancak herhangi bir ifade çalıştırılmadan önce ayrıştırma yapılabilir. Bazen bu bir sorundur, bazen değil. İyi bir örnek bulamıyorum. Ama eğer bir 'X yok' hatası alırsanız, bu ifade ile açıkça var olacaksa toplu işlere bölünür.

Ve son bir not. İşlem toplu işlere yayılabilir. (Yukarıya bakın.) Değişkenler yığınları kapsamaz.

declare @i int
set @i = 0
go
print @i

Msg 137, Level 15, State 2, Line 1
Must declare the scalar variable "@i".

1
İhtiyacım olan şey buydu, teşekkürler: "İşlem toplu işlere yayılabilir. Değişkenler toplu işlere yayılmaz."
Gary

3

GO bir grubu bitirir, kodda çok nadiren kullanmanız gerekir. Kaydedilmiş bir işlemde kullanırsanız, siz proc'u çalıştırdığınızda GO'dan sonra hiçbir kod çalıştırılmayacağını unutmayın.

BEGIN ve END, işlenecek çok satırlı kod içeren herhangi bir yordamsal tip deyimi için gereklidir. Bunlara WHILE döngüleri ve imleçleri (elbette mümkünse kaçınmanız gereken) ve EĞER ifadeleri (teknik olarak, yalnızca bir satır kod içeren bir IF ifadesi için bunlara ihtiyacınız yoktur, ancak daha kolay her zaman bir IF'den sonra koyarsanız kodu koruyun). CASE ifadeleri de END kullanır, ancak BEGIN'e sahip değildir.


GO'dan sonraki herhangi bir kod depolanan proc'a karşı gerçekten depolanır mı? CREATE veya ALTER ifadesi, GO'nun var olmamasından sonraki kod varmış gibi işlenmez mi? Ve sonra GO'dan sonraki kod, sanki kendi komut dosyasıymış gibi yürütüldü mü?
MatBailie

İmleçlerin bununla ne alakası var?
Gary McGill

3

Bugün bu problemle boğuştuktan sonra benim fikrim şudur: BEGIN ... END, {....} 'nın C dillerinde yaptığı gibi kodu parantezler, örneğin if ... else ve döngüler için kod blokları

GO, sonraki ifadeler önceki bir ifade ile tanımlanan bir nesneye dayandığında kullanılır (kullanılmalıdır). USE veritabanı, yukarıdaki iyi bir örnektir, ancak aşağıdakiler de sizi ısırır:

alter table foo add bar varchar(8);
-- if you don't put GO here then the following line will error as it doesn't know what bar is.
update foo set bar = 'bacon';
-- need a GO here to tell the interpreter to execute this statement, otherwise the Parser will lump it together with all successive statements.

Bana öyle geliyor ki sorun şudur: SQL Server SQL Ayrıştırıcısı, Oracle'ın aksine, ilk satırda yeni bir sembol tanımladığınızı ve aşağıdaki satırlarda referans vermenin uygun olduğunu anlayamıyor. Son GO'dan bu yana önceki SQL'i yürütmesini söyleyen bir GO belirteciyle karşılaşana kadar sembolü "görmez", bu noktada sembol veritabanına uygulanır ve ayrıştırıcı tarafından görünür hale gelir.

Neden noktalı virgülü anlamsal bir kırılma olarak ele alıp ifadeleri tek tek uygulamıyor, bilmiyorum ve olmasını diliyorum. Görebildiğim tek bonus, GO'dan hemen önce bir print () ifadesi koyabilmeniz ve ifadelerden herhangi biri başarısız olursa, print çalışmayacaktır. Küçük bir kazanç için çok fazla sorun.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.