(三)mysql 觸發器、存儲過程和函數(數據庫運維基礎補充)

CONTEND

一、MySQL觸發器Triggers

1.1 觸發器簡介

1.2 創建觸發器

1.3 觸發器的管理(查看,刪除)

二、mysql存儲過程procedure和函數function

2.1 procedure和function概述:

2.2 創建與調用存儲過程

2.3 創建函數

2.4 存儲過程和函數的維護


一、MySQL觸發器Triggers


1.1 觸發器簡介

        觸發器( trigger )是一個特殊的存儲過程,它的執行不是由程序調用,也不是手工啓動,而是由事件來觸發,比如當對一個表進行操作(  insert , delete,update )時就會激活它執行。觸發器經常用於加強數據的完整性約束和業務規則等。
        例如,當學生表中增加了一個學生的信息時,學生的總數就應該同時改變。因此可以針對學生表創建一個觸發器,每次增加一個學生記錄時,就執行 一次學生總數的計算操作,從而保證學生總數與記錄數的一致性。

1.2 創建觸發器


(1)先舉個簡單的示例幫助我們理解這個觸發器:創建兩個表student和student_total,表student每次插入一個學生數據或刪除學生數據,student_total作相應的修改:

--創建表並插入數據
create table student ( id int unsigned auto_increment primary key not null, name varchar(50) not null, age int not null default 18);

create table student_total ( total_num int );

insert into student_total value(0);
--下面開始創建觸發器,針對insert操作
delimiter $
create trigger stu_insert after insert on student for each row begin update student_total set total_num=total_num+1; end$

--針對delete操作
create trigger stu_delete after delete on student for each row begin update student_total set total_num=total_num-1; end$
--把分隔符修改回來然後開始插入,刪除測試下
delimiter ;
insert into student(name) values ('alice'),('bob');
select * from student_total;
+-----------+
| total_num |
+-----------+
|         2 |
+-----------+

delete from student where name='alice';
select * from student_total;
+-----------+
| total_num |
+-----------+
|         1 |
+-----------+

(2) 進階一下,創建tab1和tab2,創建觸發器(insert、delete和update)接着插入、刪除更新數據試試

create table tab1(id int auto_increment primary key,name varchar(50) not null, sex enum('male','female') default 'male' , age int not null);

create table tab2( id int primary key auto_increment, name varchar(50), salary double(10,2) default 5000);

這邊要強調一點,當你刪除或者更新的時候,後面一定跟的是主鍵。比如id就是主鍵,否則會造成一些問題如誤刪數據等,這個要謹慎! (還有刪除後面跟的是主鍵就可以了,但更新的話要設置所有的字段都更新哦)

create trigger tab1_insert after insert on tab1 for each row begin  insert into tab2 values (new.id,new.name,5000); end$

create trigger tab1_delete after delete on tab1 for each row begin  delete from tab2 where id=old.id; end$

create trigger tab1_update after update on tab1 for each row begin  update tab2 set id=new.id,name=new.name where id=old.id; end$
insert into tab1 values (1,'alice','male',19),(2,'bob','male',20),(4,'Gwen','female',23);

select * from tab1;
+----+-------+--------+-----+
| id | name  | sex    | age |
+----+-------+--------+-----+
|  1 | alice | male   |  19 |
|  2 | bob   | male   |  20 |
|  4 | Gwen  | female |  23 |
+----+-------+--------+-----+

select * from tab2;
+----+-------+---------+
| id | name  | salary  |
+----+-------+---------+
|  1 | alice | 5000.00 |
|  2 | bob   | 5000.00 |
|  4 | Gwen  | 5000.00 |
+----+-------+---------+

delete from tab1 where id=4;

select * from tab2;
+----+-------+---------+
| id | name  | salary  |
+----+-------+---------+
|  1 | alice | 5000.00 |
|  2 | bob   | 5000.00 |
+----+-------+---------+

