Mysql中的檢視、變數、儲存過程、流程控制結構、函式和觸發器
一、檢視
2.1 、什麼是檢視
檢視mysql5.1版本出現的新特性,本身是一個虛擬表,它的資料來自於表,通過執行時動態生成。通俗的講,檢視就是一條SELECT語句執行後返回的結果集。所以我們在建立檢視的時候,主要的工作就落在建立這條SQL查詢語句上。
2.2、使用檢視的好處
- 簡化sql語句,用檢視的使用者完全不需要關心後面對應的表的結構、關聯條件和篩選條件,對使用者來說已經是過濾好的複合條件的結果集。
- 保護基表的資料,提高了安全性,使用檢視的使用者只能訪問他們被允許查詢的結果集,對錶的許可權管理並不能限制到某個行某個列,但是通過檢視就可以簡單的實現。
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、系統變數
系統變數就是由系統提供的變數,不用使用者自定義。
-
檢視系統變數
-- 檢視所有系統變數 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、使用者自定義變數
-
區域性變數
區域性變數一般用在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
-
使用者變數(一次會話有效)
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、分支結構
-
if函式
-- if函式實現簡單的單雙分支,可以放在表示式的任何位置 if(條件,值1,值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
-
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、迴圈結構
-
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
-
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滿足就退出迴圈
-
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;