1. 程式人生 > >python學習_day48_mysql其他補充

python學習_day48_mysql其他補充

exception 修改 結束 end 使用 incr 方便 oca 入參

一、視圖

  視圖是一個虛擬表(非真實存在),其本質是【根據SQL語句獲取動態的數據集,並為其命名】,用戶使用時只需使用【名稱】即可獲取結果集,可以將該結果集當做表來使用。使用視圖我們可以把查詢過程中的臨時表摘出來,用視圖去實現,這樣以後再想操作該臨時表的數據時就無需重寫復雜的sql了,直接去視圖中查找即可,但視圖有明顯地效率問題,並且視圖是存放在數據庫中的,如果我們程序中使用的sql過分依賴數據庫中的視圖,即強耦合,那就意味著擴展sql極為不便,因此並不推薦使用。

1、創建視圖

create  view 視圖名 as sql語句

  註意,上述為創建視圖的語句,但是語句中的sql語句中不能包含子查詢。實例如下:

技術分享

  可以通過創建視圖的方式,將上述sql查詢語句的結果保存成視圖形式的虛擬表,下次再次使用時,就可以避免上述重復的sql語句:

技術分享

2、視圖的修改

  正如視圖概念中所述,視圖為sql語句查詢結果的虛擬表,它的真實數據是來源sql語句中涉及的真正的表中,當sql語句中只關聯一個表,更改視圖中的數據,所被關聯的表中的數據也會跟著更改,顯然這是不合理的,當sql語句中關聯多個表,則壓根不可以實現對視圖中的數據的更改。總之不可以通過update或者insert等語句對視圖中的內容進行更改。如果想真正的實現對視圖的更改,其實就是更改原有視圖中的sql語句,具體的更改語法如下:

alter view 原視圖名 as 新sql語句 

技術分享

3、刪除視圖

drop view 視圖名      #例:drop view course_teacher

  總結:使用視圖以後就無需每次都重寫子查詢的sql,但是這麽效率並不高,還不如我們寫子查詢的效率高;其次視圖是存放到數據庫裏的,如果我們程序中的sql過分依賴於數據庫中存放的視圖,那麽意味著,一旦sql需要修改且涉及到視圖的部分,則必須去數據庫中進行修改。

二、觸發器

  使用觸發器可以定制用戶對表進行【增、刪、改】操作時前後的行為,註意:沒有查詢

1、創建觸發器語法

# 插入前
CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON tb1 FOR EACH ROW
BEGIN
    ...
END

# 插入後 CREATE TRIGGER tri_after_insert_tb1 AFTER INSERT ON tb1 FOR EACH ROW BEGIN ... END # 刪除前 CREATE TRIGGER tri_before_delete_tb1 BEFORE DELETE ON tb1 FOR EACH ROW BEGIN ... END # 刪除後 CREATE TRIGGER tri_after_delete_tb1 AFTER DELETE ON tb1 FOR EACH ROW BEGIN ... END # 更新前 CREATE TRIGGER tri_before_update_tb1 BEFORE UPDATE ON tb1 FOR EACH ROW BEGIN ... END # 更新後 CREATE TRIGGER tri_after_update_tb1 AFTER UPDATE ON tb1 FOR EACH ROW BEGIN ... END

2、觸發器實例

#準備表
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 ;


#往表cmd中插入記錄,觸發觸發器,根據IF的條件決定是否插入錯誤日誌
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);


#查詢錯誤日誌,發現有兩條
mysql> select * from errlog;
+----+-----------------+---------------------+
| id | err_cmd         | err_time            |
+----+-----------------+---------------------+
|  1 | cat /etc/passwd | 2017-09-14 22:18:48 |
|  2 | useradd xxx     | 2017-09-14 22:18:48 |
+----+-----------------+---------------------+
rows in set (0.00 sec)

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

3、觸發器的刪除

  觸發器無法由用戶直接調用,而是由於對表的【增/刪/改】操作被動引發的。刪除觸發器的語法如下:

drop trigger 觸發器名;  #例:drop trigger tri_after_insert_cmd;

三、事務

  事務用於將某些操作的多個SQL作為原子性操作,一旦有某一個出現錯誤,即可回滾到原來的狀態,從而保證數據庫數據完整性。

