MYSQL——視圖,觸發器,存儲過程,流程控制

1、視圖

視圖是一個虛擬表(非真實存在),其本質是【根據SQL語句獲取動態的數據集,併爲其命名】,用戶使用時只需使用【名稱】便可獲取結果集,能夠將該結果集當作表來使用;mysql

使用視圖咱們能夠把查詢過程當中的臨時表摘出來,用視圖去實現,這樣之後再想操做該臨時表的數據時就無需重寫複雜的sql了,直接去視圖中查找便可,但視圖有明顯地效率問題,而且視圖是存放在數據庫中的,若是咱們程序中使用的sql過度依賴數據庫中的視圖,即強耦合,那就意味着擴展sql極爲不便,所以並不推薦使用。程序員

ps: 視圖在庫裏只有表結構文件沒有表數據sql

  咱們不該該修改視圖中的記錄,並且在涉及多個表的狀況下是根本沒法修改視圖中的記錄的數據庫

# =============================建立視圖

select * from emp inner join dep on emp.dep_id = dep.id;


create view emp2dep as select emp.*,dep.name as dep_name from emp inner join dep on emp.dep_id = dep.id;


mysql> update emp2dep set name="EGON" where id=1;
Query OK, 1 row affected (0.05 sec)
Rows matched: 1  Changed: 1  Warnings: 0
mysql> select * from emp2dep;
+----+-----------+--------+------+--------+--------------+
| id | name      | sex    | age  | dep_id | dep_name     |
+----+-----------+--------+------+--------+--------------+
|  1 | EGON      | male   |   18 |    200 | 技術         |
|  2 | alex      | female |   48 |    201 | 人力資源     |
|  3 | wupeiqi   | male   |   38 |    201 | 人力資源     |
|  4 | yuanhao   | female |   28 |    202 | 銷售         |
|  5 | liwenzhou | male   |   18 |    200 | 技術         |
+----+-----------+--------+------+--------+--------------+
5 rows in set (0.00 sec)

mysql>
mysql>
mysql> select * from emp;
+----+------------+--------+------+--------+
| id | name       | sex    | age  | dep_id |
+----+------------+--------+------+--------+
|  1 | EGON       | male   |   18 |    200 |
|  2 | alex       | female |   48 |    201 |
|  3 | wupeiqi    | male   |   38 |    201 |
|  4 | yuanhao    | female |   28 |    202 |
|  5 | liwenzhou  | male   |   18 |    200 |
|  6 | jingliyang | female |   18 |    204 |
|  7 | lili       | female |   48 |   NULL |
+----+------------+--------+------+--------+
7 rows in set (0.00 sec)

mysql>

# =============================修改視圖
alter view emp2dep as 查詢語句;

# =============================刪除視圖
drop view emp2dep;

 

2、觸發器

使用觸發器能夠定製用戶對錶進行【增、刪、改】操做時先後的行爲,注意:沒有查詢網絡

特別的:NEW表示即將插入的數據行,OLD表示即將刪除的數據行ide

  觸發器沒法由用戶直接調用,而知因爲對錶的【增/刪/改】操做被動引起的。oop

# 增=》insert
create trigger tri_before_insert_t1 before insert on t1 for each row
begin
    sql語句;
end

create trigger tri_after_insert_t1 after insert on t1 for each row
begin
    sql語句;
end

# 刪除=》delete
create trigger tri_before_delete_t1 before delete on t1 for each row
begin
    sql語句;
end

create trigger tri_after_delete_t1 after delete on t1 for each row
begin
    sql語句;
end


# 修改=》update

# 例如
insert into tt1 values(1,"egon",'male');


delimiter //
create trigger tri_before_insert_tt1 before insert on tt1 for each row
begin
    insert into tt2 values(NEW.name);
end //

delimiter ;


insert into tt1 values(2,"tom",'female');


# 練習
CREATE TABLE cmd (
    id INT PRIMARY KEY auto_increment,
    USER CHAR (32),
    priv CHAR (10),
    cmd CHAR (64),
    sub_time datetime, #提交時間
    success enum ('yes', 'no') #0表明執行失敗
);

CREATE TABLE errlog (
    id INT PRIMARY KEY auto_increment,
    err_cmd CHAR (64),
    err_time datetime
);

delimiter $$
create trigger tri_after_insert_cmd after insert on cmd for each row
begin
    if NEW.success = 'no' then
        insert into errlog(err_cmd,err_time) values(NEW.cmd,NEW.sub_time);
    end if;
