Python學習日記(四十) Mysql數據庫篇 八

Mysql存儲過程mysql

存儲過程是保存在Mysql上的一個別名(就是一堆SQL語句),使用別名就能夠查到結果不用再去寫SQL語句。存儲過程用於替代程序員寫SQL語句。程序員

建立存儲過程sql

delimiter //
CREATE PROCEDURE p1() BEGIN
    SELECT * FROM studenttable; INSERT INTO teachertable(tname) VALUES('陳晨'); END // delimiter ;

當咱們寫完這段代碼並執行,再去調用p1()就能夠直接執行裏面的查詢數據庫

call p1();

執行結果:oop

這樣的好處能讓功能代碼都整合到一塊且不用再去寫SQL語句,很差之處在於若是要改數據庫中的資料,那不必定能從存儲過程當中能拿到數據。性能

在公司處理數據時選用的方式:fetch

方式一:spa

  Mysql(DBA):存儲過程3d

  程序(程序員):調用存儲過程code

方式二:

  Mysql:什麼都不作

  程序:寫SQL語句

方式三:

  Mysql:什麼都不作

  程序:類和對象(本質就是SQL語句 )

經過Python中的pymysql模塊拿到p1的數據:

import pymysql conn = pymysql.connect(host = 'localhost',user = 'root',password = '',database = 'db2',charset = 'utf8') cursor = conn.cursor() cursor.callproc('p1') conn.commit() result = cursor.fetchall() print(result) cursor.close() conn.close()

傳參數in

in表示傳入一個值

delimiter //
CREATE PROCEDURE p2( IN pid INT, IN pnumber INT ) BEGIN
    SELECT * FROM scoretable WHERE student_id > pid AND number > pnumber; END // delimiter ;

呼叫執行過程p2並帶入參數

call p2(15,90);

這樣就能找到大於學生ID15而且分數大於90 的學生成績

利用pymysql執行達到相同效果:

cursor.callproc('p2',(15,80))

傳參數out

out僞造了一個返回值,主要用於表示存儲過程的執行結果

delimiter //
create procedure p3( in pid int, out pnumber int ) begin
    set pnumber = 80; select student_id from scoretable where student_id > pid and number > pnumber group by student_id; end // delimiter ;

呼叫執行過程p3並帶入參數

set @pn = 80; call p3(20,@pn); select @pn;

在pymysql中執行

import pymysql conn = pymysql.connect(host = 'localhost',user = 'root',password = '',database = 'db2',charset = 'utf8') cursor = conn.cursor() cursor.callproc('p3',(15,80)) r1 = cursor.fetchall() print(r1) cursor.execute('select @_p3_0,@_p3_1')     #返回前面寫的這兩個參數15 80 r2 = cursor.fetchall() print(r2) cursor.close() conn.close()

傳參數inout

結合in和out兩種特性

事務

比方說雙方進行一筆交易,但出現某種錯誤,一方支付了錢另外一方沒有收到,就能夠經過事務回滾到最初的狀態

delimiter //
create procedure p4( out p_status tinyint                                                     -- 狀態變量,用於判斷是否出現執行異常
) begin 
    declare exit handler for sqlexception                             -- 執行出現異常的代碼
    begin
        set p_status = 1;                                                     -- 1表示出現異常
        rollback;                                                                -- 將事務回滾
    end ; start transaction;                                                       -- 開始事務
        select student_id from scoretable group by student_id; insert into scoretable(student_id,course_id,number) values(25,3,78); commit;                                                                         -- 結束事務
    set p_status = 2;                                                               -- 2表示沒有出現異常
end // delimiter ;

遊標

遊標的性能雖然不高可是能實現循環的效果,對於每一行數據要進行分開計算的時候咱們才須要用到遊標

先建立兩個表t二、t3,而後實現t3中每行score的值等於每行t2中id+score的值

t2:

t3:

存儲過程代碼:

delimiter //
create procedure p5() begin 
    declare p_id int; declare p_score int; declare done int default false; declare temp int; declare my_cursor cursor for select id,score from t2; declare continue handler for not found set done = true; open my_cursor; p_l:loop fetch my_cursor into p_id,p_score; if done then leave p_l; end if; set temp = p_id + p_score; insert into t3(score) values(temp); end loop p_l; close my_cursor; end // delimiter ;

執行p5:

call p5();

結果:

動態執行SQL(防SQL注入)

delimiter // 
create procedure p7( in arg int ) -- 預檢測SQL語句是否具備合法性
begin 
    set @ppp = arg; prepare prod from 'select * from studenttable where sid > ?'; execute prod using @ppp; deallocate prepare prod; end // delimiter ;
call p7(15)
相關文章
相關標籤/搜索