1. 程式人生 > 實用技巧 >Mysql中的檢視、變數、儲存過程、流程控制結構、函式和觸發器

Mysql中的檢視、變數、儲存過程、流程控制結構、函式和觸發器

一、檢視

2.1 、什麼是檢視

​ 檢視mysql5.1版本出現的新特性,本身是一個虛擬表,它的資料來自於表,通過執行時動態生成。通俗的講,檢視就是一條SELECT語句執行後返回的結果集。所以我們在建立檢視的時候,主要的工作就落在建立這條SQL查詢語句上。

2.2、使用檢視的好處

  1. 簡化sql語句,用檢視的使用者完全不需要關心後面對應的表的結構、關聯條件和篩選條件,對使用者來說已經是過濾好的複合條件的結果集。
  2. 保護基表的資料,提高了安全性,使用檢視的使用者只能訪問他們被允許查詢的結果集,對錶的許可權管理並不能限制到某個行某個列,但是通過檢視就可以簡單的實現。

2.3、建立檢視

CREATE [OR REPLACE]  VIEW  view_name 
AS     select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]

如果在建立檢視的時候制定了“WITH CHECK OPTION”,那麼更新資料時不能插入或更新不符合檢視限制條件(where語句)的記錄。

LOCAL : 只要滿足本檢視的條件就可以更新。

CASCADED(預設值) : 必須滿足所有針對該檢視的所有檢視的條件才可以更新。

2.4、修改檢視

​ 修改方式一:

CREATE [OR REPLACE]  VIEW  view_name 
AS     select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]

方式二:

alter view  view_name 
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]

2.3、檢視檢視

​ 檢視檢視的方式和查看錶的方式差不多

desc view_name
show create view view_name
show tables;-- 不僅可以顯示當前資料庫下的表還可以顯示出檢視,沒有show views

2.4、刪除檢視

drop view view_name1,view_name2

注意:檢視一般是用於查詢,而不是更新,具有以下特點的檢視都不允許更新

  • 包含分組函式、group by、distinct、having、union、join
  • 檢視欄位來自欄位表示式或常數,不可執行INSERT和UPDATE,但允許執行DELETE
  • where後的子查詢用到了from中的表
  • 不可更新的檢視匯出的檢視

2.5檢視與表的比較

關鍵字 是否使用物理空間 作用於
檢視 view 只保留sql邏輯,佔用空間小 一般用於查詢
table 儲存實際的資料 可用於增刪改查

二、mysql中的變數

mysql中的變數按作用範圍可以分為以下幾個型別:區域性變數,會話變數,全域性變數。按是否是使用者自定義的又可以分為系統變數和使用者自定義變數。

2.1、系統變數

​ 系統變數就是由系統提供的變數,不用使用者自定義。

  1. 檢視系統變數

    -- 檢視所有系統變數
    show [global | session ] variables [like]
    -- 檢視指定的系統變數
    select @@[global | session].變數名  -- 類似與物件.屬性
    
    -- 給系統變數賦值
    set [global | session] 變數名 = 值
    set @@[global | session].變數名=值;
    
  • global表示全域性變數,伺服器層面上的,必須擁有super許可權才能為系統變數賦值,作用域為整個伺服器,也就是針對於所有連線(會話)有效
  • session表示會話變數,作用域為當前的會話(連線)

注意:local是session的近義詞,session可以使用local代替,在不指定session或者global的情況下,預設是session

注意:無論是global變數還是session變數,在mysql服務重啟之後,資料庫的配置又會重新初始化,一切按照my.ini的配置進行初始化。global和session的配置都會失效了

2.2、使用者自定義變數

  1. 區域性變數

    ​ 區域性變數一般用在sql語句塊中,比如儲存過程的begin/end,只在當前begin/end程式碼塊中有效,且只能放在begin end中,而且只能放在第一句。在該語句塊執行完畢後,區域性變數就消失了。declare語句專門用於定義區域性變數,可以使用default來說明預設值。

    宣告方式:declare 變數名 型別 【default 值】;

    賦值方式:

    set 變數名 = 值;
    set 變數名: = 值;
    select xx into 變數名 from 表;
    
    CREATE PROCEDURE myprocedure()
    BEGIN
    declare age int default 0;
    set age = 5;
    select age;
    end
    
  2. 使用者變數(一次會話有效)

    MySQL中使用者變數不用事前申明,在用的時候直接用“@變數名”使用就可以了。使用者變數 在客戶端連結到資料庫例項整個過程中使用者變數都是有效的。可以在begin end裡面,也可以放在外面。

    注意:無論使用還是賦值使用者變數都需要在前面記得加上@

    賦值方式:

    set @變數名=值;
    set @變數名:=值;
    select @變數名:=值;
    select xx into @變數名 from 表;
    select @num:=欄位名 from 表名;
    

    注意上面兩種賦值符號,使用set時可以用“=”或“:=”,但是使用select時必須用“:=賦值”

    使用方式:

    select @變數名;
    