update tab1 set name='aliceCC' where id =1;
select * from tab2;
+----+---------+---------+
| id | name    | salary  |
+----+---------+---------+
|  1 | aliceCC | 5000.00 |
|  2 | bob     | 5000.00 |
+----+---------+---------+

 

(3)再來一個示例,幫助我們再進一步去理解這個觸發器。創建 t1和t2 表,如下:

create table t1 (id int auto_increment primary key, name varchar(50), salary double(10,2));
create table t2(
    -> total_num int not null,
    -> total_salary double(10,2));

insert into t2 values(0,0);
select * from t2;
+-----------+--------------+
| total_num | total_salary |
+-----------+--------------+
|         0 |         0.00 |
+-----------+--------------+
delimiter $
create trigger total_num_salary  after insert on t1  for each row begin update t2 set total_num=total_num+1,total_salary=total_salary+new.salary;end$

create trigger total_num_salary2  after delete on t1  for each row begin  update t2 set total_num=total_num-1,total_salary=total_salary-old.salary; end$

delimiter ;
 insert into t1(name,salary) values 
    -> ('alice',6000),
    -> ('bob',6500),
    -> ('jack',10000);

 select * from t2;
+-----------+--------------+
| total_num | total_salary |
+-----------+--------------+
|         3 |     22500.00 |
+-----------+--------------+

delete from t1 where name='jack';
select * from t2;
+-----------+--------------+
| total_num | total_salary |
+-----------+--------------+
|         2 |     12500.00 |
+-----------+--------------+

 

1.3 觸發器的管理(查看,刪除)

這個比較簡單,記住語法格式就好了。

  • 查看操作

  • 刪除操作

 

二、mysql存儲過程procedure和函數function

2.1 procedure和function概述:

存儲過程和函數是事先經過編譯並存儲在數據庫中的一段SQL語句的集合
存儲過程和函數的區別:

  • 函數必須有返回值,而存儲過程沒有
  • 存儲過程的參數可以是IN、OUT、INOUT類型,函數的參數只能是IN

優點:

  • 存儲過程只在創建時進行編譯;而SQL語句每執行一次就編譯一次,所以使用存儲過程可以提高數據庫執行速度。
  • 簡化複雜操作,結合事務一起封裝。
  • 複用性好
  • 安全性高,可指定存儲過程的使用權。

說明:

  • 併發量少的情況下,很少使用存儲過程。
  • 併發量高的情況下,爲了提高效率,用存儲過程比較多。
     

2.2、創建與調用存儲過程

創建存儲過程語法:下面舉出一些簡單的例子

(1)無參數的形式

前面我就利用了存儲過程批量插入數據,在回顧下,只是我們沒有利用參數傳遞,那就很不靈活了,如果下次插入1000條呢?

#下面這就是創建存儲過程,實現批量插入數據,這個後面我會寫博客介紹的,在這裏就是實現批量插入數據的功能
create procedure autoinsert() 
begin 
declare i int default 1;
while(i<200000)do  
 insert into company.t1 values(i,'ggg');   
 set i=i+1; 
end while; 
end$$
 
delimiter ;   #把分隔符修改回來
call autoinsert(); #執行這個函數,開始插入數據

(2)參數形式:IN,利用它可以傳入參數方便之後修改,變得靈活!重新看一個例子。md5()是個函數,計算哈希值的。

delimiter $$
create procedure autoinsert3(IN a int)
    -> begin
    ->  declare i int default 1;
    ->  while(i<=a)do
    ->   insert into student.autoinsert values(i,md5(i));
    ->   set i=i+1;
    -> end while;
    -> end$$

