Поделиться через


НАЧИНАТЬ... КОНЕЦ (Transact-SQL)

Применимо к:SQL ServerБаза данных Azure SQLУправляемый экземпляр Azure SQLAzure Synapse AnalyticsСистема платформы аналитики (PDW)Конечная точка SQL аналитики в Microsoft FabricХранилище в Microsoft FabricБаза данных SQL в Microsoft Fabric

Помещает последовательность Transact-SQL операторов в логический блок кода. Это использование не BEGIN связано с BEGIN TRANSACTION утверждениями and BEGIN ATOMIC .

Вы можете использовать BEGIN...END блоки с предшествующим оператором управления потоком, такие IFкак , ELSE, и WHILE. Однако вы также можете использовать эти блоки без каких-либо предшествующих операторов управления потоком, чтобы организовано группировать последовательности операторов. Однако каждый новый BEGIN...END блок не создаёт новую лексическую область.

Соглашения о синтаксисе Transact-SQL

Syntax

BEGIN [ ; ]
    { sql_statement | statement_block }
END [ ; ]

Arguments

{ sql_statement | statement_block }

Любая допустимая инструкция Transact-SQL или группирование инструкций, определяемая с помощью блока инструкций.

Remarks

Блок BEGIN...END должен содержать как минимум один оператор. Если вы пытаетесь использовать пустой BEGIN...END блок, вы получаете синтаксическую ошибку, даже если после каждого ключевого слова ставить точку с запятой. Вы можете избежать пустых BEGIN...END блоков, используя GOTO метку в качестве временного утверждения. См. пример C: Используйте метку GOTO для динамически сгенерированного BEGIN... Блоки END.

BEGIN...END Блоки можно вложить.

BEGIN...END Блоки не определяют лексический объём. Если вы объявляете переменную внутри блока, она видна во всей родительской партии, а не только внутри блока с оператором DECLARE .

Нельзя использовать BEGIN...END блоки в нескольких партиях. Например, вы не можете использовать GO пакетный сепаратор внутри BEGIN...END блока.

Использование BEGIN...END блока для группировки операторов не означает, что все операторы группы работают атомарно. Когда партия выполняется вне транзакции, и возникает ошибка или вторая операторская запись блока с мультиоператорами BEGIN...END , первая операторская запись не откатывается.

Точки с запятой после BEGIN ключевых слов и ENDнеобязательны, но рекомендуются, за исключением следующих случаев:

  • Перед WITH ключевым словом, начинающим выражение общей таблицы (CTE), нужна точка с запятой.

  • Нужна точка с запятой с THROW утверждением внутри блока.

  • Используйте точку с запятой после BEGIN , чтобы избежать путаницы с BEGIN TRANSACTION утверждениями или BEGIN ATOMIC .

  • Использование точки с запятой после END гарантирует, что любое последующее утверждение, особенно ключевое WITH слово или THROW утверждение, не требует предварительной точки с запятой.

Хотя все операторы Transact-SQL валидны в блоке BEGIN...END , не стоит группировать определённые Transact-SQL операторы в одном пакете или блоке операторов. Убедитесь, что выписки не конфликтуют с существующими требованиями Transact-SQL пакета.

Examples

Примеры кода в этой статье используют базу данных образца AdventureWorks2025 или AdventureWorksDW2025, которую можно скачать с домашней страницы образцов и проектов сообщества Microsoft SQL Server и.

В следующем примере 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;

В. Используйте 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.';

С. Используйте метку GOTO для динамически сгенерированного BEGIN... КОНЕЧНЫЕ БЛОКИ

Если вы генерируете динамические Transact-SQL с BEGIN...END блоком и хотите, чтобы программа всегда отображала ключевые BEGIN...END слова, вы можете использовать GOTO метку как временную инструкцию, чтобы избежать пустого BEGIN...END блока.

BEGIN
    unusedLabel:
END

Примеры: Azure Synapse Analytics и система платформы аналитики (PDW)

С. Определите последовательность операторов, которые работают вместе

В следующем примере BEGIN и END определите ряд инструкций SQL, которые выполняются вместе.

Caution

Если убрать 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