MySQL 學習記錄系列(二)

目錄

3、視圖

3.1、視圖概述

3.2、創建或者修改視圖

3.3、查看視圖

3.4、刪除視圖

4、存儲過程和函數

4.1、存儲過程和函數概述

4.2、創建存儲過程

4.3、調用存儲過程

4.4、查看存儲過程

4.5、刪除存儲過程

4.6、語法

4.6.2、if條件判斷

4.6.3、傳遞參數

4.6.4、case結構

4.6.5、while循環

4.6.6、repeat結構

4.6.7、loop語句

4.6.8、leave語句

4.6.9、遊標/光標

4.7、存儲函數

5、觸發器

5.1、介紹

5.2、創建觸發器

5.3、刪除觸發器

5.4、查看觸發器


3、視圖

3.1、視圖概述

視圖(View)是一種虛擬存在的表。

視圖並不在數據庫中實際存在,行和列數據來自定義視圖的查詢中使用的表,並且是在使用視圖時動態生成的。

視圖就是一條SELECT語句執行後返回的結果集。

所以在創建視圖的時候,主要的工作就落在創建這條SQL查詢語句上。

視圖相對於普通的表的優勢主要包括以下幾項:

  • 簡單:使用視圖的用戶完全不需要關心後面對應的表的結構、關聯條件和篩選條件,對用戶來說已經是過濾好的複合條件的結果集。
  • 安全:使用視圖的用戶只能訪問他們被允許查詢的結果集,對錶的權限管理並不能限制到某個行某個列,但是通過視圖就可以簡單的實現。
  • 數據獨立:一旦視圖的結構確定了,可以屏蔽表結構變化對用戶的影響,源表增加列對視圖沒有影響;源表修改列名,則可以通過修改視圖來解決,不會造成對訪問者的影響。

3.2、創建或者修改視圖

創建視圖的語法爲:

CREATE [OR REPLACE] [ALGORITHM={UNDEFINED I MERGE | TEMPTABLE}]

VIEW view_name [(column_list)]

AS select_statement

[WITH [CASCADED I LOCAL] CHECK OPTION]

修改視圖的語法爲:(不建議更新視圖)

ALTER [ALGORITHM = {UNDEFINED I MERGE I TEMPTABLE}]

VIEW view_name [(column_list)]

AS select_statement

[WITH [CASCADED I LOCAL] CHECK OPTION]

選項:
WITH [CASCADED | LOCAL] CHECK OPTION 決定了是否允許更新數據,使記錄不再滿足視圖的條件。

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

CASCADED:必須滿足所有針對該視圖的所有視圖的條件纔可以更新。(默認機制)

示例,創建city_country_view視圖,執行如下SQL:

create or replace view city_country_view

as

select t.*,c.country_name from country c, city t where c.country_id=t.country_id;

查詢視圖

3.3、查看視圖

從MySQL 5.1版本開始,使用SHOW TABLES命令的時候不僅顯示錶的名字,同時也會顯示視圖的名字,而不存在單獨顯示視圖的SHOW VIEWS命令。

同樣,在使用SHOW TABLE STATUS命令的時候,不但可以顯示錶的信息,同時也可以顯示視圖的信息。

如果需要查詢某個視圖的定義,可以使用SHOW CREATE VIEW命令進行查看:

show create view view_city_country

3.4、刪除視圖

DROP VIEW [IF EXISTS] view_name [,view_name]...[RESTRICT I CASCADE]

示例,刪除視圖city_country_view:

DROP VIEW city_country_view;

 

4、存儲過程和函數

4.1、存儲過程和函數概述

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

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

函數:是一個有返回值的過程;

過程:是一個沒有返回值的函數;

4.2、創建存儲過程

CREATE PROCEDURE procedure_name([proc_parameter[,...]])
begin
        --sQL語句
end;

示例:

delimiter $
create procedure pro_test1()
begin 

select 'Hello Mysql';

end$

delimiter;

DELIMITER

