SQL學習筆記系列(七)存儲過程和函數

變量

系統變量

說明:變量由系統提供,不是用戶定義,屬於服務器層面程序員

#使用的語法
#1.查看全部的系統變量
SHOW GLOBAL VARIABLES#全局變量
SHOW 【SESSION】 VARIABLES#會話變量

#2.查看知足條件的部分系統變量
SHOW GLOBAL [SESSION] VARIABLES LIKE '%char%';

#3.查看指定的某個系統變量的值
SELECT @@global.系統變量名;
SELECT @@session.系統變量名;#默認session

#4.爲某個系統變量賦值
#方式一
SET GLOBAL 系統變量值=值;
SET 【SESSION】 系統變量值=值;

#方式二
SET @@global.系統變量名=值;
SET @@【session】.系統變量名=值;

#注意:若是是全局級別,則須要加global,若是是會話級別,則須要加SESSION,若是不寫,則默認SESSION。

1.全局變量

#查看全部的全局變量

SHOW GLOBAL VARIABLES;

#查看部分的全局變量
SHOW GLOBAL VARIABLES LIKE '%char%';

#查看指定的全局變量的值
SELECT @@global.autocommit;

#爲某個指定的全局變量賦值
SET @@global.autocommit=0;

做用域:服務器每次啓動將爲全部的全局變量賦初始值,針對於全部的會話(鏈接)有效。不能跨重啓。sql

2.會話變量

#查看全部的全局變量

SHOW 【SESSION】 VARIABLES;

#查看部分的全局變量
SHOW 【SESSION】 VARIABLES LIKE '%char%';

#查看指定的全局變量的值
SELECT @@session.tx_isolation;

#爲某個指定的全局變量賦值
SET @@session.tx_isolation='read-uncommitted';

做用域:僅僅針對於當前會話(鏈接)有效數據庫

自定義變量

說明:變量是用戶自定義的,不是由系統制定的服務器

#使用步驟
聲明
賦值
使用(查看、比較、運算等)

1.用戶變量

#(1)聲明並初始化
SET @用戶變量名=值;
SET @用戶變量名:=值;
SELECT @用戶變量名:=值;#用select只能用:=

#(2)賦值(更新用戶變量的值)
#方式一:經過SET或SELECT
    SET @用戶變量名=值;
    SET @用戶變量名:=值;
    SELECT @用戶變量名:=值;#用select只能用:=

#案例1:聲明並初始化
set @name='john';
set @name=100;

#方式二:經過SELECT INTO
SELECT 字段 INTO @變量名
FROM 表;

#案例2:賦值
SELECT COUNT(*) INTO @count
FROM employees;

#(3)使用(查看用戶變量的值)
SELECT @用戶變量名;

做用域:僅僅針對於當前會話(鏈接)有效,同於會話變量的做用域。
應用在任何地方,也便是begin end裏面或者外面。session

2.局部變量

#(1)聲明
DECLARE 變量名 類型 DEFAULT 值;

#(2)賦值
#方式一:經過SET或SELECT
    SET 局部變量名=值;
    SET局部變量名:=值;
    SELECT @局部變量名:=值;#用select只能用:=

#方式二:經過SELECT INTO
SELECT 字段 INTO 局部變量名
FROM 表;

#(3)使用
SELECT 局部變量名;

做用域:僅僅在定義它的begin end中有效
應用在begin end 中的第一句話;函數

3.對比用戶變量和局部變量

(1)用戶變量

  • 做用域:當前會話
  • 定義和使用的位置:會話中的任何地方
  • 語法:聲明的語法不一樣,用戶變量須要加上@符號,不用限定類型

(2)局部變量

  • 做用域:BEGIN END中
  • 定義和使用的位置:只能在BEGIN END中,且爲第一句話
  • 語法:聲明的語法不一樣,通常不須要加上@符號,須要限定類型
#案例1:聲明兩個變量並賦初始值,求和,並打印
    #用戶變量
    set @m=1;
    SET @n=2;
    SET @sum=@m+@n;
    select @sum;
    
    #局部變量
    DECLARE m INT DEFAULT 1;
    DECLARE n INT DEFAULT 2;
    DECLARE SUM INT;
    SET SUM=m+n;
    SELECT SUM;#會報錯,由於不在begin end中

存儲過程

含義

一組通過預先編譯的sql語句的集合,理解爲批處理語句code

好處

一、提升了sql語句的重用性,減小了開發程序員的壓力
二、簡化操做
三、減小了編譯次數而且減小了和數據庫服務器的鏈接次數,提升了效率

分類

一、無返回無參
二、僅僅帶in類型,無返回有參
三、僅僅帶out類型,有返回無參
四、既帶in又帶out,有返回有參
五、帶inout,有返回有參
注意:in、out、inout均可以在一個存儲過程當中帶多個

建立存儲過程

1.語法

create procedure 存儲過程名(in|out|inout 參數名  參數類型,...)#也叫參數列表
begin
	存儲過程體(一組合法的SQL語句)

