暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

OceanBase系统架构PL触发器

2024-01-21
286

OceanBase 数据库 MySQL 模式兼容 MySQL 5.6 的触发器。触发器是与表相关的数据库对象,触发器可以在语句插入、更新或删除关联表中的行时被激活。例如,您可以通过 INSERT 或 LOAD DATA 语句插入行,并且每插入一行就会激活一次 INSERT 触发器。如果批量插入两行数据,则会出发两次触发器。

触发器可以设置为在触发事件之前或之后激活。例如,您可以在插入表的每一行之前或在更新的每一行之后激活触发器。

触发器类型

OceanBase 数据库 MySQL 模式当前主要支持以下类型的触发器:

  • INSERT 型触发器:表示插入某一行时激活触发器,可以通过 INSERTLOAD DATAREPLACE 语句触发。

  • UPDATE 型触发器:表示更改某一行时激活触发器,可以通过 UPDATE 语句触发。

  • DELETE 型触发器:删除某一行时激活触发器,可以通过 DELETEREPLACE 语句触发。

比较特殊的是 INSERT INTO ... ON DUPLICATE KEY UPDATE 语句,每个行都会激活一个 BEFORE INSERT 触发器,接着是 AFTER INSERT 触发器或者 BEFORE UPDATE 与 AFTER UPDATE 触发器,是 AFTER INSERT 触发器还是 BEFORE UPDATE 与 AFTER UPDATE 触发器主要取决于行是否有重复的键。

创建触发器

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

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

  • 当前触发器关联的表的权限,包括 SELECTINSERTUPDATEDELETE 等权限。

  • 创建触发器权限,即 CREATE 权限。

  • 触发器激活后要执行的语句的权限。

创建触发器的 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 表示触发动作的时间,例如触发器将在每一行插入到表中之前还是之后激活。

  • INSERTUPDATE 或 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 操作,且触发器充当累加器,将插入到表的列的值求和。

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 语句的语法为:

BEGIN
[statement_list]
END

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

DELIMITER 命令示例如下:

DELIMITER new_delemiter

其中,new_delemiter 可以设置为 1 个或多个字节长度的符号,默认为分号(;),您可以将其修改为其他符号,例如 #

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

注意

使用 DELIMITER 命令修改结束符后,待语句执行结束,请务必将结束符修改为默认符号分号(;)。

示例如下:

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

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 语句。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论