該關鍵字用來聲明SQL語句的分隔符,告訴MySQL解釋器,該段命令是否已經結束了,mysql是否可以執行了。

默認情況下,delimiter是分號;。在命令行客戶端中,如果有一行命令以分號結束,那麼回車後,mysql將會執行該命令。

4.3、調用存儲過程

call pro_test1()

4.4、查看存儲過程

--查詢db_name數據庫中的所有的存儲過程

select name from mysql.proc where db='db_name';

--查詢存儲過程的狀態信息

show procedure status;

--查詢某個存儲過程的定義

show create procedure test.pro_test1\G;

4.5、刪除存儲過程

DROP PROCEDURE [IF EXISTS] sp_name;

4.6、語法

存儲過程是可以編程的,意味着可以使用變量,表達式,控制結構,來完成比較複雜的功能。

DECLARE

通過DECLARE可以定義一個局部變量,該變量的作用範圍只能在BEGIN..END塊中。

DECLARE var_name[,...] type [ DEFAULT value]

delimiter $ 

create procedure pro_test2()
begin 

declare num int default 5; 

select num+10; 

end$

delimiter ;

SET

直接賦值使用SET,可以賦常量或者賦表達式,具體語法如下:

SET var_name=expr [, var_name=expr]..…

DELIMITER $
CREATE PROCEDURE pro_test3)
BEGIN 
DECLARE NAME VARCHAR(20); 
SET NAME='MYSQL'; 
SELECT NAME; 
END$
DELIMITER;

也可以通過select...into 方式進行賦值操作:

DELIMITER $

CREATE PROCEDURE pro_test5()

BEGIN declare countnum int; 

select count(*) into countnum from city; 

select countnum;

end$

delimiter ;

4.6.2、if條件判斷

語法結構:

if search_condition then statement_list
[elseif search_condition then statement_list]..…
[else statement_list]
end if;

需求:

根據定義的身高變量,判定當前身高的所屬的身材類型

180及以上-------—->身材高挑
170-180------—->標準身材
170以下------->一般身材

示例:

CREATE DEFINER=`root`@`localhost` PROCEDURE `pro_test3`()
BEGIN
	DECLARE height int(100) DEFAULT 175;
	DECLARE description varchar(100) default '';
	
	if height >= 180	then 
		set description='身材高挑';
	elseif  height >= 170 and  height <  180 then 
		set description='標準身材';
	else
		set description='有點矮';
	end if;
	
	select CONCAT('身高', height, '對應的身材類型爲', description);
	
END

4.6.3、傳遞參數

語法格式:

create procedure procedure_name([in/out/inout]  參數名參數類型)

IN:該參數可以作爲輸入,也就是需要調用方傳入值,默認

OUT:該參數作爲輸出,也就是該參數可以作爲返回值

INOUT:既可以作爲輸入參數,也可以作爲輸出參數

IN-輸入

需求:

根據定義的身高變量,判定當前身高的所屬的身材類型

CREATE DEFINER=`root`@`localhost` PROCEDURE `pro_test3`(in height int)
BEGIN
	DECLARE description varchar(100) default '';
	
	if height >= 180	then 
		set description='身材高挑';
	elseif  height >= 170 and  height <  180 then 
		set description='標準身材';
	else
		set description='有點矮';
	end if;
	
	select CONCAT('身高', height, '對應的身材類型爲', description);
	
END

OUT-輸出

需求:

根據傳入的身高變量,獲取當前身高的所屬的身材類型

CREATE DEFINER=`root`@`localhost` PROCEDURE `pro_test3`(in height int(100),  description varchar(1024))
BEGIN
	
	if height >= 180	then 
		set description='身材高挑';
	elseif  height >= 170 and  height <  180 then 
		set description='標準身材';
	else
		set description='有點矮';
	end if;
	
	
END

調用:

call pro_test3(199, @description);

select @description

@description:這種變量要在變量名稱前面加上“@”符號,叫做用戶會話變量,代表整個會話過程都是有作用的,這個類似於全局變量一樣。

