MariaDB 视图与触发器

数据库中的视图是一个虚拟表,同真实的表一样,视图包含一系列带有名称的行和列数据,行和列数据来自由定义视图查询所引用的表,并且在引用视图时动态生成,视图是从一个或者多个表中导出的,视图的行为与表非常相似,但视图是一个虚拟表.在视图中用户可以使用SELECT语句查询数据,以及使用INSERT、UPDATE和DELETE修改记录,视图可以使用户操作方便,而且可以保障数据库系统的安全.

♥ 文章声明 ♥
该系列文章部分文字描述,参考于以下文献,化繁为简.
《MySQL5.7从入门到精通》 - 刘增杰

触发器和存储过程一样,都是嵌入到MySQL的一段程序,触发器是由事件来触发某个操作,这些事件包括INSERT、UPDATAE和DELETE语句.如果定义了触发程序,当数据库执行这些语句的时候就会激发触发器执行相应的操作,触发程序是与表有关的命名数据库对象,当表上出现特定事件时,将激活该对象.

MariaDB 视图

视图的含义:

视图是一张虚拟表,是从数据库中一个或多个表中导出来的表,视图还可以从已经存在的视图基础上定义,视图一经定义便存储在数据库中,与其相对应的数据并没有像表那样在数据库中再存储一份,通过视图看到的数据只是存放在基本表中的数据.对视图的操作与对表的操作一样,可以对其进行查询、修改和删除.当对通过视图看到的数据进行修改时,相应的基本表的数据也要发生变化.同时,若基本表的数据发生变化,则这种变化也可以自动地反映到视图中.

如下小例子:下面有个student表info表,现在我分别只想去除其中的ID号,姓名,班级,此时我们就需要用一个视图来解决,取出指定的字段.

create table student (s_id int,name varchar(40));
create table info (s_id int,glass varchar(40),addr varchar(90));

视图提供了一个很好的解决方法,创建视图的信息来自表的部分信息,只取出需要的信息,这样既能满足需求也不破坏原有的表结构.

视图的作用:

视图不仅可以简化用户对于数据的理解,也可以简化他们的操作,那些被经常使用的查询可以定义为视图,从而使得用户不必为以后的操作每次指定全部条件.

通过视图用户只能查询和修改他们所能见到的数据,数据库中的其他数据则既看不见也取不到,数据库授权命令可以使每个用户对数据库的检索限制到特定的数据库对象上,但不能授权到数据库特定行和特定的列上.通过视图,用户可以被限制在数据的不同子集上.

◆创建视图◆

在单表上创建视图:

1.首先创建一个基本表table1并插入测试数据.

MariaDB [lyshark]> create table table1(quantity INT,price INT);
Query OK, 0 rows affected (0.02 sec)

MariaDB [lyshark]> insert into table1 values(1,10);
Query OK, 1 row affected (0.00 sec)

MariaDB [lyshark]> insert into table1 values(2,30);
Query OK, 1 row affected (0.00 sec)

MariaDB [lyshark]> insert into table1 values(3,50);
Query OK, 1 row affected (0.00 sec)

2.创建视图,在table1表上创建一个view_tab1视图,其中代码有三个字段x,y,totle,SQL语句如下:

MariaDB [lyshark]> create view view_tab1(x,y,totle)
    -> AS SELECT quantity,price,quantity * price
    -> FROM table1;
Query OK, 0 rows affected (0.00 sec)

3.紧接着我们使用视图来查询创建的新表格.

MariaDB [lyshark]> select * from view_tab1;
+------+------+-------+
| x    | y    | totle |
+------+------+-------+
|    1 |   10 |    10 |
|    2 |   30 |    60 |
|    3 |   50 |   150 |
+------+------+-------+
3 rows in set (0.00 sec)

在多张表上创建视图:

1.首先创建两个测试表并插入一些数据,这里我们就创建要给studentinfo两个表,SQL语句如下:

MariaDB [lyshark]> create table student
    -> (
    -> s_id INT,
    -> name VARCHAR(40)
    -> );
Query OK, 0 rows affected (0.01 sec)

MariaDB [lyshark]> create table info
    -> (
    -> s_id INT,
    -> glass VARCHAR(40),
    -> addr VARCHAR(90)
    -> );
Query OK, 0 rows affected (0.00 sec)

MariaDB [lyshark]> insert into student values(1,'wang'),(2,'rui');
Query OK, 2 rows affected (0.33 sec)
Records: 2  Duplicates: 0  Warnings: 0

MariaDB [lyshark]> insert into info values(1,'wuban','henan'),(2,'sanban','hebei'),(3,'yiban','s
handong');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

2.接下来我们创建一个视图stu_glass,其中有三个参数(id,name,glass),分别对应两个表的不同字段,并且通过where条件限定ID号相同的关联在一起.

MariaDB [lyshark]> create view stu_glass(id,name,glass)
    -> AS select student.s_id,student.name,info.glass
    -> FROM student,info where student.s_id = info.s_id;

Query OK, 0 rows affected (0.00 sec)

MariaDB [lyshark]> select * from stu_glass;
+------+------+--------+
| id   | name | glass  |
+------+------+--------+
|    1 | wang | wuban  |
|    2 | rui  | sanban |
+------+------+--------+
2 rows in set (0.01 sec)

以上例子就解决了刚开始那个问题,通过这个视图可以很好地保护基本表中的数据.

◆查看视图◆

使用desc查看视图表结构:

MariaDB [lyshark]> desc stu_glass;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | YES  |     | NULL    |       |
| name  | varchar(40) | YES  |     | NULL    |       |
| glass | varchar(40) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.01 sec)

使用show table status查看视图:

MariaDB [lyshark]> show table status like 'stu_glass' \G
*************************** 1. row ***************************
           Name: stu_glass
         Engine: NULL
        Version: NULL
     Row_format: NULL
           Rows: NULL
 Avg_row_length: NULL
    Data_length: NULL
Max_data_length: NULL
   Index_length: NULL
      Data_free: NULL
 Auto_increment: NULL
    Create_time: NULL
    Update_time: NULL
     Check_time: NULL
      Collation: NULL
       Checksum: NULL
 Create_options: NULL
        Comment: VIEW
1 row in set (0.00 sec)

使用show create view查看视图详细信息:

MariaDB [lyshark]> show create view stu_glass \G
*************************** 1. row ***************************
                View: stu_glass
         Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `stu_glass` AS select `student`.`s_id` AS `id`,`student`.`name` AS `name`,`info`.`glass` AS `glass` from (`student` join `info`) where (`student`.`s_id` = `info`.`s_id`)
character_set_client: utf8
collation_connection: utf8_general_ci
1 row in set (0.00 sec)

MariaDB [lyshark]>

在views表中查看视图详细信息:

MariaDB [lyshark]> select * from information_schema.views;   #查视图
MariaDB [lyshark]> select * from information_schema.tables;  #查表
+---------------+--------------+------------+
| TABLE_CATALOG | TABLE_SCHEMA | TABLE_NAME |
+---------------+--------------+------------+
| def           | lyshark      | stu_glass  |
| def           | lyshark      | view_tab1  |
| def           | lyshark      | view_tab2  |
+---------------+--------------+------------+
3 rows in set (0.01 sec)

### ◆更新与删除视图◆

alter语句修改视图:

使用alter语句,修改视图view_tab1,SQL语句如下:

MariaDB [lyshark]> desc view_tab1;
+-------+------------+------+-----+---------+-------+
| Field | Type       | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| x     | int(11)    | YES  |     | NULL    |       |
| y     | int(11)    | YES  |     | NULL    |       |
| totle | bigint(21) | YES  |     | NULL    |       |
+-------+------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

