17 存儲過程

過程:

封裝了若干條語句.調用時,這些封裝體執行.

函數:

是一個有返回值的過程.

過程是沒有返回值的函數

存儲過程:

把此過程存儲在數據庫中,因此稱為存儲過程

存儲過程語法

# 創建語法:
    create procedure procedureName()
    begin
        -- sql語句
    end$

# 刪除存儲過程
    drop procedure procedureName;

# 查看已有的procedure
    show procedure status;

# 調用存儲過程:
    call procedureName();

存儲過程1--創建簡單的存儲過程

# eg:
    create procedure p1()
    begin
        select * from tableName;
    end$

存儲過程2--引入變量

# 存儲過稱是可以編程的,意味著可以使用變量,表達式,控制結構    
# eg:
    create procedure p2()
    begin
        declare age int default 18;
        declare height int default 180;
        select concat('年齡是',age,'身高是',height);
    end$

存儲過程3--變量運算

# 存儲過稱中,變量可以在sql語句中合法的運算,如+-*/,注意運算的結果是如何賦值給變量
# 語法--set 變量名 := expression
# eg:
    create procedure p3()
    begin
        declare age int default 18;
        declare height int default 180;
        set age := age + 20;
        select concat('20年后年齡是',age,'身高是',height);
    end$

存儲過稱4--控制結構(if/else)

# 語法:
    if 
        conditon 
    then
        statement
    else
        statement
    end;

# eg:
    create procedure p4()
    begin
        declare age int default 18;
        if age >= 18 then
            select '已成年';
        else
            select '未成年';
        end if;
    end$

存儲過稱5--控制結構2(while)

# 三種控制結構:  
    順序,選擇,循環

# eg: 求1-100的和
    create procedure p5()
    begin
        declare total int default 0;
        declare num int default 0;

        while num <= 100 do
            set total := total + num;
            set num := num + 1;
        end while;

        select total;
    end$ 

存儲過稱6--控制結構3(case)

# 用if/else也能實現同樣的效果
# eg: 
    create procedure p6()
    begin
        declare pos int default 0;
        set pos := floor(5*rand());

        case pos
            when 1 then select 'fly';
            when 2 then select 'sea';
            else select 'run';
        end case;
    end$  

存儲過稱7--控制結構4(repeat)

# 用while也能實現同樣的效果
# eg: 
    create procedure p7()
    begin
        declare total int default 0;
        declare i int default 0;

        repeat
            set i := i+1;
            set total := total + i;
            
        until i>=100
        end repeat;
        
        select total;
    end$ 

存儲過稱8--傳參

# 存儲過程的括號里,可以聲明參數,
# 語法:  
    [in/out/inout] 參數名 參數類型,不寫時,默認為in

# 調用: 
    call p8(3,4)

# eg:
    create procedure p8(width int , height int)
    begin
        select concat('你的面積是',width * height) as area;

        if width > height then
            select '寬大于高';
        elseif width < height then
            select '寬小于高';
        else
            select '寬等于高';
        end if;
    end$

存儲過稱9--in型參數

# 存儲過程中可以接收到這個參數
# eg: 求1-n的和
    create procedure p9(in n int)
    begin
        declare total int default 0;
        declare num int default 0;

        while num <= n do
            set total := total + num;
            set num := num + 1;
        end while;

        select total;
    end$

存儲過稱10--out型參數

# 將存儲過程中值輸出
# 調用: 
    call p10(100,@argsName)

# eg: 求1-n的和
    create procedure p10(in n int,out total int)
    begin
        declare num int default 0;
        set total := 0;

        while num <= n do
            set total := total + num;
            set num := num + 1;
        end while;

        select total;
    end$
# 此處執行完成后,輸入select @argsName即可得到對應的結果

存儲過稱11--inout型參數

# 調用: 
    set @age = 18
    call p11(@age)

# eg:   
    create procedure p11(inout age int)
    begin
        set age := 1;
        set age := age + 20;
    end$

存儲過稱12--cursor 游標

# 一條sql,對應N條資源,取出資源的接口/句柄,就說游標
# 沿著游標,可以一次取出一行

# eg: 
    create procedure p12()
    begin
        declare row_gid int;
        declare row_num int;
        declare row_name varchar(20);

        -- 這種方法不推薦使用
        -- 定義一個游標
        declare cursorName cursor for select gid,num,name from goods;

        open cursorName;
            -- 將顯示的第一行值賦予對應的變量
            fetch cursorName into row_gid,row_num,row_name;
            select row_gid,row_num,row_name;

            -- 將顯示的第二行值賦予對應的變量
            fetch cursorName into row_gid,row_num,row_name;
            select row_gid,row_num,row_name;

            -- 將顯示的第三行值賦予對應的變量(如果只有兩條數據,賦值三次會報錯)
            fetch cursorName into row_gid,row_num,row_name;
            select row_gid,row_num,row_name;

        close cursorName;
    end$