@@global.sort_buffer_size:這種在變量前加上“@@”符號,叫做系統變量

4.6.4、case結構

方式一:

CASE case_value

WHEN when_value THEN statement_list

[WHEN when_value THEN statement_list]..…

[ELSE statement_list]

END CASE;

方式二:

CASE WHEN search_condition THEN statement_list

[WHEN search_condition THEN statement_list]..…

[ELSE statement_1ist]

END CASE;

需求:

給定一個月份,然後計算出所在的季度

CREATE DEFINER=`root`@`localhost` PROCEDURE `pro_test3`(in mon int(100))
BEGIN
	DECLARE result varchar(1024) default '';
	
	CASE 
	WHEN mon >= 1  and mon < 4 THEN
		set result = '第一季度';
	WHEN mon >= 4  and mon < 7 THEN
		set result = '第二季度';
	WHEN mon >= 7  and mon < 10 THEN
		set result = '第三季度';
	ELSE
		set result = '第四季度';
END CASE;

	select result;
	
END

4.6.5、while循環

語法結構:

while search_condition do

statement_list

end while;

需求:

計算從1加到n的值

示例:

delimiter$
create procedure pro_test8(n int)
begin 

declare total int default 0;

declare start int default 0; 

while start <= n do 

set total=total+start; 

set start=start +1; 

end while;

4.6.6、repeat結構

有條件的循環控制語句,當滿足條件的時候退出循環。while是滿足條件才執行,repeat是滿足條件就退出循環。

語法結構:

REPEAT

statement_list

UNTIL search_condition

END REPEAT;

需求:

計算從1加到n的值

CREATE DEFINER=`root`@`localhost` PROCEDURE `pro_test3`(in n int(100))
BEGIN
	DECLARE total int(200) default 0;
	DECLARE num int(200) default 1;
	
	REPEAT
	set total = total+n;
	set n = n - 1;
UNTIL n=0 
END REPEAT;

	select total;
	
END

4.6.7、loop語句

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

[begin_label:]Loop
statement_list
END LoOP [end_label]

如果不在statement_list中增加退出循環的語句,那麼LOOP語句可以用來實現簡單的死循環。

4.6.8、leave語句

用來從標註的流程構造中退出,通常和BEGIN...END或者循環一起使用。

下面是一個使用LOOP和LEAVE的簡單例子,退出循環:

label :可以爲 loop 起一個別名

CREATE DEFINER=`root`@`localhost` PROCEDURE `pro_test3`(in n int(100))
BEGIN
	DECLARE total int(200) default 0;
	DECLARE num int(200) default 1;
	
	label: LOOP
	  set total = total + n;
		set n = n - 1;
		

	IF n < 0 THEN
		LEAVE label; 
	END IF; 
END LOOP label;


	select total;
	
END

4.6.9、遊標/光標

遊標是用來存儲查詢結果集的數據類型,在存儲過程和函數中可以使用光標對結果集進行循環的處理。

光標的使用包括光標的聲明、OPEN、FETCH和CLOSE,其語法分別如下。

等於說,遊標就是用於存儲結果集的

聲明光標:

DECLARE cursor_name CURSOR FOR select_statement;

OPEN光標:

OPEN cursor_name;

FETCH光標:

CLOSE cursor_name;

示例:

初始化腳本:

CREATE TABLE emp(
    id int(11) NOT NULL auto_increment,
    `name` varchar( 50) NOT NULL COMMENT '姓名',
    age int(11)comment '年齡',
    salary int(11)comment '薪水',
    primary key (id)
)engine=innodb default charset=utf8;
insert into emp(id,name,age,salary)values(null,'金毛獅王',55,3800),(null,'白眉鷹王',60,4000),(null,'青翼蝠王',38,2800),(null,'紫衫龍王',42,1800)

--查詢emp表中數據,並逐行獲取進行展示