三、儲存過程

​ 儲存過程和函式是 事先經過編譯並存儲在資料庫中的一段 SQL 語句的集合,呼叫儲存過程和函式可以簡化應用開發人員的很多工作,減少資料在資料庫和應用伺服器之間的傳輸,對於提高資料處理的效率是有好處的。

儲存過程和函式的區別在於函式必須有返回值,而儲存過程沒有

  • 儲存函式:是一個有返回值的儲存過程

  • 儲存過程:是一個沒有返回值的儲存函式

3.2、建立儲存過程

CREATE PROCEDURE procedure_name (引數模式 引數名 引數型別)
begin
	 SQL語句
end
-- 引數型別有三種
in(預設):表示輸入的引數
out:表示輸出的引數
inout:可以輸入又可以輸出

1.引數模式:in、out、inout,其中in可以省略

2.儲存過程體的每一條sql語句都需要用分號結尾

在使用命令列寫儲存過程時,由於過程中的每一條sql都需要以‘;’結尾mysql會誤以為是整個過程的結束,我們可以通過delimiter 重新定義一個分隔符

delimiter $

create procedure pro_test1()
begin
	select 'Hello Mysql' ;
end$

DELIMITER:

​ 該關鍵字用來宣告SQL語句的分隔符 , 告訴 MySQL 直譯器,該段命令是否已經結束了,mysql是否可以執行了。預設情況下,delimiter是分號;。在命令列客戶端中,如果有一行命令以分號結束,那麼回車後,mysql將會執行該命令。

呼叫儲存過程:

call procedure_name(引數)
呼叫in模式的引數:call sp1(‘值’);
呼叫out模式的引數:set @name; call sp1(@name);select @name;
呼叫inout模式的引數:set @name=值; call sp1(@name); select @name;

檢視儲存過程:

-- 查詢某個儲存過程的定義
show create procedure 儲存過程名;
-- 查詢db_name資料庫中的所有的儲存過程
select name from mysql.proc where db='db_name';

刪除儲存過程

DROP PROCEDURE  [IF EXISTS] procedure_name ;

四、流程控制結構

4.1、分支結構

  1. if函式

    -- if函式實現簡單的單雙分支,可以放在表示式的任何位置
    if(條件,值1,值2)
    
  2. if條件判斷

    實現多分支條件判斷

    語法:

    -- id條件判斷語句只能放在 begin end 語句中
    if 條件1 then 語句1;
    elseif 條件2 then 語句2;
    ...
    else 語句n;
    end if;
    
    -- 例子
    create procedure procedure1()
    begin
      declare  height  int  default  175; 
      declare  description  varchar(50);
      
      if  height >= 180  then
        set description = '身材高挑';
      elseif height >= 170 and height < 180  then
        set description = '標準身材';
      else
        set description = '一般身材';
      end if;
      
      select description ;
    end
    
  3. case結構實現多分支條件判斷

    case結構可以放在任何位置,如果放在begin end 外面,作為表示式結合著其他語句使用如果放在begin end 裡面,一般作為獨立的語句使用

    方式一:

    case 表示式或欄位
    when 值1 then 語句1;
    when 值2 then 語句2;
    ..
    else 語句n;
    end [case];
    
    -- 例子
    create procedure procedure2(day int)
    begin
      declare result varchar(20);
      case day
        when  1 then 
          set result = '星期一';
        when  2 then 
          set result = '星期二';
    	  when  3 then 
          set result = '星期三';
        when  4 then 
          set result = '星期四';
        when  5 then 
          set result = '星期五';
        when  6 then 
          set result = '星期六';
    		when  7 then 
          set result = '星期七';
    		else
    			set result = '輸入錯誤';
      end case;
      
      select concat('今天是 :',result) as dayofweek ;
    end
    

    方式二:

    case 
    when 條件1 then 語句1;
    when 條件2 then 語句2;
    ..
    else 語句n;
    end [case];
    
    -- 例子
    create procedure procedure3(month int)
    begin
      declare result varchar(20);
      case 
        when month >= 1 and month <=3 then 
          set result = '第一季度';
        when month >= 4 and month <=6 then 
          set result = '第二季度';
        when month >= 7 and month <=9 then 
          set result = '第三季度';
        when month >= 10 and month <=12 then 
          set result = '第四季度';
      end case;
      
      select concat('您輸入的月份為 :', month , ' , 該月份為 : ' , result) as content ; 
    end
    

    4.2、迴圈結構

    1. while迴圈

      while迴圈是滿足條件就繼續執行

      語法:
      
      [名稱:] while 迴圈條件 do
      	迴圈體
      end while [名稱];
      
      -- 例子:
      -- 從0加到n
      create procedure procedure4(n int)
      begin
        declare total int default 0;
        declare num int default 1;
        name1:while num<=n do
          set total = total + num;
      	set num = num + 1;
        end while name1;
        select total;
      end
      
    2. repeat迴圈

      repeat是有條件的迴圈控制語句, 當滿足條件的時候退出迴圈 。

      【名稱:】repeat
      		迴圈體
      until 結束條件 
      end repeat 【名稱】;
      
      -- 例子從1加到n
      create procedure procedure5(n int)
      begin
        declare total int default 0;
        
        repeat 
          set total = total + n;
          set n = n - 1;
          until n=0  
        end repeat;
        select total ;
      end
      -- 知道until滿足就退出迴圈
      
      
    3. loop迴圈

      loop 實現簡單的迴圈,退出迴圈的條件需要使用其他的語句定義,通常可以使用 LEAVE 語句實現,具體語法如下:

      【名稱:】loop
      迴圈體
      end loop 【名稱】;

      -- 例子從0加到n
      CREATE PROCEDURE procedure6(n int)
      BEGIN
        declare total int default 0;  
        ins: LOOP 
          IF n <= 0 then
          /* 注意這裡使用了 leave來跳出迴圈,類似於break,
          iterate可以用來結束本次迴圈開啟下一次迴圈,類似於	continue,且使用了leave或者iterate都必須指定循	環的名稱
         */
            leave ins;
          END IF;  
          set total = total + n;
          set n = n - 1;
        END LOOP ins;  
        select total;
      END
  迴圈控制語句

  - leave:類似於break,用於跳出所在的迴圈
  - iterate:類似於continue,用於結束本次迴圈,繼續下一次

  迴圈語句的總結:

  - 三種迴圈只能放在begin end中,都能實現迴圈結構
  - 這三種迴圈都可以省略名稱,但如果迴圈中添加了迴圈控制語句(leave或   iterate)則必須新增名稱
  - loop 一般用於實現簡單的死迴圈,while 先判斷後執行repeat 先執行後判斷,無條件至少執行一次。

