1. 程式人生 > >MYSQL中的function、trigger、儲存過程使用實踐

MYSQL中的function、trigger、儲存過程使用實踐

FUNCTION

就是建立一個函式,裡面寫上自己的邏輯,然後返回處理的結果

我們建立一個僱員表employees

create table employees  
(  
    employee_id int(11) primary key not null auto_increment,  
    employee_name varchar(50) not null,  
    employee_sex varchar(10) default '男',  
    hire_date datetime not null default current_timestamp,  
    employee_mgr int(11),  
    employee_salary float default 3000,  
    department_id int(11)  
);  

insert into employees(employee_name,employee_sex,employee_mgr,employee_salary,department_id) values ('David Tian','1',10,7500,1);  
insert into employees(employee_name,employee_sex,employee_mgr,employee_salary,department_id) values ('Black Xie','1',10,6600,1);  
insert into employees(employee_name,employee_sex,employee_mgr,employee_salary,department_id) values ('Moses Wang','1',10,4300,1);  
insert into employees(employee_name,employee_sex,employee_mgr,employee_salary,department_id) values ('Rena Ruan','0',10,5300,1);  
insert into employees(employee_name,employee_sex,employee_mgr,employee_salary,department_id) values ('Sunshine Ma','0',10,6500,2);  
insert into employees(employee_name,employee_sex,employee_mgr,employee_salary,department_id) values ('Scott Gao','1',10,9500,2);  
insert into employees(employee_name,employee_sex,employee_mgr,employee_salary,department_id) values ('Warren Si','1',10,7800,2);  
insert into employees(employee_name,employee_sex,employee_mgr,employee_salary,department_id) values ('Kaishen Yang','1',10,9500,3);  
insert into employees(employee_name,employee_sex,employee_mgr,employee_salary,department_id) values ('Simon Song','1',10,5500,3);  
insert into employees(employee_name,employee_sex,employee_mgr,employee_salary,department_id) values ('Brown Guan','1',10,5000,3);  
insert into employees(employee_name,employee_sex,employee_mgr,employee_salary,department_id) values ('Eleven Chen','0',10,3500,2);  
insert into employees(employee_name,employee_sex,employee_mgr,employee_salary,department_id) values ('Cherry Zhou','0',10,5500,4);  
insert into employees(employee_name,employee_sex,employee_mgr,employee_salary,department_id) values ('Klause He','1',10,4500,5);  
insert into employees(employee_name,employee_sex,employee_mgr,employee_salary,department_id) values ('Maven Ma','1',10,4500,6);  
insert into employees(employee_name,employee_sex,employee_mgr,employee_salary,department_id) values ('Stephani Wang','0',10,5500,7);  
insert into employees(employee_name,employee_sex,employee_mgr,employee_salary,department_id) values ('Jerry Guo','1',10,8500,1);  
insert into employees(employee_name,employee_sex,employee_mgr,employee_salary,department_id) values ('Gerardo Garza','1',10,25000,8);  
insert into employees(employee_name,employee_sex,employee_mgr,employee_salary,department_id) values ('Derek Wu','1',10,5500,5);  
  
  
select * from employees;  

寫一個根據id查詢僱員工資的函式

CREATE FUNCTION getInfoById (id INT) RETURNS VARCHAR (300)
BEGIN
	RETURN (
		SELECT
			CONCAT(
				'employee name:',
				employee_name,
				'---',
				'salary: ',
				employee_salary
			)
		FROM
			employees
		WHERE
			employee_id = id
	);


END

在NavicatForMySQL裡面執行下

可以看到我們在mysql裡面已經建立好了一個函式,在NavicatForMySQL也可以看到

然後呼叫下,試試效果

Procedure

儲存過程,和函式功能差不多,但是相對功能更強大,限制更少

本質上沒區別。只是函式有如:只能返回一個變數的限制。而儲存過程可以返回多個。

而函式是可以嵌入在sql中使用的,可以在select中呼叫,而儲存過程不行。

執行的本質都一樣。 
     函式限制比較多,比如不能用臨時表,只能用表變數.

  還有一些函式都不可用等等.而儲存過程的限制相對就比較少 
 

    1.    一般來說,儲存過程實現的功能要複雜一點,而函式的實現的功能針對性比較強。 
      2.    對於儲存過程來說可以返回引數,而函式只能返回值或者表物件。 
      3.    儲存過程一般是作為一個獨立的部分來執行(EXEC執行),

    而函式可以作為查詢語句的一個部分來呼叫(SELECT呼叫),由於函式可以返回一個表物件,

    因此它可以在查詢語句中位於FROM關鍵字的後面。 
      4.    當儲存過程和函式被執行的時候,SQL Manager會到procedure cache中去取相應的查詢語句,如果在procedure cache裡沒有相應的查詢語句,SQL Manager就會對儲存過程和函式進行編譯。 
      Procedure cache中儲存的是執行計劃 (execution plan) ,當編譯好之後就執行procedure cache中的execution plan,之後SQL SERVER會根據每個execution plan的實際情況來考慮是否要在cache中儲存這個plan,評判的標準一個是這個execution plan可能被使用的頻率;其次是生成這個plan的代價,也就是編譯的耗時。儲存在cache中的plan在下次執行時就不用再編譯了。

-- 下面是儲存過程
DELIMITER //
CREATE PROCEDURE proc_select_teacher_info(in id int)
BEGIN
 select * from Teacher where Tid=id;
END;
//
call proc_select_teacher_info(1)

-- 下面是函式呼叫
CREATE FUNCTION getTeacherById (id INT) RETURNS VARCHAR (300)
BEGIN
	RETURN (
		SELECT
			CONCAT('teacher', tname)
		FROM
			teacher
		WHERE
			tid = id
	);
END
select getTeacherById(1);

兩個都可以實現查詢教師的功能

查詢老師的數量並輸出到out引數裡面

create PROCEDURE proc_get_teacher_count(out n int)
BEGIN
select count(*) from teacher;
END
call proc_get_teacher_count(@n)

將學生id為1的年齡加以並放入inout

create procedure update_student_age(in id int,inout num int)
BEGIN
select age into num from student where sid=id;
set num:=num+1;
select num;
END

 call update_student_age(1,@num)

該學生本來年齡為10的,結果修改後,結果是11

Trigger

trigger 就是觸發器,聯想一下網頁介面的按鈕監聽事件

一個道理,但是觸發器不能經常用,因為每次操作一行資料都會觸發這個監聽事件,確實挺浪費的。

下面是語法

CREATE TRIGGER 觸發器名 BEFORE|AFTER 觸發事件
ON 表名 FOR EACH ROW
BEGIN
    執行語句列表
END

 根據以上的表格,可以使用一下格式來使用相應的資料:

NEW.columnname:新增行的某列資料
OLD.columnname:刪除行的某列資料

我們針對於上面的僱員表建立一個插入的觸發器,每次插入都會在操作日誌裡面插入當前僱員的名字和操作時間

操作日誌表oplogs的表結構如下:

create trigger insert_trigger AFTER INSERT ON employees FOR EACH ROW
BEGIN
DECLARE s1 VARCHAR(40)character set utf8;
DECLARE s2 VARCHAR(20) character set utf8;
SET s2 = ' is created';
SET s1 = CONCAT(NEW.employee_name,s2);
INSERT into oplogs(optype,time) VALUES(s1,NOW());
END

然後我們插入一條資料

insert into employees(employee_name,employee_sex,employee_mgr,employee_salary,department_id) values ('meinv','0',10,2300,1);  

然後我們去操作日誌看下,觸發器已經自動觸發,並在操作日誌表插入了一條新的資料