---
title: 编组
description: 创建 DML 触发器 创建触发器 您可以使用 CREATE TRIGGER 语句创建触发器。 创建触发器的用户需要具备以下权限： 当前触发器关联的表的权限，包括 SELECT 、 INSERT 、 UPDATE 、 DELETE 等权限。 触发器权限，即 CREATE TRIGGER 权限。 触发器激活后要执行的语句…
image: https://mdn.alipayobjects.com/huamei_22khvb/afts/img/A*OSPzQ6GUQF4AAAAAQHAAAAgAeiGDAQ/original
---
切换语言

- 中文站 - 简体中文
- International - English
- 日本站 - 日本語

文档反馈![](https://mdn.alipayobjects.com/huamei_22khvb/afts/img/A*P8CuR4UJ_FkAAAAAAAAAAAAADiGDAQ/original) OceanBase 数据库分布式版 - V 3.2.3 企业版 LTS

# 创建 DML 触发器

更新时间：2023-07-18 17:25:58

## 创建触发器

您可以使用 `CREATE TRIGGER` 语句创建触发器。

创建触发器的用户需要具备以下权限：

- 当前触发器关联的表的权限，包括 `SELECT`、`INSERT`、`UPDATE`、`DELETE` 等权限。
 - 触发器权限，即 `CREATE TRIGGER` 权限。
 - 触发器激活后要执行的语句的权限。

创建触发器的 SQL 语法如下：

```sql
CREATE
    TRIGGER trigger_name
    trigger_time trigger_event
    ON tbl_name FOR EACH ROW
    trigger_body

trigger_time: { BEFORE | AFTER }

trigger_event: { INSERT | UPDATE | DELETE }

```

语法说明：

- 触发器名称 `trigger_name` 必须保持唯一。
 - `tbl_name` 表示建立触发器的表名，即在哪张表上建立触发器。
 - `BEFORE` 或 `AFTER` 表示触发动作的时间，即触发器将在每一行插入到表中之前还是之后激活。
 - `INSERT` 、`UPDATE` 或 `DELETE` 表示触发事件，即激活触发器的操作类型。
 - `FOR EACH ROW`用于定义触发器的主体，每次触发器激活时就会执行该语句，对于受触发事件影响的每一行都会执行一次。

OceanBase 数据库中也定义了 `NEW.columnName` 和 `OLD.columnName`：

- 在 `INSERT` 型触发器中，`NEW.columnName` 用来表示将要（`BEFORE`）或已经（`AFTER`）插入的新数据。

  其中，`columnName` 为相应数据表的某一列名。
 - 在 `UPDATE` 型触发器中，`OLD.columnName` 用来表示将要或已经被修改的原数据，`NEW.columnName` 用来表示将要或已经修改后的新数据。
 - 在 `DELETE` 型触发器中，`OLD.columnName` 用来表示将要或已经被删除的原数据。
 - `OLD.columnName` 是只读的，而 `NEW.columnName` 则可以在触发器中使用 `SET` 赋值。

创建触发器的示例如下：

创建一个触发器 `test_trg`，并将其与表 `test` 相关联，以激活 Insert 操作，且触发器充当累加器，将插入到表的列的值求和。

```sql
obclient>CREATE TABLE test (user_id INT, user_num DECIMAL(10,2));
Query OK, 0 rows affected

obclient> CREATE TRIGGER test_trg BEFORE INSERT ON test
       FOR EACH ROW SET @sum = @sum + NEW.user_num;
Query OK, 0 rows affected

```

此外，如果需要定义的触发器有多条执行语句时，可以使用 `BEGIN ... END` 语句，分别表示整个代码块的开始和结束。

`BEGIN ... END` 语句的语法为：

```sql
BEGIN
[statement_list]
END

```

其中，`statement_list` 表示一个或多个语句的列表，列表内的每条语句都必须使用分号（;）结尾。由于在 SQL 语句中，分号（;）是语句结束的标识符，遇到分号表示该段语句已经结束，系统就会开始执行该段语句，最终导致在执行过程中，解释器因为找不到与 `BEGIN` 匹配的 `END`而报错。为了避免发生此类错误，可以使用 `DELIMITER` 命令来修改语句结束符。

`DELIMITER` 命令示例如下：

```sql
DELIMITER new_delimiter

```

其中，`new_delimiter` 可以设置为 1 个或多个长度的符号，默认为分号（;），您可以将其修改为其他符号，例如 `#`。

添加 `DELIMITER` 命令后， `DELIMITER` 命令后的语句再使用分号则不会报错，直到遇到设置的结束符（`#`），才认为该语句结束。

> **注意**
>
>  
>
> 使用 `DELIMITER` 命令修改结束符后，待语句执行结束，请务必将结束符修改为默认符号分号（;）。

示例如下：

obclient>DELIMITER #

obclient>CREATE TRIGGER test_trg BEFORE UPDATE ON test
               FOR EACH ROW
               BEGIN
               IF NEW.user_num < 1 THEN
              SET NEW.user_num  = 1;
              ELSEIF NEW.user_num > 45 THEN
              SET NEW.user_num= 45;
             END IF;
             END;#
Query OK, 0 rows affected

obclient>DELIMITER ;

```

## 触发器的使用限制

MySQL 模式的触发器有以下使用限制：

- 对于同一个表，不能有多个触发器具备相同的触发事件和触发动作的时间。
 - 只能在永久表上创建触发器，不能对临时表创建触发器。
 - 触发器不能使用 `CALL` 语句调用将数据返回给客户端或使用动态 SQL 的存储过程，但是允许存储过程或者函数通过 `OUT` 或者 IN`OUT` 类型的参数将数据返回触发器。
 - 触发器中不能使用开启或结束事务的语句段，例如，开始事务（`START TRANSACTION`）、提交事务（`COMMIT`）或回滚事务（`ROLLBACK`），但是可以回滚到一个保存点，即 Savepoint 是允许的，因为回滚到保存点不会结束事务。
 - 外键不会激活触发器。
 - 触发器中不允许返回值，因此触发器中不能有返回语句，如果需要立即停止一个触发器，则需要使用 `LEAVE` 语句。

 上一篇 下一篇 ![有帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*y6ocSqN8cqsAAAAAAAAAAAAAARQnAQ)![无帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*BG9IQJyLHF8AAAAAAAAAAAAAARQnAQ)![反馈](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*eTWdQKCRKHwAAAAAAAAAAAAAARQnAQ)[AI](https://www.oceanbase.com/obi) 咨询热线
