深入浅出MySQL-07-【开发常用数据库对象】

发布于:2024-04-30 ⋅ 阅读:(27) ⋅ 点赞:(0)

前言

环境:

Windows11
MySQL-8.0.35

1.视图

MySQL从5.0.1版本开始提供视图功能,本节将对MySQL中的视图进行介绍。

1.1.什么是视图

视图(View)是一种虚拟存在的表,对于使用视图的用户来说基本上是透明的。视图并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。

视图相对于普通的表的优势主要包括以下几项:

  • 简单:使用视图的用户完全不需要关心后面对应的表的结构、关联条件和筛选条件,对用户来说已经是过滤好的复合条件的结果集。
  • 安全:使用视图的用户只能访问他们被允许查询的结果集,对表的权限管理并不能限制到某个行某个列,但是通过视图就可以简单地实现。
  • 数据独立:一旦视图的结构确定了,可以屏蔽表结构变化对用户的影响,源表增加列对视图没有影响;源表修改列名,则可以通过修改视图来解决,不会造成对访问者的影响。

1.2.视图操作

视图的操作包括创建或者修改视图、删除视图,以及查看视图定义。

1.3.创建或者修改视图

创建视图需要有 CREATE VIEW 的权限,并且对于查询涉及的列有SELECT权限。如果使用 CREATE OR REPLACE 或者 ALTER 修改视图,还需要该视图的DROP 权限。

创建视图的语法如下:

mysql> ? create view;
Name: 'CREATE VIEW'
Description:
Syntax:
CREATE
    [OR REPLACE]
    [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
    [DEFINER = user]
    [SQL SECURITY { DEFINER | INVOKER }]
    VIEW view_name [(column_list)]
    AS select_statement
    [WITH [CASCADED | LOCAL] CHECK OPTION]
    ... ...

修改视图的语法如下:

mysql> ? alter view;
Name: 'ALTER VIEW'
Description:
Syntax:
ALTER
    [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
    [DEFINER = user]
    [SQL SECURITY { DEFINER | INVOKER }]
    VIEW view_name [(column_list)]
    AS select_statement
    [WITH [CASCADED | LOCAL] CHECK OPTION]
        ... ...

例如,要创建一个视图 staff_list_view,可以使用如下命令:

mysql> CREATE OR REPLACE VIEW staff_list_view AS
	-> SELECT s.staff_id, s.first_name, s.last_name, a.address
	-> FROM staff AS s, addrss AS a
	-> where s.address_id = a.address_id ;
Query OK, 0 rows affected (0.00 sec)

注意:

  • 视图在 5.7.7 版本执之前,FROM关键字后面不能包含子查询。
  • 视图是基于SQL查询的,因此它的性能可能受到查询复杂性的影响。
  • 视图不存储数据,它只是保存了查询。因此,对基表的任何更改都会反映到视图中
  • 视图可以嵌套,即一个视图可以基于另一个视图。但是,过度嵌套可能导致性能下降和复杂性增加。
  • 不是所有的SQL语句都可以在视图中使用。例如,某些数据库系统可能不允许在视图中使用ORDER BY子句,或者对视图进行某些类型的更新操作。

视图的可更新性和视图中查询的定义有关系,以下类型的视图是不可更新的。

  • 包含以下关键字的 SQL语句:聚合函数(SUM、MIN、MAX、COUNT等)、DISTINCT、GROUP BY、HAVING、UNION 或 UNIONALL。
  • 常量视图。
  • SELECT中包含子查询。
  • JOIN。
  • FROM 一个不能更新的视图。
  • WHERE字句的子查询引用了FROM字句中的表。

例如,以下的视图都是不可更新的:

// 包含聚合函数的视图
mysql > create or replace view person_view as
	-> select id, sum(age) from person group by id;
Query OK, 0 rows affected (0.00 sec)

// 常量视图
mysql > create or replace view pi as
	-> select 3.1415926 as pi;
Query OK, 0 rows affected (0.00 sec)

// select中包含子查询
mysql > create or replace view city_view as
	-> select (select city from city where city_id = 1);
Query OK, 0 rows affected (0.00 sec)

WITH [CASCADED | LOCAL] CHECK OPTION 用于限制通过视图插入或更新的数据必须满足视图定义中的条件。当向视图中插入或更新数据时,MySQL 会检查这些数据是否满足定义视图时所基于的查询条件。如果数据不满足这些条件,操作将会失败。其中:

  • LOCAL 检查通过视图插入或更新的数据是否满足定义该视图的WHERE子句(如果有的话)的条件。如果数据不满足这些条件,MySQL会抛出一个错误。
  • CASCADED 确保通过视图插入或更新的数据不仅满足视图本身的条件,还满足所有底层基表(或基于试图的视图)上的约束条件。

示例,假设我们有一个名为 employees 的表,其中包含员工的信息,并且有一个基于该表的视图view_active_employees,该视图只显示 status = ‘active’ 的员工。

如果我们试图通过这个视图插入一个 status 不为 ‘active’ 的员工记录,那么操作将会失败,因为新记录不满足视图定义的条件。

注意:

  • 如果视图没有明确指定是 LOCAL 还是 CASCADED ,则默认就是 CASCADED 。
  • WITH CHECK OPTION 仅在通过视图进行的插入和更新操作时生效。它不会影响通过视图进行的查询操作。
  • 视图上的 WITH CHECK OPTION 不会覆盖基表上的任何约束。基表上的约束(如主键约束、唯一约束、外键约束等)仍然会单独应用。
  • 如果试图通过视图插入或更新数据,而这些数据违反了基表的约束,即使它们满足视图定义的条件,操作也会失败。

1.4.删除视图

可以一次删除一个或者多个视图,前提是有该视图的DROP权限。删除语法如下:

mysql> ? drop view;
Name: 'DROP VIEW'
Description:
Syntax:
DROP VIEW [IF EXISTS]
    view_name [, view_name] ...
    [RESTRICT | CASCADE]

示例,删除多个视图:

mysql> drop view if exists test_view1, test_view2 ...

1.5.查看视图

从 5.1 版本开始,使用 SHOW TABLES 命令的时候不仅显示表的名字,同时也会显示视图的名字,而不存在单独显示视图的SHOW VIEWS命令。

同样,使用 SHOW TABLES STATUS 命令的时候,不仅显示表的信息,同时也显示视图的名字,而不存在单独显示视图的 SHOW VIEWS 命令。语法如下:

mysql> ? show table status;
Name: 'SHOW TABLE STATUS'
Description:
Syntax:
SHOW TABLE STATUS
    [{FROM | IN} db_name]
    [LIKE 'pattern' | WHERE expr]

如果需要查询某个视图的定义,可以使用 SHOW CREATE VIEW 命令查看:

mysql> ? show create view
Name: 'SHOW CREATE VIEW'
Description:
Syntax:
SHOW CREATE VIEW view_name

同时也可以查看系统表 information_schema.views 查看视图的相关信息。

2.存储过程和函数

MySQL从版本 5.0 开始支持存储过程 和 函数。

2.1.什么是存储过程和函数

存储过程 和 函数 是事先经过编译并存储在数据库中的一段SQL语句的集合,调用存储过程和函数可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的。

存储过程和函数的区别在于:

  • 函数必须有返回值,而存储过程没有
  • 存储过程的参数可以使用IN、OUT、INOUT 类型,而函数的参数只能是IN类型的。

2.2.存储过程和函数的相关操作

在对存储过程或函数进行操作时,需要首先确认用户是否具有相应的权限。

例如,创建存储过程或者函数需要 CREATE ROUTINE 权限,修改或者删除存储过程或者函数需要 ALTER ROUTINE 权限,执行存储过程或者函数需要 EXECUTE 权限。

2.3.创建、修改存储过程或者函数

创建、修改 存储过程或函数 的语法如下:

mysql> ? create procedure
Name: 'CREATE PROCEDURE'
Description:
Syntax:
CREATE
    [DEFINER = user]
    // 这里是创建存储过程
    PROCEDURE [IF NOT EXISTS] sp_name ([proc_parameter[,...]])
    [characteristic ...] routine_body

CREATE
    [DEFINER = user]
    // 这里是创建函数
    FUNCTION [IF NOT EXISTS] sp_name ([func_parameter[,...]])
    RETURNS type
    [characteristic ...] routine_body

proc_parameter:
    [ IN | OUT | INOUT ] param_name type

func_parameter:
    param_name type

type:
    Any valid MySQL data type

characteristic: {
    COMMENT 'string'
  | LANGUAGE SQL
  | [NOT] DETERMINISTIC
  | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
  | SQL SECURITY { DEFINER | INVOKER }
}

routine_body:
    Valid SQL routine statement

调用存储过程的语法如下:

CALL procedure_name(parameter1, parameter2, ...);

MySQL的存储过程和函数中允许包含DDL语句,也允许在存储过程中执行提交(Commit,即确认之前的修改)或者回滚(Rollback,即放弃之前的修改),但是存储过程和函数中不允许执行LOAD DATA INFILE语句。此外,存储过程和函数中可以调用其他的过程或者函数。

下面列举几个创建存储过程以及调用示例:

// 示例1:不带参数的存储过程
CREATE PROCEDURE SayHello()  
BEGIN  
    SELECT 'Hello, World!';  
END;  
  
-- 调用存储过程  
CALL SayHello();

// ------------------------------------

// 带输入参数的存储过程
CREATE PROCEDURE GetEmployeeNameByID(IN emp_id INT)  
BEGIN  
    SELECT name FROM employees WHERE id = emp_id;  
END;  
  
-- 调用存储过程  
CALL GetEmployeeNameByID(1);

// -------------------------------------

// 示例3:带输入输出参数的存储过程
CREATE PROCEDURE DoubleNumber(INOUT num INT)  
BEGIN  
    SET num = num * 2;  
END;  
  
-- 调用存储过程  
SET @my_number = 5;  
CALL DoubleNumber(@my_number);  
SELECT @my_number;  -- 返回10

注意事项:

  • 存储过程是在MySQL服务器上执行的,而不是在客户端应用程序上。
  • 存储过程可以包含复杂的逻辑,包括条件语句、循环等。
  • 存储过程可以提高性能,因为它们的执行计划可以被缓存和重用。
  • 存储过程有助于保持数据库逻辑的一致性,因为它们封装了特定的业务规则。
  • 需要谨慎管理存储过程的权限,确保只有授权的用户可以创建、修改或执行存储过程。

通常我们在执行创建过程和函数之前,都会通过“DELIMITER $$”命令将语句的结束符从“;” 修改成其他符号,这里使用的是“$$”,这样在过程和函数中的“;”就不会被 MySQL解释成语句的结束而提示错误。存储过程或者函数创建完毕,通过“DELIMITER;”命令再将结束符改回成“;”

和视图不一样,存储过程和函数的 CREATE 语法不支持使用 CREATE OR REPLACE 语法进行修改,如果需要对已有的存储过程或函数进行修改,需要执行 ALTER 语法。

下面列举几个创建函数以及调用过程示例:

-- 接受一个整数参数并返回它的平方
DELIMITER //  
CREATE FUNCTION SquareNumber(x INT) RETURNS INT  
BEGIN  
    RETURN x * x;  
END //  
DELIMITER ;

在这个示例中,我们使用了DELIMITER来更改命令结束符,以便在函数体中使用分号。然后,我们定义了函数SquareNumber,它接受一个整数参数x,并返回x的平方。最后,我们将命令结束符恢复为分号。

创建函数后,你可以在SQL查询中像使用内置函数一样使用它:

SELECT SquareNumber(5);  -- 返回25

2.4.删除存储过程或函数

和视图不一样,这里一次只能删除一个存储过程或者函数(视图可以一次删除多个),删除存储过程或者函数需要相应的 ALTER ROUTINE 权限,语法如下:

mysql> ? drop procedure
Name: 'DROP PROCEDURE'
Description:
Syntax:
DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name

2.5.查看存储过程或者函数

查看存储过程、函数的状态、定义等信息。

2.5.1.查看存储过程或函数的状态

SHOW {PROCEDURE | FUNCTION} STATUS
    [LIKE 'pattern' | WHERE expr]

2.5.2.查看存储过程或函数的定义

SHOW CREATE {PROCEDURE | FUNCTION} sp_name

2.5.3.通过查看 information_schema.Routines 了解存储过程和函数的信息

除了上述两种方法,我们还可以查看系统表来了解存储过程和函数的相关信息,通过查看 information_schema.Routines 就可以获得存储过程和函数的名称、类型、语法、创建人等信息。语法如下:

select * from routines where routine_name = 'sp_name' \G

2.6.变量的使用

存储过程和函数中可以使用变量,在版本 5.1 开始,变量是不区分大小写的。

2.6.1.变量的定义

通过 DECLARE 可以定义一个局部变量,该变量的作用范围只能在BEGIN…END 块中,可以用在嵌套的块中。变量的定义必须写在复合语句的开头,并且在任何其他语句的前面。可以一次声明多个相同类型的变量。如果需要,可以使用 DEFAULT 赋默认值。

定义一个变量的语法如下:

mysql> ? declare variable
Name: 'DECLARE VARIABLE'
Description:
Syntax:
DECLARE var_name [, var_name] ... type [DEFAULT value]

例如定义一个DATE类型的变量last_month_start:

DECLARE last_month_start DATE;

2.6.2.变量的赋值

变量可以直接赋值,或者通过查询赋值。直接赋值使用 SET,可以赋常量或者表达式,具体语法如下:

SET var_name = expr [, var_name = expr] ...

给刚才定义的变量 last_month_start 赋值,如下:

SET last_month_start = DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH);

也可以通过查询将结果赋值给变量,使用 SELECT … INTO ,这要求查询返回的结果必须只有一行,如下:

SELECT col_name[, ...] INTO var_name [, ...] table_expr

2.7.定义条件和处理

条件的定义和处理可以用来定义在处理过程中遇到问题将如何进行相应的处理。

2.7.1.条件的定义

语法如下:

mysql>? declare condition
Name: 'DECLARE CONDITION'
Description:
Syntax:
DECLARE condition_name CONDITION FOR condition_value

condition_value: {
    mysql_error_code
  | SQLSTATE [VALUE] sqlstate_value
}

DECLARE CONDITION 允许你基于特定的SQLSTATE值或MySQL错误代码定义一个命名条件。这可以使得错误处理代码更具可读性和可维护性。

示例:

-- 基于SQLSTATE值定义条件
DECLARE custom_condition CONDITION FOR SQLSTATE '42000'; 

或者 

-- 基于MySQL错误代码定义条件(例如,重复键错误)
DECLARE custom_condition CONDITION FOR 1062;

2.7.2.条件的处理

语法如下:

mysql> ? declare handler
Name: 'DECLARE HANDLER'
Description:
Syntax:
DECLARE handler_action HANDLER
    FOR condition_value [, condition_value] ...
    statement

handler_action: {
    CONTINUE
  | EXIT
  | UNDO
}

condition_value: {
    mysql_error_code
  | SQLSTATE [VALUE] sqlstate_value
  | condition_name
  | SQLWARNING
  | NOT FOUND
  | SQLEXCEPTION
}

DECLARE HANDLER 用于声明一个处理程序,该处理程序会在指定的条件被触发时执行。你可以为不同类型的条件(如 NOT FOUND, SQLEXCEPTION, 或自定义条件)声明处理程序。

处理程序可以是 CONTINUE 类型的,这意味着当处理程序执行完毕后,存储过程或函数将继续执行后续语句;也可以是 EXIT 类型的,这会在处理程序执行完毕后终止存储过程或函数的执行。

示例:

DECLARE CONTINUE HANDLER FOR custom_condition  
BEGIN  
    -- 当custom_condition被触发时,这里的代码将被执行  
    SELECT 'Custom condition occurred, but procedure execution continued.';  
END;

或者,你可以直接基于SQLSTATE或错误代码声明处理程序,而无需首先使用 DECLARE CONDITION:

DECLARE CONTINUE HANDLER FOR SQLSTATE '42000'  
BEGIN  
    -- 当SQLSTATE '42000'的错误发生时,这里的代码将被执行  
    SELECT 'A syntax error occurred, but procedure execution continued.';  
END;

可以在一个存储过程或函数中同时使用 DECLARE CONDITION 和 DECLARE HANDLER。首先定义命名条件,然后声明处理程序来响应这些条件。

DELIMITER //  
CREATE PROCEDURE MyProcedure()  
BEGIN  
    -- 定义命名条件  
    DECLARE custom_condition CONDITION FOR SQLSTATE '42000';  
  
    -- 声明处理程序  
    DECLARE CONTINUE HANDLER FOR custom_condition  
    BEGIN  
        -- 当custom_condition被触发时执行的代码  
        SELECT 'Custom syntax error occurred, but procedure execution continued.';  
    END;  
  
    -- 可能会触发custom_condition的SQL语句  
    -- 例如,一个带有语法错误的SQL语句  
    SELECT column_that_doesnt_exist FROM my_table;  
END //  
DELIMITER ;

在这个例子中,如果 SELECT 语句因为列不存在而触发了一个 42000 的SQLSTATE错误,那么自定义的处理程序将被执行,输出一条消息,并且存储过程将继续执行后续的代码(因为使用了 CONTINUE HANDLER)。如果没有定义处理程序,那么这个错误通常会导致存储过程终止。

2.8.光标(游标)的使用

在存储过程和函数中,可以使用光标对结果集进行循环的处理。光标的使用包括光标的 声明、OPEN、FETCH和CLOSE,其语法分别如下。

  • 声明光标

需要声明一个游标,并指定它将用于哪个查询:

DECLARE cursor_name CURSOR FOR select_statemet
  • OPEN光标

声明游标后,你需要打开它以便可以开始读取数据:

OPEN cursor_name
  • FETCH光标

可以使用 FETCH 语句从游标中获取数据。这通常在一个循环中进行,直到没有更多的行可以获取:

FETCH [[NEXT] FROM] cursor_name INTO var_name [, var_name] ...
  • CLOSE光标

当你完成从游标中读取数据后,应该关闭它:

CLOSE cursor_name

注意:

  • 变量、条件、处理程序、光标都是通过 DECLARE定义的,它们之间是有先后顺序要求的。变量和条件必须在最前面声明,然后才能是光标的声明,最后才可以是处理程序的声明。
  • 游标在数据库操作中相对较慢,并且可能增加系统的开销。因此,除非确实需要逐行处理数据,否则通常建议避免使用游标,并尽可能使用集合操作来处理查询结果。
  • 游标主要用于存储过程和函数。如果你只是在执行简单的查询并从结果集中获取数据,那么通常不需要使用游标。

2.9.流程控制

在 MySQL 中,特别是在存储过程、函数或触发器中,你可以使用流程控制语句来控制程序的执行流程。这些流程控制语句包括条件语句(如 IF、CASE)、循环语句(如 LOOP、WHILE、REPEAT…UNTIL)以及标签和跳转语句(如 LEAVE、ITERATE)。

2.9.1.条件语句IF

实现条件判断,满足不同的条件执行不同的语句列表,语法如下:

mysql> ? if statement
Name: 'IF STATEMENT'
Description:
Syntax:
IF search_condition THEN statement_list
    [ELSEIF search_condition THEN statement_list] ...
    [ELSE statement_list]
END IF

2.9.2.条件语句CASE

CASE可以实现比 IF 更复杂一些的条件构造,语法如下:

mysql> ? case statement
Name: 'CASE STATEMENT'
Description:
Syntax:
CASE case_value
    WHEN when_value THEN statement_list
    [WHEN when_value THEN statement_list] ...
    [ELSE statement_list]
END CASE

Or:

CASE
    WHEN search_condition THEN statement_list
    [WHEN search_condition THEN statement_list] ...
    [ELSE statement_list]
END CASE

2.9.3.循环语句LOOP

LOOP实现简单的循环,退出循环的条件需要使用其他的语句定义,通常使用LEAVE语句实现,语法如下:

mysql> ? loop
Name: 'LOOP'
Description:
Syntax:
[begin_label:] LOOP
    statement_list
END LOOP [end_label]

如果不在 statement_list 中增加退出循环的语句,那将是一个死循环。

2.9.4.循环语句WHILE

实现的是有条件的循环控制语句,即当满足条件时执行循环的内容,语法如下:

mysql> ? while
Name: 'WHILE'
Description:
Syntax:
[begin_label:] WHILE search_condition DO
    statement_list
END WHILE [end_label]

WHILE和下面 REPEAT 循环的区别在于:

  1. WHILE是满足条件才执行循环,REPEAT是满足条件退出循环。
  2. WHILE在首次循环执行之前就判断条件,所以循环最少执行0次,而REPEAT是在首次循环之后才判断条件,所以循环最少执行1次。

2.9.5.循环语句REPEAT…UNTIL

也是有条件的循环控制语句,当满足条件的时候退出循环,具体语法如下:

mysql> ? repeat loop
Name: 'REPEAT LOOP'
Description:
Syntax:
[begin_label:] REPEAT
    statement_list
UNTIL search_condition
END REPEAT [end_label]

2.9.6.标签和跳转语句LEAVE

用来从标注的流程构造中退出,通常和 BEGIN … END 或者 循环一起使用,具体语法如下:

mysql> ? leave
Name: 'LEAVE'
Description:
Syntax:
LEAVE label

2.9.7.标签和跳转语句ITERATE

必须用在循环中,作用是跳过当前循环的剩下的语句,直接进入下一轮循环(类似于java的continue)。具体语法如下:

mysql> ? iterate
Name: 'ITERATE'
Description:
Syntax:
ITERATE label

2.10.事件调度器

可以将数据库按照自定义的时间周期出发某种操作,可以理解为时间触发器,类似Linux系统在的任务调度器 crontab。

具体语法如下:

mysql> ? create event
Name: 'CREATE EVENT'
Description:
Syntax:
CREATE
    [DEFINER = user]
    EVENT
    [IF NOT EXISTS]
    event_name
    ON SCHEDULE schedule
    [ON COMPLETION [NOT] PRESERVE]
    [ENABLE | DISABLE | DISABLE ON SLAVE]
    [COMMENT 'string']
    DO event_body;

schedule: {
    AT timestamp [+ INTERVAL interval] ...
  | EVERY interval
    [STARTS timestamp [+ INTERVAL interval] ...]
    [ENDS timestamp [+ INTERVAL interval] ...]
}

interval:
    quantity {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE |
              WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |
              DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}

如果时间调度器不再使用,可以禁用(disable)或者删除(drop):

-- alter event, 禁用
mysql> ? alter event
Name: 'ALTER EVENT'
Description:
Syntax:
ALTER
    [DEFINER = user]
    EVENT event_name
    [ON SCHEDULE schedule]
    [ON COMPLETION [NOT] PRESERVE]
    [RENAME TO new_event_name]
    [ENABLE | DISABLE | DISABLE ON SLAVE]
    [COMMENT 'string']
    [DO event_body]
或者 

-- drop event,删除
mysql> ? drop event
Name: 'DROP EVENT'
Description:
Syntax:
DROP EVENT [IF EXISTS] event_name

3.触发器

触发器是与表有关的数据库对象,在满足定义条件时触发,并执行触发器中定义的语句集合。

也就是说MySQL的触发器(Trigger)是一种特殊的存储过程,它在指定的数据库事件(如INSERT、UPDATE或DELETE操作)发生时自动执行。触发器的主要作用包括数据完整性约束、日志记录和审计、数据同步和复制等。

触发器的主要组成部分包括:

  • 触发时机:指定触发器是在事件之前(BEFORE)还是之后(AFTER)执行。
  • 触发事件:与触发器关联的数据库操作,如INSERT、UPDATE或DELETE。
  • 触发的表:触发器所关联的表。
  • 触发逻辑:当触发器被激活时执行的SQL语句或操作。

3.1.创建触发器

创建触发器语法如下:

mysql> ? create trigger
Name: 'CREATE TRIGGER'
Description:
Syntax:
CREATE
    [DEFINER = user]
    TRIGGER [IF NOT EXISTS] trigger_name
    trigger_time trigger_event
    ON tbl_name FOR EACH ROW
    [trigger_order]
    trigger_body

trigger_time: { BEFORE | AFTER }

trigger_event: { INSERT | UPDATE | DELETE }

trigger_order: { FOLLOWS | PRECEDES } other_trigger_name

注意:

  • 触发器只能创建在永久表上,不能对临时表创建触发器

3.2.删除触发器

一次可以删除一个触发器,具体语法如下:

mysql> ? drop trigger
Name: 'DROP TRIGGER'
Description:
Syntax:
DROP TRIGGER [IF EXISTS] [schema_name.]trigger_name

3.3.查看触发器

mysql> ? show triggers
Name: 'SHOW TRIGGERS'
Description:
Syntax:
SHOW TRIGGERS
    [{FROM | IN} db_name]
    [LIKE 'pattern' | WHERE expr]

3.4.触发器的使用

触发器执行的语句有以下两个限制:

  • 触发程序既不能调用将数据返回客户端的存储程序,也不能使用采用 CALL 语句的动态 SOL语句,但是允许存储程序通过参数将数据返回触发程序。也就是存储过程或者函数通过 OUT或者 INOUT 类型的参数将数据返回触发器是可以的,但是不能调用直接返回数据的过程。

  • 不能在触发器中使用以显式或隐式方式开始或结束事务的语句,如START TRANS-ACTION、COMMIT或ROLLBACK。

MySQL的触发器是按照 BEFORE 触发器、行操作、AFTER 触发器的顺序执行的,其中任何一步操作发生错误都不会继续执行剩下的操作。

如果是对事务表进行的操作,那么会整个作为一个事务被回滚(Rollback),但是如果是对非事务表进行的操作,那么已经更新的记录将无法回滚。