delimiter ;
call autoinsert3(10);
select * from autoinsert;
+------+----------------------------------+
| id   | name                             |
+------+----------------------------------+
|    1 | c4ca4238a0b923820dcc509a6f75849b |
|    2 | c81e728d9d4c2f636f067f89cc14862c |
|    3 | eccbc87e4b5ce2fe28308fd9f2a7baf3 |
|    4 | a87ff679a2f3e71d9181a67b7542122c |
|    5 | e4da3b7fbbce2345d7772b0674a318d5 |
|    6 | 1679091c5a880faf6fb5e6087eb1b2dc |
|    7 | 8f14e45fceea167a5a36dedd4bea2543 |
|    8 | c9f0f895fb98ab9159f51fd0297e236d |
|    9 | 45c48cce2e2d7fbdea1afc51c7c6ad26 |
|   10 | d3d9446802a44259755d38e6d163e820 |
+------+----------------------------------+

(3)out 用法參例:

delimiter $$
create procedure p2 (out param1 int)      --創建存儲過程
    -> begin
    ->  select count(*) into param1 from mysql.user;
    -> end$$

delimiter ;
select @a;  --查看a變量是否爲空,爲空後面讓它傳參

call p2(@a);  --調用參數

select @a;   --可以直接用變量查詢和後面的select語句是一樣的
+------+
| @a   |
+------+
|    4 |
+------+

select count(*)  from mysql.user;
+----------+
| count(*) |
+----------+
|        4 |
+----------+

(4)in和out同時用,參例如下:

#統計指定部門的員工數
mysql> delimiter $$
mysql> create procedure count_num(in p1 varchar(50),out p2 int)
    -> begin
    ->  select count(*) into p2 from company.employee
    ->    where post=p1;
    -> end$$

mysql> delimiter ;
mysql> call count_num('sale',@b);
mysql> select @b;
+------+
| @b   |
+------+
|    4 |
+------+

#統計指定部門工資超過例如2000的總人數
mysql> delimiter $$
mysql> create procedure count_num1(in p1 varchar(50),in p2 float(10,2),out p3 int)
    ->  begin
    -> select count(*) into p3 from company.employee 
    -> where post=p1 and salary>=p2;
    -> end$$

mysql> call count_num1('hr',2000,@c)$$
mysql> select @C$$
+------+
| @C   |
+------+
|    1 |
+------+

(5)inout參例

create procedure inout_test(inout p1 int)  begin   if(p1 is not null)then      set p1=p1+1;    else      set p1=100; end if; end$$

call inout_test(@e)$$
select(@e)$$
+------+
| (@e) |
+------+
|  100 |
+------+
call inout_test(@e)$$
select(@e)$$
+------+
| (@e) |
+------+
|  101 |
+------+

2.3 創建函數

在我創建函數的時候出現以下錯誤,百度了下修改下就可以了

ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)

set global log_bin_trust_function_creators=TRUE;

參例: 


create function name_from_emp(a int) returns varchar(50) begin  return(select name from employee    where id=a); end$$

select name_from_emp(5)$$
+------------------+
| name_from_emp(5) |
+------------------+
| jack             |
+------------------+
select * from employee where name=name_from_emp(5)$$ --查看全部信息也可調用這個函數
+----+------+------+------------+------------+-----------------+---------+--------+--------+
| id | name | sex  | hire_date  | post       | job_description | salary  | office | dep_id |
+----+------+------+------------+------------+-----------------+---------+--------+--------+
|  5 | jack | male | 2018-02-02 | instructor | teach           | 5000.00 |    501 |    100 |
+----+------+------+------------+------------+-----------------+---------+--------+--------

 

2.4 存儲過程和函數的維護

這個和之前的table,index等差不多,如下:

 在創建存儲過程的時候,多了變量這個概念,mysql變量的術語一般用得着是用戶變量和全局變量:
1.用戶變量:以"@"開始,形式爲"@變量名",由客戶端定義的變量。
用戶變量跟mysq|客戶端是綁定的, 設置的變量只對當前用戶使用的客戶端生效,當用戶斷開連接自動釋放。
2.全局變量:定義時如下兩種形式, set GLOBAL變量名或者set @@global.變量名
對所有客戶端生效,但只有具有super管理員的權限纔可以設置全局變量。
這個做個瞭解,後面還會用的着的。

 

 

 

 

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