> For the complete documentation index, see [llms.txt](https://mariadb.com/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mariadb.com/docs/server/reference/sql-statements/programmatic-compound-statements/begin-end.md).

# BEGIN END

## Syntax

```bnf
[begin_label:] BEGIN [NOT ATOMIC]
    [statement_list]
END [end_label]
```

`NOT ATOMIC` is required when used outside of a [stored procedure](/docs/server/server-usage/stored-routines/stored-procedures.md). Inside stored procedures or within an anonymous block, `BEGIN` alone starts a new anonymous block.

## Description

`BEGIN ... END` syntax is used for writing compound statements. A compound statement can contain multiple statements, enclosed by the `BEGIN` and `END` keywords. statement\_list represents a list of one or more statements, each terminated by a semicolon (i.e., `;`) statement delimiter. statement\_list is\
optional, which means that the empty compound statement (`BEGIN END`) is legal.

Note that `END` will perform a commit. If you are running in [autocommit](/docs/server/server-management/variables-and-modes/server-system-variables.md#autocommit) mode, every statement will be committed separately. If you are not running in `autocommit` mode, you must execute a [COMMIT](/docs/server/reference/sql-statements/transactions/commit.md) or [ROLLBACK](/docs/server/reference/sql-statements/transactions/rollback.md) after `END` to get the database up to date.

Use of multiple statements requires that a client is able to send statement strings containing the statement delimiter. This is handled in the [mysql command-line client](/docs/server/clients-and-utilities/mariadb-client/mysql-command-line-client.md) with the [DELIMITER ](/docs/server/clients-and-utilities/mariadb-client/mariadb-command-line-client.md#delimiters)command.\
Changing the `;` end-of-statement delimiter (for example, to`//`) allows `;` to be used in a program body.

A compound statement within a [stored program](/docs/server/server-usage/stored-routines.md) can be [labeled](/docs/server/reference/sql-statements/programmatic-compound-statements/labels.md). `end_label` cannot be given unless `begin_label` also is present. If both are present, they must be the same.

`BEGIN ... END` constructs can be nested. Each block can define its own variables, a `CONDITION`, a `HANDLER` and a [CURSOR](/docs/server/reference/sql-statements/programmatic-compound-statements/programmatic-compound-statements-cursors.md), which don't exist in the outer blocks. The most local declarations override the outer objects which use the same name (see example below).

The declarations order is the following:

* [DECLARE local variables](/docs/server/reference/sql-statements/programmatic-compound-statements/declare-variable.md)
* [DECLARE CONDITIONs](/docs/server/reference/sql-statements/programmatic-compound-statements/declare-condition.md)
* [DECLARE CURSORs](/docs/server/reference/sql-statements/programmatic-compound-statements/programmatic-compound-statements-cursors/declare-cursor.md)
* [DECLARE HANDLERs](/docs/server/reference/sql-statements/programmatic-compound-statements/declare-handler.md)

Note that `DECLARE HANDLER` contains another `BEGIN ... END` construct.

Here is an example of a very simple, anonymous block:

```sql
BEGIN NOT ATOMIC
SET @a=1;
CREATE TABLE test.t1(a INT);
END|
```

Below is an example of nested blocks in a stored procedure:

```sql
CREATE PROCEDURE t( )
BEGIN
   DECLARE x TINYINT UNSIGNED DEFAULT 1;
   BEGIN
      DECLARE x CHAR(2) DEFAULT '02';
       DECLARE y TINYINT UNSIGNED DEFAULT 10;
       SELECT x, y;
   END;
   SELECT x;
END;
```

In this example, a [TINYINT](/docs/server/reference/data-types/numeric-data-types/tinyint.md) variable, `x` is declared in the outer block. But in the inner block `x` is redeclared as a [CHAR](/docs/server/reference/data-types/string-data-types/char.md) and an `y` variable is declared. The inner [SELECT](/docs/server/reference/sql-statements/data-manipulation/selecting-data/select.md) shows the "new" value of `x`, and the value of `y`. But when x is selected in the outer block, the "old" value is returned. The final [SELECT](/docs/server/reference/sql-statements/data-manipulation/selecting-data/select.md) doesn't try to read `y`, because it doesn't exist in that context.

## See Also

* [Using compound statements outside of stored programs](/docs/server/reference/sql-statements/programmatic-compound-statements/using-compound-statements-outside-of-stored-programs.md)
* [Changes in Oracle mode](/docs/release-notes/community-server/about/compatibility-and-differences/sql_modeoracle.md)

<sub>*This page is licensed: GPLv2, originally from*</sub> [<sub>*fill\_help\_tables.sql*</sub>](https://github.com/MariaDB/server/blob/main/scripts/fill_help_tables.sql)

{% @marketo/form formId="4316" %}