五、儲存函式

​ 儲存函式相對於儲存過程最大的一個不同點就是,儲存函式必須有返回值

CREATE FUNCTION function_name(引數模式 引數名 引數型別) --引數模式是in可以省略
-- 宣告返回型別,這歷史returns,不是return
RETURNS type 
BEGIN
	sql語句
	return 返回值;
END;

-- 例子,將輸入的數乘2並返回
create FUNCTION fun1(num int)
returns int
BEGIN
	DECLARE cnum int default 0;
	set cnum = num*2;
	return cnum;
end

-- 使用函式
select fun1(5);

六、觸發器

6.1、簡介

​ 觸發器是與表有關的資料庫物件,指在 insert/update/delete 之前或之後,觸發並執行觸發器中定義的SQL語句集合。觸發器的這種特性可以協助應用在資料庫端確保資料的完整性 , 日誌記錄 , 資料校驗等操作 。觸發事件的操作和觸發器裡的SQL語句是一個事務操作,具有原子性,要麼全部執行,要麼都不執行;

使用別名 OLD 和 NEW 來引用觸發器中發生變化的記錄內容

觸發器型別 NEW 和 OLD的使用
INSERT 型觸發器 NEW 表示將要或者已經新增的資料
UPDATE 型觸發器 OLD 表示修改之前的資料 , NEW 表示將要或已經修改後的資料
DELETE 型觸發器 OLD 表示將要或者已經刪除的資料

6.2建立觸發器

create trigger trigger_name 

before/after insert/update/delete

on tbl_name 

[ for each row ]  -- 行級觸發器

begin

	trigger_stmt ;

end;

before/after :觸發器觸發的時間

insert/update/delete:觸發器觸發的條件

根據出發時間和觸發條件的組合(笛卡爾積)可以看出一種有6中觸發器。

for each row:行級觸發器,針對每一行的改動執行一次

在 InnoDB 資料庫中,其上建立的表是事務性表,也就是事務安全的。這時,若SQL語句或觸發器執行失敗,MySQL 會回滾事務,有:
①如果 BEFORE 觸發器執行失敗,SQL 無法正確執行。
②SQL 執行失敗時,AFTER 型觸發器不會觸發。
③AFTER 型別的觸發器執行失敗,SQL 會回滾。

注意:觸發器使用的表需要支援事務(就是InnoDB),建立觸發器的表,不能再sql語句(就是BEGIN...END)中再次操作該張表。

-- 在emp表中插入資料後執行觸發器
create trigger emp_logs_insert_trigger
after insert 
on emp 
for each row 
begin
  insert into emp_logs (id,operation,operate_time,operate_id,operate_params) values(null,'insert',now(),new.id,concat('插入後(id:',new.id,', name:',new.name,', age:',new.age,', salary:',new.salary,')'));	
end 

6.3、刪除觸發器

-- 如果不指定schema_name,就預設當前的資料庫
drop trigger [schema_name.]trigger_name

6.4、檢視觸發器

-- 可以通過執行 SHOW TRIGGERS 命令檢視觸發器的狀態、語法等資訊。
show triggers;

參考連結:https://www.jianshu.com/p/3ffdf1397ce1