適用於:SQL Server
Azure SQL 資料庫
Azure SQL 受控執行個體
Azure Synapse Analytics
分析平台系統(PDW)
Microsoft Fabric 中的 SQL 分析端點
Microsoft Fabric 中的倉儲
Microsoft Fabric 中的 SQL 資料庫
將一連串 Transact-SQL 語句包圍在一個邏輯程式碼區塊中。 這種用法 BEGIN 與 BEGIN TRANSACTION and BEGIN ATOMIC 陳述無關。
你可以使用BEGIN...END前置有 、 IFELSE、 和 WHILE的區塊。 不過,你也可以使用這些區塊,而不使用任何前置的流量控制語句,以有組織的方式將一連串語句分組。 然而,每個新 BEGIN...END 區塊並不會產生新的詞彙範圍。
Syntax
BEGIN [ ; ]
{ sql_statement | statement_block }
END [ ; ]
Arguments
{ sql_statement | statement_block}
使用語句區塊所定義的任何有效 Transact-SQL 語句或語句群組。
Remarks
一個 BEGIN...END 區塊必須包含至少一個語句。 如果你嘗試使用空 BEGIN...END 區塊,即使你在每個關鍵字後面加分號,也會有語法錯誤。 你可以透過使用GOTO標籤作為佔位語句來避免BEGIN...END空區塊。 參見 範例 C:使用動態產生的 BEGIN... 的 GOTO 標籤。終結區塊。
BEGIN...END 區塊可以是巢狀的。
BEGIN...END 區塊並不定義任何詞彙範圍。 如果你在區塊內宣告變數,它會在整個父批次中可見,而不僅限於包含該 DECLARE 語句的區塊內。
你不能在多個批次間使用 BEGIN...END 區塊。 例如,你不能在區塊內BEGIN...END使用GO批次分離器。
用 BEGIN...END 區塊來分組語句並不代表群組裡的所有語句都以原子方式執行。 當批次在交易外執行,且多重陳述 BEGIN...END 區塊的第二個陳述句提出錯誤或拋出異常時,第一個陳述句不會被回滾。
與 關鍵字後BEGIN的分號為可選,但建議使用,除非以下情況:END
你需要在關鍵字前
WITH加分號,才能開啟 常見表格表達 式(CTE)。你需要一個分號,且陳述
THROW句在一個區塊內。後面用分號
BEGIN避免與BEGIN TRANSACTIONorBEGIN ATOMIC語句混淆。使用分號後
END可確保後續語句,特別是WITH關鍵字或THROW語句,前方不需加分號。
雖然所有 Transact-SQL 語句在區 BEGIN...END 塊內都有效,但你不應該將某些 Transact-SQL 語句集中在同一批次或語句區塊中。 確保報價不會與現有的 Transact-SQL 批次需求衝突。
Examples
本文中的程式代碼範例會使用 AdventureWorks2025 或 AdventureWorksDW2025 範例資料庫,您可以從 Microsoft SQL Server 範例和社群專案 首頁下載。
A。 依序定義一連串邏輯相關的陳述
在以下範例中, BEGIN 並 END 定義邏輯相關的 Transact-SQL 語句序列,依序執行。 範例中也展示了巢狀區塊。
USE AdventureWorks2025;
GO
DECLARE @personId AS INT = (
SELECT p.BusinessEntityID
FROM Person.Person AS p
WHERE p.rowguid = { GUID '92C4279F-1207-48A3-8448-4636514EB7E2' }
);
IF (@personId IS NULL)
THROW 50001, 'Person not found.', 1;
/* Concatenate the person's name fields: */;
BEGIN
DECLARE @title AS NVARCHAR (8),
@first AS NVARCHAR (50),
@middle AS NVARCHAR (50),
@last AS NVARCHAR (50),
@suffix AS NVARCHAR (10);
SELECT @title = NULLIF (p.Title, N''),
@first = p.FirstName,
@middle = NULLIF (p.MiddleName, N''),
@last = p.LastName,
@suffix = NULLIF (p.Suffix, N'')
FROM Person.Person AS p
WHERE p.BusinessEntityID = @personId;
DECLARE @nameConcat AS NVARCHAR (255) = CONCAT_WS(N' ', @title, @first, @middle, @last, @suffix);
/* This is a nested BEGIN...END block: */;
BEGIN
DECLARE @emails AS NVARCHAR (MAX) = (
SELECT STRING_AGG(e.EmailAddress, /*separator:*/N'; ')
FROM Person.EmailAddress AS e
WHERE e.BusinessEntityID = @personId
);
SET @nameConcat = CONCAT(@nameConcat, N' (', @emails, N')');
END
END
/* BEGIN...END blocks do not define a lexical scope, so
even though @nameAndEmails is declared above, it is
still in-scope after the END keyword. */
SELECT @nameConcat AS NameAndEmails;
B. 使用 BEGIN...交易中的 END
在下列範例中,BEGIN 和 END 會定義一系列同時執行的 Transact-SQL 陳述式。 如果沒有包含該 BEGIN...END 區塊,兩個 ROLLBACK TRANSACTION 語句都會執行,並回傳兩個 PRINT 訊息。
USE AdventureWorks2025;
GO
BEGIN TRANSACTION;
IF @@TRANCOUNT = 0
BEGIN
SELECT FirstName,
MiddleName
FROM Person.Person
WHERE LastName = 'Adams';
ROLLBACK TRANSACTION;
PRINT N'Rolling back the transaction two times causes an error.';
END
ROLLBACK TRANSACTION;
PRINT N'Rolled back the transaction.';
C. 動態產生的 BEGIN... 使用GOTO標籤。端區塊
如果你用區塊產生動態 Transact-SQL BEGIN...END ,且想讓程式永遠渲染 BEGIN...END 關鍵字,可以用 GOTO 標籤作為佔位語句,避免區塊是 BEGIN...END 空的。
BEGIN
unusedLabel:
END
範例:Azure Synapse Analytics 和 Analytics Platform System (PDW)
C. 定義一系列連貫的陳述
在以下範例中,BEGIN 和 END 會定義一系列同時執行的 SQL 陳述式。
謹慎
如果你移除 BEGIN 和 END 關鍵字,以下範例會進入無限迴圈。 該 WHILE 語句只迴圈查詢, SELECT 且從未進入該 SET @Iteration += 1 語句。
-- Uses AdventureWorksDW;
DECLARE @Iteration AS INT = 0;
WHILE @Iteration < 10
BEGIN
SELECT FirstName,
MiddleName
FROM dbo.DimCustomer
WHERE LastName = 'Adams';
SET @Iteration + = 1;
END