CREATE DEFINER=`root`@`localhost` PROCEDURE `pro_test3`()
BEGIN
	DECLARE e_id int(20);
	DECLARE e_name VARCHAR(200);
	DECLARE e_age int(100);
	DECLARE e_salary int(11);
	DECLARE emp_result CURSOR for select * from emp;
	
	OPEN emp_result;
		FETCH emp_result into e_id,e_name,e_age,e_salary;
		SELECT CONCAT('id=',e_id,'name=',e_name,'age=',e_age, 'salary=', e_salary);
        
        FETCH emp_result into e_id,e_name,e_age,e_salary;
		SELECT CONCAT('id=',e_id,'name=',e_name,'age=',e_age, 'salary=', e_salary);
	
	CLOSE emp_result;

END

循環遊標

DECLARE emp_result CURSOR for select * from emp;
DECLARE EXIT HANDLER FOR NOT FOUND set has_data=0;

-- 必須聲明在遊標之後
-- 否則出現
ERROR 1337 (42000):Variable or condition declaration after cursor or handler declaration

CREATE DEFINER=`root`@`localhost` PROCEDURE `pro_test3`()
BEGIN
	DECLARE e_id int(20);
	DECLARE e_name VARCHAR(200);
	DECLARE e_age int(100);
	DECLARE e_salary int(11);
	DECLARE has_data int DEFAULT 1;
	
	DECLARE emp_result CURSOR for select * from emp;
	DECLARE EXIT HANDLER FOR NOT FOUND set has_data=0;
	
	
	
	OPEN emp_result;
		REPEAT
			FETCH emp_result into e_id,e_name,e_age,e_salary;
			SELECT CONCAT('id=',e_id,'name=',e_name,'age=',e_age, 'salary=', e_salary);
		
			UNTIL has_data=0		
		END REPEAT;
	
	CLOSE emp_result;

END

4.7、存儲函數

語法結構:

CREATE FUNCTION function_name([ param type..])
RETURNS type

BEGIN

..............

END;

案例:

定義一個存儲過程,請求滿足條件的總記錄數;

CREATE FUNCTION `func_test1`(`countryId` int)
	RETURNS int
BEGIN
	DECLARE num int;
	
	select COUNT(*) into num  from city where country_id = countryId;
	
	RETURN num;
END;

 

5、觸發器

5.1、介紹

觸發器是與表有關的數據庫對象,指在insert/update/delete之前或之後,觸發並執行觸發器中定義的SQL語句集合。

觸發器的這種特性可以協助應用在數據庫端確保數據的完整性,日誌記錄,數據校驗等操作。

使用別名OLD和NEW來引用觸發器中發生變化的記錄內容,這與其他的數據庫是相似的。

現在觸發器還只支持行級觸發,不支持語句級觸發。

5.2、創建觸發器

語法結構:

create trigger trigger_name

before/after insert/update/delete

on tbl_name

[ for each row]   -- 當前操作的是行級觸發器

begin

.......

end

trigger_stmt;

示例:

通過觸發器記錄emp表的數據變更日誌,包含增加,修改,刪除;

首先創建一張日誌表:

create table emp_logs(
	id int(11)not null auto_increment,
	operation varchar(20)not null comment'操作類型,insert/update/delete',
	operate_time datetime not null comment '操作時間',
	operate_id int(11)not null comment '操作表的ID',
	operate_params varchar(500) comment '操作參數',
	primary key(id)
)engine=innodb default charset=utf8;

創建insert型觸發器,完成插入數據時的日誌記錄:

CREATE TRIGGER emp_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( 1插入後( id : ',new.id,', NAME : ',new.name,', age : ',new.age,', salary : ',new.salary,') "));
ends

5.3、刪除觸發器

語法結構:

drop trigger [schema_name.]trigger_name

如果沒有指定 schema_name,默認爲當前數據庫。

5.4、查看觸發器

可以通過執行 SHOW TRIGGERS命令查看觸發器的狀態、語法等信息。

語法結構:

show triggers;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章