一. Rank

给出不同的用户的分数,然后根据分数计算排名

  1. (gcdb@localhost) 09:34:47 [mytest]> create table t_rank(id int,score int);
  2. Query OK, 0 rows affected (0.02 sec)
  3. (gcdb@localhost) 10:13:03 [mytest]> insert into t_rank values(1, 10), (2, 20), (3, 30), (4, 30), (5, 40), (6, 40);
  4. Query OK, 6 rows affected (0.00 sec)
  5. Records: 6 Duplicates: 0 Warnings: 0
  6. (gcdb@localhost) 10:13:13 [mytest]> select * from t_rank;
  7. +------+-------+
  8. | id | score |
  9. +------+-------+
  10. | 1 | 10 |
  11. | 2 | 20 |
  12. | 3 | 30 |
  13. | 4 | 30 |
  14. | 5 | 40 |
  15. | 6 | 40 |
  16. +------+-------+
  17. 6 rows in set (0.00 sec)
  18. (gcdb@localhost) 10:13:24 [mytest]>
  19. (gcdb@localhost) 10:21:54 [mytest]> SET @prev_value := NUll;
  20. Query OK, 0 rows affected (0.00 sec)
  21. -- 假设比较到第N行,设置一个变量prev_value用于存放第N-1score的分数
  22. -- 用于比较第N行的score和第N-1行的score
  23. -- prev_value可以理解为 是临时保存第N-1行的score的变量
  24. (gcdb@localhost) 10:25:38 [mytest]> set @rank_count := 0; -- 用于存放当前的排名
  25. Query OK, 0 rows affected (0.00 sec)
  26. (gcdb@localhost) 10:25:38 [mytest]> select id, score,
  27. -> case
  28. -> when @prev_value = score then @rank_count
  29. -- 相等则prev_value不变, 并返回rank_count(第一次为NULL,不会相等,所以跳转到下一个when语句)
  30. -> when @prev_value := score then @rank_count := @rank_count + 1
  31. -- 不等,则第N行的score赋值(:=)给prev_value。且rank_count增加1
  32. -> end as rank_column -- case 开始的,end结尾
  33. -> from t_rank
  34. -> order by score desc;
  35. +------+-------+-------------+
  36. | id | score | rank_column |
  37. +------+-------+-------------+
  38. | 5 | 40 | 1 |
  39. | 6 | 40 | 1 |
  40. | 3 | 30 | 2 |
  41. | 4 | 30 | 2 |
  42. | 2 | 20 | 3 |
  43. | 1 | 10 | 4 |
  44. +------+-------+-------------+
  45. 6 rows in set (0.00 sec)
  46. -- case
  47. -- when [condition_1] then [do_something_1]
  48. -- when [condition_2] then [do_something_2]
  49. -- end
  50. -- 语法: 如果 condition_1条件满足,则执行 do_something_1 然后就跳出,不会执行condition_2;
  51. -- 如果 condition_1条件不满足,则继续执行到 condition_2。以此类推。

-上面语句一句编写

  1. "select id, score,
  2. case
  3. when @prev_value = score then @rank_count
  4. when @prev_value := score then @rank_count := @rank_count + 1
  5. end as rank_column
  6. from t_rank t,
  7. (SELECT @prev_value := NUll,@rank_count:= 0 ) a
  8. order by score desc;"
  9. (gcdb@localhost) 10:26:57 [mytest]> select id, score,
  10. -> case
  11. -> when @prev_value = score then @rank_count
  12. -> when @prev_value := score then @rank_count := @rank_count + 1
  13. -> end as rank_column
  14. -> from t_rank t,
  15. -> (SELECT @prev_value := NUll,@rank_count:= 0 ) a --把@prev_value@rank_count放到子查询里面
  16. -> order by score desc;
  17. +------+-------+-------------+
  18. | id | score | rank_column |
  19. +------+-------+-------------+
  20. | 5 | 40 | 1 |
  21. | 6 | 40 | 1 |
  22. | 3 | 30 | 2 |
  23. | 4 | 30 | 2 |
  24. | 2 | 20 | 3 |
  25. | 1 | 10 | 4 |
  26. +------+-------+-------------+
  27. 6 rows in set (0.00 sec)
  28. (gcdb@localhost) 11:06:00 [mytest]>

rank参考资料


二. 视图

官方view文档