存儲過稱13--cursor 游標(推薦使用)

# eg:
    create procedure p13()
    begin
        declare row_gid int;
        declare row_num int;
        declare row_name varchar(20);

        declare i int default 0;
        -- 定義一個變量,用來計算顯示了幾條數據
        declare cnt int default 0;

        -- 定義一個游標
        declare cursorName cursor for select gid,num,name from goods;

        select count(*) into cnt from goods;

        open cursorName;

            repeat
                set i := i +1;
                fetch cursorName into row_gid,row_num,row_name;
                select row_gid,row_num,row_name;
            until i >= cnt
            end repeat;
        
        close cursorName;
    end$

存儲過稱14--越界標志(continue handler for not found)

# 在MySQL cursor中,可以declare continue handler來操作一個越界標志
# 語法: declare continue handler for not  found 語句;
# 表中只有三條數據,但是下面的代碼執行后 ,會取出四行,最后一行顯示兩次
# 代碼中有邏輯錯誤,分析:
    當第四次執行 repeat 時,fetch-->沒有數據,觸發越界標志中的not  found-->set you := 0-->continue-->執行fetch后面的sql語句(select row_gid,row_num,row_name;)-->所以,最后一行被取出兩次

# eg:
    create procedure p14()
    begin
        declare row_gid int;
        declare row_num int;
        declare row_name varchar(20);

        declare you int default 1;
        
        -- 定義一個游標
        declare cursorName cursor for select gid,num,name from goods;
        declare continue handler for not found set you := 0;

        open cursorName;

        repeat
            fetch cursorName into row_gid,row_num,row_name;
            select row_gid,row_num,row_name;
        until you = 0
        end repeat;
        
        close cursorName;
    end$

存儲過稱15--越界標志(exit handler for not found)

# 越界標志解決邏輯錯誤(不完善,沒考慮到表為空的情況)
# 引入另一種越界標志:declare exit handler for not found 語句;

# eg:
    create procedure p15()
    begin
        declare row_gid int;
        declare row_num int;
        declare row_name varchar(20);

        declare you int default 1;
        
        -- 定義一個游標
        declare cursorName cursor for select gid,num,name from goods;
        declare exit handler for not found set you := 0;

        open cursorName;

        repeat
            fetch cursorName into row_gid,row_num,row_name;
            select row_gid,row_num,row_name;
        until you = 0
        end repeat;
        
        close cursorName;
    end$

存儲過稱16--越界標志(undo handler)

# 除以上兩種越界標志(continue,exit)外,還有undo handler
# continue是觸發后,后面的語句繼續執行
# exit是觸發后,后面的語句不再執行
# undo是觸發后,前面的語句撤銷(MySQL暫不支持)


# 不改變越界標志,解決邏輯錯誤(完善)
# eg: 
    create procedure p16()
    begin
        declare row_gid int;
        declare row_num int;
        declare row_name varchar(20);

        declare you int default 1;
        
        -- 定義一個游標
        declare cursorName cursor for select gid,num,name from goods;
        declare exit handler for not found set you := 0;

        open cursorName;
            -- 1: 先取出一行數據,如果取出,則 not found未觸發,
            fetch cursorName into row_gid,row_num,row_name;

            repeat
                -- 2: 執行顯示語句
                select row_gid,row_num,row_name;
                -- 3: 在進行fetch如果取不到,觸發continue越界標志,繼續向下執行,
                -- 下面沒有sql語句,所以不會再顯示
                fetch cursorName into row_gid,row_num,row_name;
            until you = 0
            end repeat;
        
        close cursorName;
    end$
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • oracle存儲過程常用技巧 我們在進行pl/sql編程時打交道最多的就是存儲過程了。存儲過程的結構是非常的簡單的...
    dertch閱讀 3,509評論 1 12
  • 我們在進行pl/sql編程時打交道最多的就是存儲過程了。存儲過程的結構是非常的簡單的,我們在這里除了學習存儲過程的...
    AlbenXie閱讀 2,983評論 1 3
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,766評論 18 399
  • 1.1 基本結構 PL/SQL程序由三個塊組成,即聲明部分、執行部分、異常處理部分。 1.2 命名規則 1.3 記...
    慢清塵閱讀 3,900評論 3 14
  • 往往看別人的代碼會有這樣的感慨:看不懂理還亂是離愁別是一番滋味在心頭 為什么要使用存儲過程? 在mysql開發中使...
    老馬的春天閱讀 2,141評論 0 9