MariaDB [lyshark]> alter view view_tab1
    -> AS select quantity from table1;
Query OK, 0 rows affected (0.00 sec)

MariaDB [lyshark]> desc view_tab1;
+----------+---------+------+-----+---------+-------+
| Field    | Type    | Null | Key | Default | Extra |
+----------+---------+------+-----+---------+-------+
| quantity | int(11) | YES  |     | NULL    |       |
+----------+---------+------+-----+---------+-------+
1 row in set (0.00 sec)

update更新视图:

MariaDB [lyshark]> select * from stu_glass;
+------+------+--------+
| id   | name | glass  |
+------+------+--------+
|    1 | wang | wuban  |
|    2 | rui  | sanban |
+------+------+--------+
2 rows in set (0.00 sec)

MariaDB [lyshark]> update stu_glass SET id=3 where name="rui";
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1  Changed: 0  Warnings: 0

MariaDB [lyshark]> select * from stu_glass;
+------+------+-------+
| id   | name | glass |
+------+------+-------+
|    1 | wang | wuban |
|    3 | rui  | yiban |
+------+------+-------+
2 rows in set (0.00 sec)

删除视图中指定字段:注意,联合字段的视图无法删除.

MariaDB [lyshark]> select * from view_tab1;
+------+------+-------+
| x    | y    | totle |
+------+------+-------+
|    1 |   10 |    10 |
|    2 |   30 |    60 |
|    3 |   50 |   150 |
+------+------+-------+
3 rows in set (0.00 sec)

MariaDB [lyshark]> delete from view_tab1 where x=1;
Query OK, 1 row affected (0.00 sec)

MariaDB [lyshark]> select * from view_tab1;
+------+------+-------+
| x    | y    | totle |
+------+------+-------+
|    2 |   30 |    60 |
|    3 |   50 |   150 |
+------+------+-------+
2 rows in set (0.00 sec)

删除一个视图:

1.查询一下,我们比如要删除view_tab1view_tab2两个视图.

MariaDB [lyshark]> select * from information_schema.views;   #查视图
+---------------+--------------+------------+
| TABLE_CATALOG | TABLE_SCHEMA | TABLE_NAME |
+---------------+--------------+------------+
| def           | lyshark      | stu_glass  |
| def           | lyshark      | view_tab1  |
| def           | lyshark      | view_tab2  |
+---------------+--------------+------------+
3 rows in set (0.01 sec)

2.通过drop view语句直接删除掉.

MariaDB [lyshark]> drop view if exists view_tab1;
Query OK, 0 rows affected (0.00 sec)

MariaDB [lyshark]> drop view if exists view_tab2;
Query OK, 0 rows affected (0.00 sec)

3.再次查询,发现没有了,删除成功.

MariaDB [lyshark]> select * from information_schema.views;
+---------------+--------------+------------+
| TABLE_CATALOG | TABLE_SCHEMA | TABLE_NAME |
+---------------+--------------+------------+
| def           | lyshark      | stu_glass  |
+---------------+--------------+------------+
1 row in set (0.00 sec)

MariaDB触发器

触发器(Trigger)是个特殊的存储过程,不同的是,执行存储过程要使用CALL语句来调用,而触发器的执行不需要使用CALL语句来调用,也不需要手工启动,只要当一个预定义的事件发生的时候,就会被MySQL自动调用,触发器可以查询其他表,而且可以包含复杂的SQL语句,它们主要用于满足复杂的业务规则或要求.

一般来说创建触发器的基本语法如下:

create trigger trigger_name trigger_time trigger_event
ON table_name FOR EACH ROW trigger_stmt

#----------------------------------------------------------------
#[参数解释]

trigger_name              #触发器名称
trigger_time              #标识触发时机(befor/after)
trigger_event             #标识触发事件
table_name                #建立触发器表名,即在那张表上建立触发器
trigger_stmt              #触发器执行语句

而创建多个执行语句的触发器的语法如下:

create trigger trigger_name trigger_time trigger_event
ON table_name FOR EACH ROW
BEGIN
执行语句块...
END

◆创建触发器◆

创建只有一条执行语句的触发器:

1.首先创建一个account表,表中有两个字段,分别是acct_num字段(INT),amount字段(float).

MariaDB [lyshark]> create table account(acct_num INT,amount DECIMAL(10,2));
Query OK, 0 rows affected (0.01 sec)

MariaDB [lyshark]> desc account;
+----------+---------------+------+-----+---------+-------+
| Field    | Type          | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| acct_num | int(11)       | YES  |     | NULL    |       |
| amount   | decimal(10,2) | YES  |     | NULL    |       |
+----------+---------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

2.创建一个名为ins_sum的触发器,触发条件是向数据表account插入数据之前,对新插入的amount字段值进行求和计算.

MariaDB [lyshark]> create trigger ins_sum BEFORE INSERT ON account
    -> FOR EACH ROW SET @sum=@sum+NEW.amount;
Query OK, 0 rows affected (0.00 sec)

MariaDB [lyshark]> set @sum=0;
Query OK, 0 rows affected (0.00 sec)

MariaDB [lyshark]> insert into account values(1,1.00),(2,2.00);
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

MariaDB [lyshark]> select @sum;
+------+
| @sum |
+------+
| 3.00 |
+------+
1 row in set (0.00 sec)

以上例子,首先创建一个account表,再向表account插入数据之前,计算所有新插入的account表的amount值之和,触发器的名称为ins_sum,条件是在向表中插入数据之前触发.

创建具有多条执行语句的触发器:

1.首相创建4个测试表格,并写入以下测试字段.

MariaDB [lyshark]> create table test1(a1 INT);
Query OK, 0 rows affected (0.00 sec)

MariaDB [lyshark]> create table test2(a2 INT);
Query OK, 0 rows affected (0.00 sec)

MariaDB [lyshark]> create table test3(a3 INT NOT NULL AUTO_INCREMENT primary key);
Query OK, 0 rows affected (0.00 sec)

MariaDB [lyshark]> create table test4(
    -> a4 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    -> b4 INT DEFAULT 0
    -> );
Query OK, 0 rows affected (0.07 sec)

2.创建一个包含多个执行语句的触发器,当test1有数据插入时,执行触发语句,代码如下:

MariaDB [lyshark]> DELIMITER //
MariaDB [lyshark]> create trigger testref BEFORE INSERT ON test1
    -> FOR EACH ROW
    -> BEGIN
    -> insert into test2 set a2=NEW.a1;
    -> delete from test3 where a3=NEW.a1;
    -> update test4 set b4=b4+1 where a4=NEW.a1;
    -> END
    -> //
MariaDB [lyshark]> DELIMITER ;;

以上代码创建了一个名为testref的触发器,这个触发器的触发条件是在向表test1插入数据前执行触发器的语句,具体执行代码如下:

MariaDB [lyshark]> insert into test1 values (1),(3),(1),(7),(1),(4);
Query OK, 6 rows affected (0.01 sec)
Records: 6  Duplicates: 0  Warnings: 0

当test1表格插入数据后,其他表格也会出现相同的数据,这就是触发器所做的贡献.

MariaDB [lyshark]> select * from test1;
+------+
| a1   |
+------+
|    1 |
|    3 |
|    1 |
|    7 |
|    1 |
|    4 |
+------+
6 rows in set (0.00 sec)

MariaDB [lyshark]> select * from test2;
+------+
| a2   |
+------+
|    1 |
|    3 |
|    1 |
|    7 |
|    1 |
|    4 |
+------+
6 rows in set (0.00 sec)

关于触发器的另一个小实验:

1.先来创建一个数据表.

MariaDB [lyshark]> create table myevent(id int,name char(20));
Query OK, 0 rows affected (0.01 sec)