2.1、创建视图

  1. --
  2. -- 创建视图,视图名v_rank
  3. --
  4. (gcdb@localhost) 11:34:40 [mytest]> create view v_rank as select * from t_rank; --对select结果增加条件进行过滤后,再创建视图
  5. Query OK, 0 rows affected (0.04 sec)
  6. (gcdb@localhost) 11:35:08 [mytest]> show create table v_rank \G; --查看视图表结构
  7. *************************** 1. row ***************************
  8. View: v_rank
  9. Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`gcdb`@`%` SQL SECURITY DEFINER VIEW `v_rank` AS select `t_rank`.`id` AS `id`,`t_rank`.`score` AS `score` from `t_rank`
  10. character_set_client: utf8
  11. collation_connection: utf8_general_ci --显示的是视图的定义
  12. 1 row in set (0.00 sec)
  13. ERROR:
  14. No query specified
  15. (gcdb@localhost) 11:35:48 [mytest]> show create table t_rank \G; --查看原表结构
  16. *************************** 1. row ***************************
  17. Table: t_rank
  18. Create Table: CREATE TABLE `t_rank` (
  19. `id` int(11) DEFAULT NULL,
  20. `score` int(11) DEFAULT NULL
  21. ) ENGINE=InnoDB DEFAULT CHARSET=utf8
  22. 1 row in set (0.00 sec)
  23. ERROR:
  24. No query specified
  25. (gcdb@localhost) 11:35:59 [mytest]> select * from v_rank; -- 可以直接查询该视图得结果
  26. +------+-------+
  27. | id | score |
  28. +------+-------+
  29. | 1 | 10 |
  30. | 2 | 20 |
  31. | 3 | 30 |
  32. | 4 | 30 |
  33. | 5 | 40 |
  34. | 6 | 40 |
  35. +------+-------+
  36. 6 rows in set (0.00 sec)
  37. -- 视图的作用是,可以对开发人员是透明的,屏蔽部分敏感的列
  38. -- 视图在mysql是虚拟表。根据视图的定义,还是取执行定义中的select语句。
  39. -- 只开放部分列
  40. (gcdb@localhost) 11:40:35 [mytest]> create view v_rank_01 as select id from t_rank; -- 只开放id
  41. Query OK, 0 rows affected (0.00 sec)
  42. (gcdb@localhost) 11:42:50 [mytest]> select * from v_rank_01; -- 即使 select * ,也只能看到id列,具有隐藏原来表中部分列的功能
  43. +------+
  44. | id |
  45. +------+
  46. | 1 |
  47. | 2 |
  48. | 3 |
  49. | 4 |
  50. | 5 |
  51. | 6 |
  52. +------+
  53. 6 rows in set (0.00 sec)
  54. -- 不要取用select * from 去创建视图,因为mysql会把*逐个解析成列。
  55. -- 当原来的表结构发生变化时,视图的表结构是不会发生变化的,视图在创建的瞬间,便确定了结构。
  56. -- 比如,当你alter原来的表 增加列(add columns)时,再去查询该视图,新增加的列是不存在的。
  57. (gcdb@localhost) 11:43:20 [mytest]> alter table t_rank add column c int default 0; -- 增加一列名字为c,默认值为0
  58. Query OK, 0 rows affected (0.06 sec)
  59. Records: 0 Duplicates: 0 Warnings: 0
  60. (gcdb@localhost) 11:44:59 [mytest]> select * from t_rank; -- 查询原表
  61. +------+-------+------+
  62. | id | score | c |
  63. +------+-------+------+
  64. | 1 | 10 | 0 |
  65. | 2 | 20 | 0 |
  66. | 3 | 30 | 0 |
  67. | 4 | 30 | 0 |
  68. | 5 | 40 | 0 |
  69. | 6 | 40 | 0 |
  70. +------+-------+------+
  71. 6 rows in set (0.00 sec)
  72. (gcdb@localhost) 11:45:08 [mytest]> select * from v_rank; -- 尽管view_rankselect * 创建,但当时没有列c,所以无法得到c列的值
  73. +------+-------+
  74. | id | score |
  75. +------+-------+
  76. | 1 | 10 |
  77. | 2 | 20 |
  78. | 3 | 30 |
  79. | 4 | 30 |
  80. | 5 | 40 |
  81. | 6 | 40 |
  82. +------+-------+
  83. 6 rows in set (0.00 sec)
  84. (gcdb@localhost) 11:49:35 [mytest]> drop view v_rank_01; --删除视图
  85. Query OK, 0 rows affected (0.01 sec)
  86. -- 注意:mysql中的视图都是虚拟表。不像Oracle可以物化成真实存在的表。
  87. -- 每次查询视图,实际上还是去查询的原来的表,只是查询的规则是在视图创建时经过定义的。