end

2.注意

一、存儲過程體中的每條SQL語句的結尾要求必須加分號。存儲過程的結尾須要設置新的結束標記,delimiter 新的結束標記
示例:
delimiter $ #這是設置結束標記

CREATE PROCEDURE 存儲過程名(IN|OUT|INOUT 參數名  參數類型,...)
BEGIN
	sql語句1;
	sql語句2;

END $

二、存儲過程體中能夠有多條sql語句,若是僅僅一條sql語句,則能夠省略begin end

三、參數前面的符號的意思
in:該參數只能做爲輸入 (該參數不能作返回值)也就是該參數須要調用方傳入值
out:該參數只能做爲輸出(該參數只能作返回值)也就是該參數能夠做爲返回值
inout:既能作輸入又能作輸出,也就是該參數既須要傳入值,又能夠返回值

四、	參數列表包含三部分:參數模式、參數名、參數類型
舉例:IN stuname VARCHAR(20)
參數模式:IN、OUT、INOUT

調用存儲過程

call 存儲過程名(實參列表)

1. 空參列表

#案例1:插入到admin表中五條記錄

DELIMITER $
CREATE PROCEDURE myp1()
BEGIN
    INSERT INTO admin(username,PASSWORD)
    VALUES('john1','0000'),('lily','0000'),('rose','0000'),('jack','0000'),('tom','0000');
END $ #在cmd開啓MySQL裏使用

CALL myp1()$

2.建立帶in模式參數的存儲過程

#案例1:建立存儲過程實現:根據女神名,查詢對應的男神信息
DELIMITER $
create procedure myp2(IN beautyName varchar(20))#默認是IN,能夠省略
begin
	select bo.*
    from boys bo
    right join beauty b on bo.id=b.boyfriend_id
    where b.name=beautyName;
END $

call myp2('小昭')$

#案例2:建立存儲過程實現,用戶是否登錄成功
DELIMITER $
create procedure myp5(in username varchar(20),in password varchar(20))
begin
	DECLARE result int default 0;#聲明並初始化
	select count(*) into result #賦值
    from admin
    where admin.username=username
    and admin.password=password;

    select if(result>0,'成功','失敗');#使用
end $

call myp5('張飛','8888')$ #在cmd開啓MySQL裏使用

3.建立帶out模式的存儲過程

#案例1:根據女神名,返回對應的男神名
    USE girls;
    DELIMITER $
    CREATE PROCEDURE myp5(IN beautyName VARCHAR(20),OUT boyName VARCHAR(20))
    BEGIN
	    SELECT bo.boyName INTO boyName
    	FROM boys bo
	    INNER JOIN beauty b ON bo.id=b.boyfriend_id
	    WHERE b.name=beautyName;
    END $

    CALL myp5('小昭',@bName)$
    SELECT @bName$

#案例2:根據女神名,返回對應的男神名和男神魅力值
DELIMITER $
CREATE PROCEDURE myp7(IN beautyName VARCHAR(20),OUT boyName VARCHAR(20),OUT usercp INT) 
BEGIN
	SELECT boys.boyname ,boys.usercp INTO boyname,usercp
	FROM boys 
	RIGHT JOIN
	beauty b ON b.boyfriend_id = boys.id
	WHERE b.name=beautyName ;
	
END $


#調用
CALL myp7('小昭',@name,@cp)$
SELECT @name,@cp$

4.建立帶inout模式參數的存儲過程

#案例1:傳入a和b兩個值,最終a和b都翻倍並返回
DELIMITER $
CREATE PROCEDURE myp8(INOUT a INT ,INOUT b INT)
BEGIN
	SET a=a*2;
	SET b=b*2;
END $

SET @m=10$
SET @n=20$
CALL myp8(@m,@n)$
SELECT @m,@n$

案例分析

#案例1:建立存儲過程或函數實現傳入用戶名和密碼,插入到admin表中
DELIMITER $
CREATE PROCEDURE test_pro1(IN username VARCHAR(20),loginpwd VARCHAR(20))
BEGIN
	INSERT INTO admin(admin.username,PASSWORD)
	VALUE(username,loginpwd);
END $

CALL test_pro1('admin','0000')$

SELECT *
FROM admin$

    
#案例2:建立存儲過程或函數實現傳入女神編號,返回女神名稱和女神電話
DELIMITER $
CREATE PROCEDURE test_pro2(IN id INT,OUT NAME VARCHAR(20),OUT phone VARCHAR(20))
BEGIN
    SELECT b.name,b.phone INTO NAME,phone
    FROM beauty b
    WHERE b.id=id;

END$

CALL test_pro2(1,@m,@n)$
SELECT @m,@n$
    
#案例3:建立存儲過程或函數實現傳入兩個女神生日,返回大小
 
CREATE PROCEDURE test_pro3(IN birth1 DATETIME,IN birth2 DATETIME,OUT result INT)
BEGIN
	SELECT DATEDIFF (birth1,birth2) INTO result;
	