create table user(
id int primary key auto_increment,
name char(32),
balance int
);

insert into user(name,balance)
values
(wsb,1000),
(egon,1000),
(ysb,1000);

#原子操作,執行中無異常
start transaction;
update user set balance=900 where name=wsb; 
update user set balance=1010 where name=egon; 
update user set balance=1090 where name=ysb; 
commit;

#出現異常,回滾到初始狀態
start transaction;
update user set balance=800 where name=wsb; 
update user set balance=1020 where name=egon; 
uppdate user set balance=1180 where name=ysb; 
rollback;  
commit;

技術分享技術分享

四、存儲過程

  存儲過程包含了一系列可執行的sql語句,存儲過程存放於MySQL中,通過調用它的名字可以執行其內部的一堆sql。使用存儲過程的優點:(1)用於替代程序寫的SQL語句,實現程序與sql解耦;(2)基於網絡傳輸,傳別名的數據量小,而直接傳sql數據量大。缺點是程序員擴展功能不方便。

1、數據庫與程序使用方式

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

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

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

2、創建無參數存儲過程

#創建無參存儲過程
delimiter $$                             #符號不局限於此,但前後需一致
create procedure p1()
begin
    declare i int default 1;
    while (i<10) do
        select * from course;
        set i=i+1;
    end while;
end $$
delimiter ;


#調用存儲過程
call p1();

3、創建有參數存儲過程

  有參數的情況時,在定義存儲過程中必須定義參數的類型,包含三種,解釋如下:

#in          僅用於傳入參數用
#out         僅用於返回值用
#inout       既可以傳入又可以當作返回值

  應用實例:

#創建有參存儲過程
delimiter $$
create procedure p2(
    in x char(5),
    out y int
)
begin
    select cid from course where cname=x;
    set y=1;
end $$
delimiter ;

#mysql中調用:
set @x=生物;
set @y=0;
call p2(@x,@y);

#查看返回值
select @y;


#pymysql中的調用:
import pymysql
conn=pymysql.connect(
    host=localhost,
    port=3306,
    user=root,
    password=‘‘,
    database=day48,
    charset=utf8
   )

cur=conn.cursor()
#拿到存儲過程sql語句的執行結果
cur.callproc(p2,(生物,0))
print(cur.fetchall())
#拿到存儲過程返回值 ‘‘‘pymysql默認會把參數變為如下形式名字,分別為生物和0的名字:@_p2_0 ,@_p2_1;‘‘‘ cur.execute(select @_p2_1;) print(cur.fetchone()) cur.close() conn.close()

  帶事務存儲過程實例:

#介紹
delimiter //
            create procedure p4(
                out status int
            )
            BEGIN
                1. 聲明如果出現異常則執行{
                    set status = 1;
                    rollback;
                }
                   
                開始事務
                    -- 由秦兵賬戶減去100
                    -- 方少偉賬戶加90
                    -- 張根賬戶加10
                    commit;
                結束
                
                set status = 2;
                
                
            END //
            delimiter ;

#實現
delimiter //
create PROCEDURE p5(
    OUT p_return_code tinyint
)
BEGIN 
    DECLARE exit handler for sqlexception 
    BEGIN 
        -- ERROR 
        set p_return_code = 1; 
        rollback; 
    END; 

    DECLARE exit handler for sqlwarning 
    BEGIN 
        -- WARNING 
        set p_return_code = 2; 
        rollback; 
    END; 

    START TRANSACTION; 
        DELETE from tb1; #執行失敗
        insert into blog(name,sub_time) values(yyy,now());
    COMMIT; 

    -- SUCCESS 
    set p_return_code = 0; #0代表執行成功

END //
delimiter ;

#在mysql中調用存儲過程
set @res=123;
call p5(@res);
select @res;

#在python中基於pymysql調用存儲過程
cursor.callproc(p5,(123,))
print(cursor.fetchall()) #查詢select的查詢結果

cursor.execute(select @_p5_0;)
print(cursor.fetchall())

4、刪除存儲過程

drop procedure proc_name;

python學習_day48_mysql其他補充