2.2、视图的算法

  • 视图的算法(ALGORITHM)有三种方式:

    • UNDEFINED : 默认方式,由MySQL来判断使用下面的哪种算法
    • MERGE每次通过物理表查询得到结果,把结果merge(合并)起来返回
    • TEMPTABLE : 产生一张临时表,把数据放入临时表后,客户端再去临时表取数据(不会缓存

TEMPTABLE 特点 :即使访问条件一样,第二次查询还是会去读取物理表中的内容,并重新生成一张临时表,并不会取缓存之前的表。(临时表是Memory存储引擎,默认放内存,超过配置大小放磁盘)
当查询有一个较大的结果集时,使用TEMPTABLE可以快速的结束对该物理表的访问,从而可以快速释放这张物理表上占用的资源。然后客户端可以对临时表上的数据做一些耗时的操作,而不影响原来的物理表。所以一般我们使用默认的UNDEFINED,由MySQL自己去判断


三. 触发器

官方trigger文档

3.1、触发器介绍

  • 触发器定义

    • 触发器的对象是,当表上出现特定的事件触发该程序的执行
  • 触发器的类型

    • UPDATE

      • update 操作
    • DELETE

      • delete 操作
      • replace 操作
        • 注意:drop,truncate等DDL操作不会触发DELETE
    • INSERT

      • insert 操作
      • load data 操作
      • replace 操作

注意:replace操作会触发两次,一次是UPDATE类型的触发器,一次是INSERT类型的触发器

MySQL 5.6版本同一个类型的触发器只能有一个(单个表)

MySQL 5.7允许多个同一类型的触发器

触发器只触发DML(Data Manipulation Language)操作,不会触发DDL(Data Definition Language)操作 (create,drop等操作)

3.2、触发器语法

  • 创建触发器
  1. CREATE
  2. [DEFINER = { user | CURRENT_USER }]
  3. TRIGGER trigger_name -- 触发器名字
  4. trigger_time trigger_event -- 触发时间和事件
  5. ON tbl_name FOR EACH ROW
  6. [trigger_order]
  7. trigger_body
  8. trigger_time: { BEFORE | AFTER } -- 事件之前还是之后触发
  9. trigger_event: { INSERT | UPDATE | DELETE } -- 三个类型
  10. trigger_order: { FOLLOWS | PRECEDES } other_trigger_name
  • trigger_name:标识触发器名称,用户自行指定;
  • trigger_time:标识触发时机,取值为 BEFORE 或 AFTER;
  • trigger_event:标识触发事件,取值为 INSERT、UPDATE 或 DELETE;
  • tbl_name:标识建立触发器的表名,即在哪张表上建立触发器;
  • trigger_stmt:触发器程序体,可以是一句SQL语句,或者用 BEGIN 和 END 包含的多条语句。
  • trigger_order:值为FOLLOWS 或者 PRECEDES 后面跟上现有的触发器的名字(注意:这两个触发器的触发条件和触发时间必须一样)。如果为FOLLOWS,这个新的触发器就会在现有的触发器之后被触发。如果为PRECEDES,就会在现有的触发器之前执行。
  • trigger_body:触发器的程序体

由此可见,可以建立6种触发器,即:BEFORE INSERT、BEFORE UPDATE、BEFORE DELETE、AFTER INSERT、AFTER UPDATE、AFTER DELETE

另外有一个限制是5.7.2之前不能同时在一个表上建立2个相同类型的触发器。

3.3、UPDATE 类型触发器

  1. (gcdb@localhost) 11:49:38 [mytest]> create table t_trigger(name varchar(32),score int(10),primary key(name));
  2. Query OK, 0 rows affected (0.01 sec)
  3. (gcdb@localhost) 12:10:21 [mytest]> insert into t_trigger values('fanghao',88),('caowei',59),('xuliuyann',93);
  4. Query OK, 3 rows affected (0.00 sec)
  5. Records: 3 Duplicates: 0 Warnings: 0
  6. (gcdb@localhost) 13:46:20 [mytest]> select * from t_trigger;
  7. +----------+-------+
  8. | name | score |
  9. +----------+-------+
  10. | caowei | 59 |
  11. | fanghao | 88 |
  12. | xuliuyan | 93 |
  13. +----------+-------+
  14. 3 rows in set (0.00 sec)
  15. (gcdb@localhost) 14:00:10 [mytest]> delimiter // -- 将语句分隔符定义设置为 // (原来是';')
  16. (gcdb@localhost) 14:00:44 [mytest]> create trigger trg_update_score -- 定义触发器名字
  17. -> before update on t_trigger -- 作用在test_trigger_1 更新(update)之前(before)
  18. -> for each row -- 每行
  19. -> begin -- 开始定义
  20. -> if new.score < 60 then set new.score=60; -- 如果新值小于60,则设置为60
  21. -> elseif new.score > 100 then set new.score=100; -- 如果新值大于100,则设置为100
  22. -> end if; -- if 对应结束
  23. -> end -- begin 对应结束
  24. -> //
  25. Query OK, 0 rows affected (0.01 sec)
  26. (gcdb@localhost) 14:11:52 [mytest]> delimiter ; -- 将语句分隔符定义设置为 ';' 结束符
  27. (gcdb@localhost) 14:02:21 [mytest]> show triggers from mytest \G;
  28. *************************** 1. row ***************************
  29. Trigger: trg_update_score
  30. Event: UPDATE --定义为update类型
  31. Table: t_trigger
  32. Statement: if new.score < 60 then set new.score=60;
  33. elseif new.score > 100 then set new.score=100;
  34. end if
  35. Timing: BEFORE
  36. Created: 2017-12-09 14:00:45.45
  37. sql_mode:
  38. Definer: gcdb@%
  39. character_set_client: utf8
  40. collation_connection: utf8_general_ci
  41. Database Collation: utf8_general_ci
  42. 1 row in set (0.00 sec)
  43. ERROR:
  44. No query specified
  45. (gcdb@localhost) 14:21:41 [mytest]> insert into t_trigger values('tom',55); -- 插入tom,分数55
  46. Query OK, 1 row affected (0.00 sec)
  47. (gcdb@localhost) 14:21:55 [mytest]> select * from t_trigger;
  48. +------+-------+
  49. | name | score |
  50. +------+-------+
  51. | tom | 55 |
  52. +------+-------+
  53. 1 row in set (0.00 sec)
  54. (gcdb@localhost) 14:21:58 [mytest]> update t_trigger set score=58 where name = 'tom'; --更新tom分数为58
  55. Query OK, 1 row affected (0.00 sec)
  56. Rows matched: 1 Changed: 1 Warnings: 0
  57. (gcdb@localhost) 14:22:09 [mytest]> select * from t_trigger;
  58. +------+-------+
  59. | name | score |
  60. +------+-------+
  61. | tom | 60 | --因为update类型,触发了触发器,score值小60设置为60
  62. +------+-------+
  63. 1 row in set (0.00 sec)
  64. (gcdb@localhost) 14:22:11 [mytest]> insert into t_trigger values('sim',111); -- 插入sim,分数111
  65. Query OK, 1 row affected (0.00 sec)
  66. (gcdb@localhost) 14:22:26 [mytest]> update t_trigger set score=2222 where name = 'sim'; -- 插入sim,分数2222,触发了触发器,score值大于100设置为100
  67. Query OK, 1 row affected (0.00 sec)
  68. Rows matched: 1 Changed: 1 Warnings: 0
  69. (gcdb@localhost) 14:22:39 [mytest]> select * from t_trigger;
  70. +------+-------+
  71. | name | score |
  72. +------+-------+
  73. | sim | 100 |
  74. | tom | 60 |
  75. +------+-------+
  76. 2 rows in set (0.00 sec)
  77. (gcdb@localhost) 14:22:42 [mytest]> update t_trigger set score=99 where name = 'sim'; --更新sim分数为99,触发了触发器但是,分数在60< score <100 之间,不符合更改条件,未设置,还是99
  78. Query OK, 1 row affected (0.00 sec)
  79. Rows matched: 1 Changed: 1 Warnings: 0
  80. (gcdb@localhost) 14:22:49 [mytest]> select * from t_trigger;
  81. +------+-------+
  82. | name | score |
  83. +------+-------+
  84. | sim | 99 |
  85. +------+-------+
  86. 2 rows in set (0.00 sec)
  87. (gcdb@localhost) 14:22:50 [mytest]>

3.4、INSERT 类型触发器

*创建两张测试表

  1. (gcdb@localhost) 14:44:36 [mytest]> create table t_teachar(tid varchar(30) primary key,tpasswd varchar(32) not null);
  2. Query OK, 0 rows affected (0.01 sec)
  3. (gcdb@localhost) 14:46:57 [mytest]> create table t_user(uid varchar(30) primary key,upasswd varchar(32) not null);
  4. Query OK, 0 rows affected (0.01 sec)
  5. (gcdb@localhost) 14:56:56 [mytest]> show create table t_user \G;
  6. *************************** 1. row ***************************
  7. Table: t_user
  8. Create Table: CREATE TABLE `t_user` (
  9. `uid` varchar(30) NOT NULL,
  10. `upasswd` varchar(32) NOT NULL,
  11. PRIMARY KEY (`uid`)
  12. ) ENGINE=InnoDB DEFAULT CHARSET=utf8
  13. 1 row in set (0.00 sec)
  14. ERROR:
  15. No query specified
  16. (gcdb@localhost) 14:57:09 [mytest]> show create table t_terchar \G;
  17. *************************** 1. row ***************************
  18. Table: t_terchar
  19. Create Table: CREATE TABLE `t_terchar` (
  20. `tid` varchar(30) NOT NULL,
  21. `tpasswd` varchar(32) NOT NULL,
  22. PRIMARY KEY (`tid`)
  23. ) ENGINE=InnoDB DEFAULT CHARSET=utf8
  24. 1 row in set (0.00 sec)
  25. ERROR:
  26. No query specified
  27. (gcdb@localhost) 15:13:40 [mytest]> DELIMITER //
  28. (gcdb@localhost) 15:14:02 [mytest]> CREATE TRIGGER trg_insert_after_teachar
  29. -> AFTER INSERT ON t_teachar
  30. -> FOR EACH ROW
  31. -> BEGIN
  32. -> INSERT t_user(uid, upasswd) VALUES(NEW.tid, NEW.tpasswd); --在t_teachar表插入语句之后也在t_user表插入语句
  33. -> END
  34. -> //
  35. Query OK, 0 rows affected (0.01 sec)
  36. (gcdb@localhost) 15:14:02 [mytest]> DELIMITER ;
  37. (gcdb@localhost) 15:14:09 [mytest]> show triggers \G;
  38. *************************** 1. row ***************************
  39. Trigger: trg_insert_after_teachar
  40. Event: INSERT
  41. Table: t_teachar
  42. Statement: BEGIN
  43. INSERT t_user(uid, upasswd) VALUES(NEW.tid, NEW.tpasswd);
  44. END
  45. Timing: AFTER
  46. Created: 2017-12-09 15:14:02.07
  47. sql_mode:
  48. Definer: gcdb@%
  49. character_set_client: utf8
  50. collation_connection: utf8_general_ci
  51. Database Collation: utf8_general_ci
  52. (gcdb@localhost) 15:14:19 [mytest]> insert into t_teachar values('1','aaaa'); --在t_teachar表里插入语句
  53. Query OK, 1 row affected (0.00 sec)
  54. (gcdb@localhost) 15:14:44 [mytest]> select * from t_user; --在t_user表里面可以看
  55. +-----+---------+
  56. | uid | upasswd |
  57. +-----+---------+
  58. | 1 | aaaa |
  59. +-----+---------+
  60. 1 row in set (0.00 sec)
  61. (gcdb@localhost) 15:14:56 [mytest]>

3.5、Delete 类型触发器

  1. (gcdb@localhost) 16:01:00 [mytest]> drop table t_user;
  2. Query OK, 0 rows affected (0.01 sec)
  3. (gcdb@localhost) 16:04:02 [mytest]> create table t_user(uid varchar(30) primary key,upasswd varchar(32) not null,score int,time timestamp(6) not null default current_timestamp(6) on updatecurrent_timestamp(6));
  4. Query OK, 0 rows affected (0.01 sec)
  5. (gcdb@localhost) 16:04:20 [mytest]> drop table t_teachar;
  6. Query OK, 0 rows affected (0.03 sec)
  7. (gcdb@localhost) 16:04:40 [mytest]> create table t_teachar(tid varchar(30) primary key,tpasswd varchar(32) not null,score int,time timestamp(6) not null default current_timestamp(6) on update current_timestamp(6));
  8. Query OK, 0 rows affected (0.24 sec)
  9. (gcdb@localhost) 16:28:37 [mytest]> insert into t_teachar values('1','aaaa',77,null);
  10. Query OK, 1 row affected (0.00 sec)
  11. (gcdb@localhost) 16:30:29 [mytest]> insert into t_teachar values('2','bbbb',88,null);
  12. Query OK, 1 row affected (0.00 sec)
  13. (gcdb@localhost) 16:30:29 [mytest]> insert into t_teachar values('3','cccc',99,null);
  14. Query OK, 1 row affected (0.00 sec)
  15. (gcdb@localhost) 16:30:46 [mytest]> insert into t_user values('1','aaaa',77,null);
  16. Query OK, 1 row affected (0.00 sec)
  17. (gcdb@localhost) 16:31:36 [mytest]> insert into t_user values('2','bbbb',88,null);
  18. Query OK, 1 row affected (0.00 sec)
  19. (gcdb@localhost) 16:31:36 [mytest]> insert into t_user values('3','cccc',99,null);
  20. Query OK, 1 row affected (0.00 sec)
  21. (gcdb@localhost) 16:34:35 [mytest]> DELIMITER //
  22. (gcdb@localhost) 16:35:23 [mytest]> CREATE TRIGGER trg_delete_teachar
  23. -> AFTER DELETE ON t_teachar
  24. -> FOR EACH ROW
  25. -> BEGIN
  26. -> DELETE FROM t_user WHERE uid = OLD.Tid;
  27. -> END
  28. -> //
  29. Query OK, 0 rows affected (0.00 sec)
  30. (gcdb@localhost) 16:35:23 [mytest]> DELIMITER ;
  31. (gcdb@localhost) 16:35:24 [mytest]> select * from t_teachar;
  32. +-----+---------+-------+----------------------------+
  33. | tid | tpasswd | score | time |
  34. +-----+---------+-------+----------------------------+
  35. | 1 | aaaa | 77 | 2017-12-09 16:30:29.668864 |
  36. | 2 | bbbb | 88 | 2017-12-09 16:30:29.669887 |
  37. | 3 | cccc | 99 | 2017-12-09 16:30:30.885201 |
  38. +-----+---------+-------+----------------------------+
  39. 3 rows in set (0.00 sec)
  40. (gcdb@localhost) 16:35:35 [mytest]> select * from t_user;
  41. +-----+---------+-------+----------------------------+
  42. | uid | upasswd | score | time |
  43. +-----+---------+-------+----------------------------+
  44. | 1 | aaaa | 77 | 2017-12-09 16:31:36.076287 |
  45. | 2 | bbbb | 88 | 2017-12-09 16:31:36.076968 |
  46. | 3 | cccc | 99 | 2017-12-09 16:31:37.350546 |
  47. +-----+---------+-------+----------------------------+
  48. 3 rows in set (0.00 sec)
  49. (gcdb@localhost) 16:35:40 [mytest]> delete from t_teachar where tid=1;
  50. Query OK, 1 row affected (0.00 sec)
  51. (gcdb@localhost) 16:35:49 [mytest]> select * from t_user;
  52. +-----+---------+-------+----------------------------+
  53. | uid | upasswd | score | time |
  54. +-----+---------+-------+----------------------------+
  55. | 2 | bbbb | 88 | 2017-12-09 16:31:36.076968 |
  56. | 3 | cccc | 99 | 2017-12-09 16:31:37.350546 |
  57. +-----+---------+-------+----------------------------+
  58. 2 rows in set (0.00 sec)
  59. (gcdb@localhost) 16:35:51 [mytest]> select * from t_teachar;
  60. +-----+---------+-------+----------------------------+
  61. | tid | tpasswd | score | time |
  62. +-----+---------+-------+----------------------------+
  63. | 2 | bbbb | 88 | 2017-12-09 16:30:29.669887 |
  64. | 3 | cccc | 99 | 2017-12-09 16:30:30.885201 |
  65. +-----+---------+-------+----------------------------+
  66. 2 rows in set (0.00 sec)
  67. (gcdb@localhost) 16:36:05 [mytest]>

3.6、显示和删除触发器

  1. (gcdb@localhost) 16:47:15 [mytest]> show triggers \G;
  2. *************************** 1. row ***************************
  3. Trigger: trg_delete_teachar
  4. Event: DELETE
  5. Table: t_teachar
  6. Statement: BEGIN
  7. DELETE FROM t_user WHERE uid = OLD.Tid;
  8. END
  9. Timing: AFTER
  10. Created: 2017-12-09 16:35:23.60
  11. sql_mode:
  12. Definer: gcdb@%
  13. character_set_client: utf8
  14. collation_connection: utf8_general_ci
  15. Database Collation: utf8_general_ci
  16. 1 row in set (0.00 sec)
  17. ERROR:
  18. No query specified
  19. (gcdb@localhost) 16:47:46 [mytest]> drop trigger trg_delete_teachar;
  20. Query OK, 0 rows affected (0.00 sec)
  21. (gcdb@localhost) 16:48:24 [mytest]> show triggers \G;
  22. Empty set (0.00 sec)
  23. ERROR:
  24. No query specified
  25. (gcdb@localhost) 16:48:28 [mytest]>

3.7、触发器总结

  • 触发器对性能有损耗,应当非常慎重使用;

  • 对于事物表,触发器执行失败则整个语句回滚

  • Row格式主从复制,触发器不会在从库上执行

    • 因为从库复制的肯定是主库已经提交的数据,既然已经提交了说明触发器已经被触发过了,所以从库不会执行。
  • 使用触发器时应防止递归执行;

    1. delimiter //
    2. create trigger trg_test
    3. before update on 'test_trigger'
    4. for each row
    5. begin
    6. update test_trigger set score=20 where name = old.name; -- 又触发了update操作,循环触发了
    7. end;//

3.8、触发器模拟物化视图

  • 物化视图的概念

    • 不是基于基表的虚表
    • 根据基表实际存在的实表
    • 预先计算并保存耗时较多的SQL操作结果(如多表链接(join)或者group by等)
  • 模拟物化视图

  1. (root@localhost) 17:21:28 [mytest]> create table Orders
  2. -> (order_id int unsigned not null auto_increment,
  3. -> product_name varchar(30) not null,
  4. -> price decimal(8,2) not null,
  5. -> amount smallint not null,
  6. -> primary key(order_id));
  7. Query OK, 0 rows affected (0.13 sec) -- 创建Orders
  8. (root@localhost) 17:26:40 [mytest]> insert into Orders values
  9. -> (null, 'cpu', 135.5 ,1),
  10. -> (null, 'memory', 48.2, 3),
  11. -> (null, 'cpu', 125.6, 3),
  12. -> (null, 'cpu', 105.3, 4);
  13. Query OK, 4 rows affected (0.06 sec) -- 插入测试数据
  14. Records: 4 Duplicates: 0 Warnings: 0
  15. (root@localhost) 17:26:42 [mytest]> select * from Orders;
  16. +----------+--------------+--------+--------+
  17. | order_id | product_name | price | amount |
  18. +----------+--------------+--------+--------+
  19. | 1 | cpu | 135.50 | 1 |
  20. | 2 | memory | 48.20 | 3 |
  21. | 3 | cpu | 125.60 | 3 |
  22. | 4 | cpu | 105.30 | 4 |
  23. +----------+--------------+--------+--------+
  24. 4 rows in set (0.00 sec)
  25. -- 建立一个模拟物化视图的表(即用这张表来模拟物化视图)
  26. (root@localhost) 17:28:36 [mytest]> CREATE TABLE Orders_MV(
  27. -> product_name VARCHAR(30) NOT NULL
  28. -> , price_sum DECIMAL(8,2) NOT NULL
  29. -> , amount_sum INT NOT NULL
  30. -> , price_avg FLOAT NOT NULL
  31. -> , orders_cnt INT NOT NULL
  32. -> , UNIQUE INDEX (product_name)
  33. -> );
  34. Query OK, 0 rows affected (0.00 sec)
  35. --创建一个普通视图
  36. (root@localhost) 17:28:36 [mytest]> CREATE VIEW v_orders AS SELECT
  37. -> product_name,sum(price),sum(amount),avg(price),count(1)
  38. -> FROM Orders
  39. -> GROUP BY product_name;
  40. Query OK, 0 rows affected (0.04 sec)
  41. -- 通过Orders表的数据,将测试数据初始化到Orders_MV表中
  42. (root@localhost) 17:31:22 [mytest]> insert into Orders_MV
  43. -> select product_name, sum(price),sum(amount), avg(price), count(*)
  44. -> from Orders
  45. -> group by product_name;
  46. Query OK, 2 rows affected (0.00 sec)
  47. Records: 2 Duplicates: 0 Warnings: 0
  48. (root@localhost) 17:32:37 [mytest]> select * from Orders_MV;
  49. +--------------+-----------+------------+-----------+------------+
  50. | product_name | price_sum | amount_sum | price_avg | orders_cnt |
  51. +--------------+-----------+------------+-----------+------------+
  52. | cpu | 366.40 | 8 | 122.133 | 3 |
  53. | memory | 48.20 | 3 | 48.2 | 1 |
  54. +--------------+-----------+------------+-----------+------------+
  55. 2 rows in set (0.00 sec)
  56. -- MySQL workbench中输入,比较方便
  57. delimiter //
  58. CREATE TRIGGER tgr_Orders_insert -- 创建触发器为tgr_Orders_insert
  59. AFTER INSERT ON Orders -- 触发器是INSERT类型的,且作用于Orders
  60. FOR EACH ROW
  61. BEGIN
  62. SET @old_price_sum := 0; -- 设置临时存放Orders_MV表(模拟物化视图)的字段的变量
  63. SET @old_amount_sum := 0;
  64. SET @old_price_avg := 0;
  65. SET @old_orders_cnt := 0;
  66. SELECT -- select ... into ... 在更新Orders_MV之前,将Orders_MV中对应某个产品的信息写入临时变量
  67. IFNULL(price_sum, 0),
  68. IFNULL(amount_sum, 0),
  69. IFNULL(price_avg, 0),
  70. IFNULL(orders_cnt, 0)
  71. FROM
  72. Orders_MV
  73. WHERE
  74. product_name = NEW.product_name INTO @old_price_sum , @old_amount_sum , @old_price_avg , @old_orders_cnt;
  75. SET @new_price_sum = @old_price_sum + NEW.price; -- 累加新的值
  76. SET @new_amount_sum = @old_amount_sum + NEW.amount;
  77. SET @new_orders_cnt = @old_orders_cnt + 1;
  78. SET @new_price_avg = @new_price_sum / @new_orders_cnt ;
  79. REPLACE INTO Orders_MV
  80. VALUES(NEW.product_name, @new_price_sum,
  81. @new_amount_sum, @new_price_avg, @new_orders_cnt );
  82. -- REPLACE 将对应的物品(唯一索引)的字段值替换new_xxx的值
  83. END;//
  84. delimiter ;
  85. (root@localhost) 17:37:35 [mytest]> insert into Orders values (null, 'ssd', 299, 3);
  86. Query OK, 1 row affected (0.01 sec)
  87. (root@localhost) 17:37:44 [mytest]> insert into Orders values (null, 'memory', 47.9, 5);
  88. Query OK, 1 row affected (0.00 sec)
  89. (root@localhost) 17:38:07 [mytest]> select * from Orders_MV;
  90. +--------------+-----------+------------+-----------+------------+
  91. | product_name | price_sum | amount_sum | price_avg | orders_cnt |
  92. +--------------+-----------+------------+-----------+------------+
  93. | cpu | 366.40 | 8 | 122.133 | 3 |
  94. | memory | 96.10 | 8 | 48.05 | 2 | -- 数量自动增加了1,价格也发生了变化
  95. | ssd | 299.00 | 3 | 299 | 1 | -- 新增加的ssd产品
  96. +--------------+-----------+------------+-----------+------------+
  97. 3 rows in set (0.00 sec)
  98. (root@localhost) 17:38:09 [mytest]> select * from v_orders;
  99. +--------------+------------+-------------+------------+----------+
  100. | product_name | sum(price) | sum(amount) | avg(price) | count(1) |
  101. +--------------+------------+-------------+------------+----------+
  102. | cpu | 366.40 | 8 | 122.133333 | 3 |
  103. | memory | 96.10 | 8 | 48.050000 | 2 |
  104. | ssd | 299.00 | 3 | 299.000000 | 1 |
  105. +--------------+------------+-------------+------------+----------+
  106. 3 rows in set (0.00 sec)
  107. --
  108. -- IFNULL MySQL内建函数的演示
  109. --
  110. (root@localhost) 08:47:45 [mytest]> select @test;
  111. +-------+
  112. | @test |
  113. +-------+
  114. | NULL | -- 当前会话中没有test变量
  115. +-------+
  116. 1 row in set (0.00 sec)
  117. (root@localhost) 08:47:46 [mytest]> select ifnull(@test, 100); -- 如果testNULL,则ifnull返回100
  118. +--------------------+
  119. | ifnull(@test, 100) |
  120. +--------------------+
  121. | 100 | -- ifnull函数return的值是100
  122. +--------------------+
  123. 1 row in set (0.00 sec)
  124. (root@localhost) 08:48:30 [mytest]> select @test;
  125. +-------+
  126. | @test |
  127. +-------+
  128. | NULL | -- 但是test还是NULL
  129. +-------+
  130. 1 row in set (0.00 sec)
  131. (root@localhost) 08:48:40 [mytest]> set @test:=200; -- test变量赋值为200
  132. Query OK, 0 rows affected (0.00 sec)
  133. (root@localhost) 08:48:49 [mytest]> select ifnull(@test, 100); -- 再次ifnull判断,此时test不为null,则返回test变量的值
  134. +--------------------+
  135. | ifnull(@test, 100) |
  136. +--------------------+
  137. | 200 | -- test不为null。返回test的值200
  138. +--------------------+
  139. 1 row in set (0.00 sec)
  140. --
  141. -- select into 用法
  142. --
  143. (root@localhost) 08:51:19 [mytest]> select @id_1;
  144. +-------+
  145. | @id_1 |
  146. +-------+
  147. | NULL | -- 当前变量id_01null
  148. +-------+
  149. 1 row in set (0.00 sec)
  150. (root@localhost) 08:52:10 [mytest]> select @score_1;
  151. +----------+
  152. | @score_1 |
  153. +----------+
  154. | NULL | -- 当前变量score_01null
  155. +----------+
  156. 1 row in set (0.00 sec)
  157. (root@localhost) 08:53:56 [mytest]> select * from t_rank;
  158. +------+-------+------+
  159. | id | score | c |
  160. +------+-------+------+
  161. | 1 | 10 | 0 |
  162. | 2 | 20 | 0 |
  163. | 3 | 30 | 0 |
  164. | 4 | 30 | 0 |
  165. | 5 | 40 | 0 |
  166. | 6 | 40 | 0 |
  167. +------+-------+------+
  168. 6 rows in set (0.00 sec)
  169. (root@localhost) 08:55:04 [mytest]> select id,score from t_rank where id =1 into @id_01,@score_01;-- 选择id=1的记录,将对应的idscore赋值给变量 id_01 score_01
  170. Query OK, 1 row affected (0.00 sec)
  171. (root@localhost) 08:55:27 [mytest]> select @id_01;
  172. +-------+
  173. | @id_1 |
  174. +-------+
  175. | 1 |
  176. +-------+
  177. 1 row in set (0.00 sec)
  178. (root@localhost) 08:55:41 [mytest]> select @score_01;
  179. +-----------+
  180. | @score_01 |
  181. +-----------+
  182. | 10 |
  183. +-----------+
  184. 1 row in set (0.00 sec)
  185. -- 触发器对性能会有影响,相当于在一个事物中插入了其他的事物

013:Rank、视图、触发器、MySQL内建函数的更多相关文章

  1. Mysql 视图,触发器,存储过程,函数,事务

    视图 视图虚拟表,是一个我们真实查询结果表,我们希望将某次查询出来的结果作为单独的一个表,就叫视图,无法对图字段内容进行增删改. --格式: CREATE VIEW 视图名字 AS 操作; --比如: ...

  2. mysql 视图 触发器 事物 存储过程 函数 流程控制

    1.视图 *** 视图是有一条sql语句的查询结果构成的虚拟表 其不是物理存在的 使用方式与普通表相同 视图的作用1.简化sql语句的编写 2.限制可以查看的数据 可以使用权限来完成 权限某一个库 的 ...

  3. MySQL 视图触发器事务存储过程函数

    事务  致命三问 什么是事务:开启了一个包含多条SQL语句的事务,这些SQL语句要么都执行成功,要么有别想成功:例如A向B转账,二人账户并不属于一家银行,在转账过程中由于网络问题,导致A显示转账 成功 ...

  4. MySQL拓展 视图,触发器,事务,存储过程,内置函数,流程控制,索引,慢查询优化,数据库三大设计范式

    视图: 1.什么是视图 视图就是通过查询得到一张虚拟表,然后保存下来,下次直接使用即可 2.为什么要用视图 如果要频繁使用一张虚拟表,可以不用重复查询 3.如何使用视图 create view tea ...

  5. MySQL 视图 触发器 事务 存储过程 函数 流程控制 索引与慢查询优化

    视图 1.什么是视图? 视图就是通过查询得到的一张虚拟表,然后保存下来,下次可直接使用 2.为什么要使用视图? 如果要频繁使用一张虚拟表,可以不用重复查询 3.如何使用视图? create view ...

  6. mysql 视图 触发器 存储过程 函数事务 索引

    mysql 视图 触发器 存储过程 函数事务 索引 视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集,并可以将其当 ...

  7. MySQL 查询 存储过程 视图 触发器 函数 索引 建表语句 数据库版本 当前登录用户 当前数据库名称

    MySQL 查询 存储过程 视图 触发器 函数 索引 建表语句 数据库版本 当前登录用户 当前数据库名称   INFORMATION_SCHEMA.TABLES INFORMATION_SCHEMA. ...

  8. day40 mycql 视图,触发器,存储过程,函数

    视图,触发器,存储过程,自定义函数 -- 回顾 1.mysql 约束 1.非空 not null 2. 主键约束 primary key 3. 唯一约束 unique 4. 外键约束 foreign ...

  9. python 全栈开发,Day64(视图,触发器,函数,存储过程,事务)

    昨日内容回顾 pymysql:属于python的一个模块 pip3 install pymysql conn = pymysql.connect(...,charset = 'uft8') 创建游标 ...

随机推荐

  1. 微信测试帐号如何设置URL和Token,以及相关验证的原理

    首先说明,本帮助文档是利用javaweb的Servlet来进行“接口配置信息配置信息”认证的. 在学习微信公众号开发的时候,读到填写服务器配置的帮助部分,总是不能理解为啥按照他的步骤做总是设置失败(吐 ...

  2. FFmpeg再学习 -- 硬件加速编解码

    为了搞硬件加速编解码,用了一周时间来看 CUDA,接下来开始加以总结. 一.什么是 CUDA (1)首先需要了解一下,什么是 CUDA. 参看:百度百科 -- CUDA 参看:CUDA基础介绍 参看: ...

  3. PHP常见带有下划线的常量

    1.__PHP_Incomplete_Class <?php echo __PHP_Incomplete_Class::class; ?> __PHP_Incomplete_Class 2 ...

  4. oracle对三个列求sum

    oracle数据库对test_table表的三个列count1,count2,count3求sum的两种sql,做个记录 第一种 select sum (case when count1 is not ...

  5. fiddler与Charles的区别

    一.Fiddle2(v2.4.2.6,windows) fiddler除了常规的替换http请求.模拟慢网速外,还有一些日常开发里能用到的特殊功能. 1. http代理服务器 fiddler启动的时候 ...

  6. UNIX环境高级编程 标准IO库

    标准I/O库处理很多细节,使得便于用户使用. 流和 FILE 对象 对于标准I/O库,操作是围绕 流(stream)进行的.当用标准I/O打开或创建一个文件时,我们已使一个流与一个文件相关联. 对于A ...

  7. CodeForces - 321E:Ciel and Gondolas (四边形不等式优化DP)

    题意:N个人排成一行,分成K组,要求每组的不和谐值之和最小. 思路:开始以为是斜率优化DP,但是每个区间的值其实已经知道了,即是没有和下标有关的未知数了,所以没必要用斜率. 四边形优化. dp[i][ ...

  8. angularJS 全选反选批量删除

    <th> <label for="flag"> <span ng-hide="master">全选</span> ...

  9. php excel 读取日期问题

    在 php excel 读取 xls 格式的文件时,xls 上面显示的是正常的日期格式 但是读取出来的话,就会是一个万位整形数据,这显然不是我们想要的日期 读取出来的结果: 41807 $t = 41 ...

  10. SQL中char、varchar、nchar、nvarchar 详解

    char     char是定长的,也就是当你输入的字符小于你指定的数目时,char(8),你输入的字符小于8时,它会再后面补空值.当你输入的字符大于指定的数时,它会截取超出的字符. varchar[ ...