MariaDB [lyshark]> desc myevent;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| id    | int(11)  | YES  |     | NULL    |       |
| name  | char(20) | YES  |     | NULL    |       |
+-------+----------+------+-----+---------+-------+
2 rows in set (0.00 sec)

2.创建一个trig_insert的触发器,在向表account插入数据之后会向表myevent插入一组数据,代码如下:

MariaDB [lyshark]> create trigger trig_insert AFTER INSERT ON account
    -> FOR EACH ROW INSERT INTO myevent values(2,'after insert');
Query OK, 0 rows affected (0.00 sec)

3.此时我们执行插入语句,向account表插入数据,查询myevent表,发现自动添加上了,说明触发器生效了.

MariaDB [lyshark]> insert into account values(1,1.00),(2,2.00);
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0


MariaDB [lyshark]> select * from myevent;
+------+--------------+
| id   | name         |
+------+--------------+
|    2 | after insert |
|    2 | after insert |
+------+--------------+
2 rows in set (0.00 sec)

◆查看与删除触发器◆

show triggers 查看所有触发器:

MariaDB [lyshark]> show triggers \G;
*************************** 1. row ***************************
             Trigger: ins_sum
               Event: INSERT
               Table: account
           Statement: SET @sum=@sum+NEW.amount
              Timing: BEFORE
             Created: NULL
            sql_mode:
             Definer: root@localhost
character_set_client: utf8
collation_connection: utf8_general_ci
  Database Collation: latin1_swedish_ci
*************************** 2. row ***************************
             Trigger: trig_insert
               Event: INSERT
               Table: account
           Statement: INSERT INTO myevent values(2,'after insert')
              Timing: AFTER
             Created: NULL
            sql_mode:
             Definer: root@localhost
character_set_client: utf8
collation_connection: utf8_general_ci
  Database Collation: latin1_swedish_ci

在triggers表中查看触发器:

MariaDB [lyshark]> select * from information_schema.triggers \G;

*************************** 1. row ***************************
           TRIGGER_CATALOG: def
            TRIGGER_SCHEMA: lyshark
              TRIGGER_NAME: ins_sum
        EVENT_MANIPULATION: INSERT
      EVENT_OBJECT_CATALOG: def
       EVENT_OBJECT_SCHEMA: lyshark
        EVENT_OBJECT_TABLE: account
              ACTION_ORDER: 0
          ACTION_CONDITION: NULL
          ACTION_STATEMENT: SET @sum=@sum+NEW.amount
        ACTION_ORIENTATION: ROW
             ACTION_TIMING: BEFORE
ACTION_REFERENCE_OLD_TABLE: NULL
ACTION_REFERENCE_NEW_TABLE: NULL
  ACTION_REFERENCE_OLD_ROW: OLD
  ACTION_REFERENCE_NEW_ROW: NEW
                   CREATED: NULL
                  SQL_MODE:
                   DEFINER: root@localhost
      CHARACTER_SET_CLIENT: utf8
      COLLATION_CONNECTION: utf8_general_ci
        DATABASE_COLLATION: latin1_swedish_ci

删除触发器: 删除lyshark数据库中的,ins触发器,SQL如下:

1.先查询一下触发器的名称,SQL语句如下:

MariaDB [lyshark]> select TRIGGER_SCHEMA,TRIGGER_NAME from information_schema.triggers;
+----------------+--------------+
| TRIGGER_SCHEMA | TRIGGER_NAME |
+----------------+--------------+
| lyshark        | ins_sum      |
| lyshark        | trig_insert  |
| lyshark        | testref      |
+----------------+--------------+
3 rows in set (0.00 sec)

2.一条命令删除.

MariaDB [lyshark]> drop trigger lyshark.ins_sum;
Query OK, 0 rows affected (0.00 sec)
posted @ 2018-12-29 20:46  lyshark  阅读(543)  评论(0编辑  收藏  举报