END $

CALL test_pro3('1998-1-1',NOW(),@result)$
SELECT @result$

#案例4:建立存儲過程或函數實現傳入一個日期,格式化成xx年xx月xx日並返回

DELIMITER $ 
CREATE PROCEDURE test_pro4(IN mydate DATETIME ,OUT strdate VARCHAR(50))
BEGIN 
	SELECT DATE_FORMAT(mydate,'%y年%m月%d日') INTO strdate;
END $

CALL test_pro4(NOW(),@str)$
SELECT @str$

#案例5:建立存儲過程或函數實現傳入女生名稱,返回:女神 AND 男神 格式的字符串
#如 傳入:小昭,返回:小昭 AND 張無忌
DELIMITER $ 
CREATE PROCEDURE test_pro5(IN beautyname VARCHAR(20) ,OUT str VARCHAR(50))
BEGIN 
	SELECT CONCAT(beautyname,'and' ,IFNULL(boyname,'null') )INTO str
	FROM boys bo
	RIGHT JOIN beauty b ON b.boyfriend_id=bo.id
	WHERE b.name=beautyname;
END $

CALL test_pro5('柳巖',@str)$
SELECT @str$

#案例6:建立存儲過程或函數,根據傳入的條目數和起始索引,查詢beauty表的記錄
DELIMITER $ 
CREATE PROCEDURE test_pro6(IN size INT ,IN startindex INT)
BEGIN 
	SELECT *
	FROM beauty 
	LIMIT startindex,size;
END $

CALL test_pro6(3,5)$

刪除存儲過程

#語法
DROP PROCEDURE 存儲過程名 #一次只能刪除一個

##查看存儲過程的信息
SHOW CREATE PROCEDURE 存儲過程名;

函數

含義

一組預先編譯好的SQL語句的集合,理解成批處理語句索引

好處

一、提升了sql語句的重用性,減小了開發程序員的壓力
二、簡化操做
三、減小了編譯次數而且減小了和數據庫服務器的鏈接次數,提升了效率

函數與存儲過程的區別

1.存儲過程

  • 能夠有0個返回,也能夠有多個返回
  • 適合作批量插入、批量更新(增刪改)

2.函數

  • 有且僅有有1個返回
  • 適合作處理數據後返回一個結果

建立函數

學過的函數:LENGTH、SUBSTR、CONCAT等作用域

#語法
CREATE FUNCTION 函數名(參數名 參數類型,...) RETURNS 返回類型
BEGIN
	函數體
	
END

注意

  • 參數列表包含兩部分:參數名、參數類型
  • 函數體:確定會有return語句,若是沒有會報錯。若是return沒有放在函數體的最後也不會報錯,但不建議。
  • 當函數體中僅有一句話,能夠省略begin end
  • 使用delimiter語句設置結束標記(DELIMITER $ ;是錯誤的)

調用函數

SELECT 函數名(實參列表)

函數案例演示

1.無參有返回

#案例1:返回公司的員工個數
set global log_bin_trust_function_creators=1;#若是語法沒問題仍是報錯,加上這條語句

DELIMITER $ 
CREATE FUNCTION myf1() RETURNS INT
BEGIN
	DECLARE c INT DEFAULT 0; #定義變量
	SELECT COUNT(*) INTO c #賦值
	FROM employees;
	RETURN c;
END$

SELECT myf1()$
SELECT myf1()$

2.有參返回

#案例1:根據員工名,返回它的工資(題外話:笑死,老師用的是‘它’)
DELIMITER $ 
create function myf2(empname varchar(20)) returns double
begin
	set @sal=0;#定義一個用戶變量
	select salary into @sal #賦值
	from employees
	where last_name=empname;
	return @sal;
end$

select myf2('kochhar')$

#案例2:根據部門名,返回該部門的平均工資
DELIMITER $ 
CREATE FUNCTION myf3(deptname VARCHAR(20)) RETURNS DOUBLE #double是浮點型
BEGIN
	DECLARE sal DOUBLE;#定義一個局部變量,double是浮點型
	SELECT AVG(salary)INTO sal #賦值
	FROM employees e
	JOIN departments d ON e.department_id=d.department_id
	WHERE d.department_name=deptname;
	RETURN sal;
END$

SELECT myf3('IT')$

查看函數

SHOW CREATE FUNCTION myf3;

刪除函數

DROP FUNCTION myf3;

案例綜合分析

#案例1:建立函數,實現傳入兩個float,返回兩者之和。
DELIMITER $ 
CREATE FUNCTION test_fun1(num1 FLOAT,num2 FLOAT) RETURNS FLOAT #不要忘記是returns不是return
BEGIN
	DECLARE SUM FLOAT DEFAULT 0;
	SET SUM=num1+num2;
	RETURN SUM;
END$

SELECT test_fun1(1,2)$
相關文章
相關標籤/搜索