end $$
delimiter ;

insert into cmd(user,priv,cmd,sub_time,success) values
    ('egon','0755','ls -l /etc',NOW(),'yes'),
    ('egon','0755','cat /etc/passwd',NOW(),'no'),
    ('egon','0755','useradd xxx',NOW(),'no'),
    ('egon','0755','ps aux',NOW(),'yes');

drop trigger tri_after_insert_cmd ;

 

3、存儲過程

存儲過程包含了一系列可執行的sql語句,存儲過程存放於MySQL中,經過調用它的名字能夠執行其內部的一堆sqlfetch

使用存儲過程的
優勢:
1. 用於替代程序寫的SQL語句,實現程序與sql解耦
2. 基於網絡傳輸,傳別名的數據量小,而直接傳sql數據量大

缺點:
1. 程序員擴展功能不方便

 

程序與數據庫結合使用的三種方式spa

#方式一:
MySQL:存儲過程
程序:調用存儲過程對象

#方式二:
MySQL:
程序:純SQL語句

#方式三:
MySQL:
程序:類和對象,即ORM(本質仍是純SQL語句)

對於存儲過程,能夠接收參數,其參數有三類:
in        僅用於傳入參數用
out      僅用於返回值用
inout   既能夠傳入又能夠看成返回值

 

# 建立無參存儲過程
delimiter $$
create procedure p1()
begin
    select * from emp;
end $$

delimiter ;

call p1();

# 建立有參存儲過程
delimiter $$
create procedure p2(
    in n int,
    out res int
)
begin
    select * from emp where id > n;
    set res=1;
end $$

delimiter ;



==========================>在mysql裏調用存儲過程
mysql> set @x=1111;
Query OK, 0 rows affected (0.00 sec)

mysql> call p2(3,x);
ERROR 1414 (42000): OUT or INOUT argument 2 for routine db4.p2 is not a variable or NEW pseudo-variable in BEFORE trigger
mysql> call p2(3,@x);
+----+------------+--------+------+--------+
| id | name       | sex    | age  | dep_id |
+----+------------+--------+------+--------+
|  4 | yuanhao    | female |   28 |    202 |
|  5 | liwenzhou  | male   |   18 |    200 |
|  6 | jingliyang | female |   18 |    204 |
|  7 | lili       | female |   48 |   NULL |
+----+------------+--------+------+--------+
4 rows in set (0.00 sec)

Query OK, 0 rows affected (0.01 sec)

mysql> select @x;
+------+
| @x   |
+------+
|    1 |
+------+
1 row in set (0.00 sec)
 
  
 
   
==========================>在pymysql裏調用存儲過程

import
pymysql # pip3 install pymysql conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", password="123", db="db4", charset="utf8mb4") cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.callproc('p2',(3,0)) # @_p2_0=3,@_p2_1=0 ''' set @_p2_0=3 set @_p2_1=0 call p2(@_p2_0,@_p2_1); ''' print(cursor.fetchall()) cursor.execute("select @_p2_1;") print(cursor.fetchall()) cursor.execute("select @_p2_0;") print(cursor.fetchall()) cursor.close() conn.close()

 

 
   
==========================>刪除存儲過程
drop procedure proc_name;
4、流程控制

條件語句

 

#if條件語句

delimiter //
CREATE PROCEDURE proc_if ()
BEGIN
    
    declare i int default 0;
    if i = 1 THEN
        SELECT 1;
    ELSEIF i = 2 THEN
        SELECT 2;
    ELSE
        SELECT 7;
    END IF;

END //
delimiter ;

 

循環語句

#while循環語句

delimiter //
CREATE PROCEDURE proc_while ()
BEGIN

    DECLARE num INT ;
    SET num = 0 ;
    WHILE num < 10 DO
        SELECT
            num ;
        SET num = num + 1 ;
    END WHILE ;

END //
delimiter ;

 

#repeat 循環

delimiter //
CREATE PROCEDURE proc_repeat ()
BEGIN

    DECLARE i INT ;
    SET i = 0 ;
    repeat
        select i;
        set i = i + 1;
        until i >= 5
    end repeat;

END //
delimiter ;

 

#loop循環

BEGIN
    
    declare i int default 0;
    loop_label: loop
        
        set i=i+1;
        if i<8 then
            iterate loop_label;
        end if;
        if i>=10 then
            leave loop_label;
        end if;
        select i;
    end loop loop_label;

END
相關文章
相關標籤/搜索