GO หลังจากทุกคำสั่ง T-SQL


34

เหตุผลเบื้องหลังการใช้คำสั่ง GO หลังจากทุกคำสั่ง SQL คืออะไร ฉันเข้าใจว่า GO ส่งสัญญาณการสิ้นสุดของแบทช์และ / หรืออนุญาตให้มีชื่อเสียงของข้อความ แต่สิ่งที่มันมีประโยชน์ใช้หลังจากทุกคำสั่ง

ฉันแค่อยากรู้อยากเห็นเป็นเอกสาร Microsoft จำนวนมาก ฯลฯ ได้เริ่มใช้มันหลังจากทุกคำสั่งหรือบางทีฉันเพิ่งเริ่มสังเกตเห็น

นอกจากนี้สิ่งที่ถือว่าเป็นแนวปฏิบัติที่ดีที่สุด

คำตอบ:


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 โดยทางโปรแกรม ลองตรวจสอบกันก่อนว่า ตัวเลือกของฉันที่นี่คือการใช้ Extended Events:

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 ของฉันมันเป็นวิธีที่รวดเร็วในการดูผู้ริเริ่มเหตุการณ์ ชื่อ "พารามิเตอร์สตริงการเชื่อมต่อและการกรองออกจากนั้น)

หลังจากที่ฉันเรียกใช้รหัส 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 ต้องเริ่มแบตช์ งบอื่น ๆ ทั้งหมดที่ตามมาในชุดนั้นจะถูกตีความเป็นส่วนหนึ่งของคำนิยามของคำสั่งสร้างครั้งแรก

ตารางไม่สามารถเปลี่ยนแปลงได้จากนั้นคอลัมน์ใหม่ที่อ้างอิงในชุดเดียวกัน

หากคำสั่ง EXECUTE เป็นคำสั่งแรกในชุดงานคำสั่ง EXECUTE ไม่จำเป็นต้องใช้ จำเป็นต้องใช้คีย์เวิร์ด EXECUTE หากคำสั่ง EXECUTE ไม่ใช่คำสั่งแรกในแบตช์

เช่นเดียวกันข้อผิดพลาดรันไทม์บางอย่าง (ข้อผิดพลาดการคอมไพล์จะไม่อนุญาตให้เรียกใช้งานแบตช์เพื่อเริ่มต้น) ที่เกิดขึ้นในระหว่างแบทช์อาจทำให้เกิดพฤติกรรมที่แตกต่างกัน: การยกเลิกแบตช์โดยสิ้นเชิงหรือดำเนินการต่อ ลิงก์ให้สองตัวอย่างที่ดีจริงๆ: ข้อผิดพลาดทางคณิตศาสตร์มากเกินไปจะหยุดการประมวลผลของชุดในขณะที่ข้อผิดพลาดการละเมิดข้อ จำกัด จะป้องกันเฉพาะคำสั่งปัจจุบันไม่ให้เสร็จสมบูรณ์ แต่ชุดจะดำเนินการต่อ)

เช่นเดียวกับหลาย ๆ สิ่งในอาชีพของเราแม้ว่าความชอบส่วนตัวจะเป็นแรงผลักดันอย่างมากต่อการที่คุณเป็นบุคคลและผู้เขียนรหัส T-SQL จะยุติกระบวนการ บางคนกำหนดแบทช์อย่างชัดเจนเฉพาะเมื่อพวกเขาจำเป็นต้อง (ดูด้านบนสำหรับข้อกำหนดเหล่านั้น) และคนอื่น ๆ ยกเลิกแบทช์โดยทางโปรแกรม 100% ของเวลาแม้ว่าพวกเขาจะดำเนินการคำสั่งเดียวในหน้าต่าง Query ใน SSMS คนส่วนใหญ่มักจะตกที่ใดที่หนึ่งในสองขอบเขต สำหรับสิ่งที่คุ้มค่าเทอร์มิเนลคำสั่งจะมีสิ่งต่อไปนี้เหมือนกันและมีข้อกำหนดบังคับน้อยมาก ส่วนใหญ่ของทั้งหมดนี้คือรูปแบบโค้ดที่ไม่ได้บังคับใช้ (ใน SSMS และ SQLCMD)


บางทีอาจเป็นความคิดเห็นที่ไร้เดียงสา แต่มันทำให้ฉันเห็นว่า SQL Server สามารถระบุได้ว่าจะให้ทำงานอย่างไรในแบทช์ของตัวเอง เช่นการใช้กฎที่คุณอธิบายไว้แทนที่จะอาศัยผู้ใช้ในการเขียนสคริปต์ซึ่งอาจเกิดข้อผิดพลาดได้ง่ายและดูเหมือนว่าจะเพิ่ม bloat ที่ไม่จำเป็นลงในสคริปต์
Steve Chambers

1
@ SteveChambers ความเชื่อมั่นของฉันอย่างแน่นอน คำตอบบอกว่า "มันง่ายอย่างนั้น" (แบตช์คือกลุ่มของคำสั่ง Transact-SQL หนึ่งรายการหรือมากกว่าที่ส่งพร้อมกันจากแอปพลิเคชันไปยัง SQL Server เพื่อดำเนินการ) แต่ก็ไม่ใช่ มีชุดคำสั่งที่ฉันสามารถลองและส่งเป็นชุดที่ล้มเหลวได้ ในที่สุดฉันคิดว่าคุณต้องเข้าใจว่าทำไมและวิธีการส่งแบทช์แตกต่างจากการส่งชุดของแต่ละงบ - ดังนั้นในที่สุดฉันก็มีส่วนตอบเองในเรื่องนี้: stackoverflow.com/a/56370223/3714936ซึ่งพูดถึงความคิดเห็นของคุณ .
youcantryreachingme
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.