存储过程与触发器

很开心我今天又开设了一个新的专题,那就是数据库,俗话说不想当dba的程序员不是一个好前端。。。我这里不是mysql入门讲堂,讲的都是有一定基础的东西。

1 存储过程

话不多说,咱们举个例子简单了解下。



这是一张学生表,含有3个数据。

DROP PROCEDURE if EXISTS Proc;

DELIMITER //
CREATE PROCEDURE Proc()
BEGIN
   SELECT * FROM student;
END// 
DELIMITER ;

CALL Proc();

我们通过CREATE PROCEDURE创建了一个存储过程Proc,语句是查询student表内容,调用通过call,返回内容就是表的数据。

DROP PROCEDURE if EXISTS Proc;

DELIMITER //
CREATE PROCEDURE Proc(IN id INT)
BEGIN
   SELECT * FROM student WHERE age > id;
END// 
DELIMITER ;

CALL Proc(23);

我们将这个存储过程改为了查询年龄大雨23岁的。

其实到这里大概也知道了,存储过程到底是干嘛的,其实就是编写一个函数让我们可以更轻松的拿取我们想要的数据。

DROP PROCEDURE if EXISTS Proc;

DELIMITER //
CREATE PROCEDURE Proc(IN id INT ,OUT count INT)
BEGIN
  SELECT count(*) into count FROM student WHERE age > id;
END// 
DELIMITER ;

CALL Proc(21,@count);
select @count;

这个存储过程里面🈶️个参数,一个输出,一个输入,注意输出用@,count最后代表的是大于21的人个数。

我们现在有个需求就是往这个student表里添加10个学生,我们这次是使用存储过程来做的。

DELIMITER $$
DROP PROCEDURE IF EXISTS `addStudent` $$
CREATE PROCEDURE addStudent( IN studentCount INT ) 
BEGIN 
    DECLARE i INT DEFAULT 0;                  -- 计数器
    DECLARE returnMsg VARCHAR(50) DEFAULT '';   -- 返回值信息
    DECLARE rowCount int DEFAULT 0;             -- 操作sql的时候影响行数
    
      outer_label:BEGIN
      START TRANSACTION;
      WHILE i < studentCount DO
        SET i=i+1;
        INSERT INTO `student`   (`name`,`age`) VALUES ('****',i+1);
        SELECT row_count() INTO rowCount;
        IF rowCount<=0 THEN
            LEAVE outer_label;            
        END IF;                 
      END WHILE;

      END outer_label;  -- 只要是在outer_label代码块内 任意位置 Leave outer_label,那么Leave后的代码将不再执行 

      IF i=studentCount THEN
        COMMIT;
        SET returnMsg = i;
          ELSE
        ROLLBACK;
        SET returnMsg = 'error';
         END IF;
      SELECT returnMsg;
   
END $$
DELIMITER ;

其实这就是在mysql里面写了一回js代码,注意while和if的用法即可。通过addStudent(10)插入10条数据。

上面的例子比较综合,咱们以一个简单例子结尾。

DELIMITER //  
CREATE PROCEDURE proc1 (IN parameter1 INTEGER)   
BEGIN   
    DECLARE variable1 CHAR(10);   
    IF parameter1 = 17 THEN   
        SET variable1 = 'birds';   
        ELSE 
        SET variable1 = 'beasts';   
    END IF;   
INSERT INTO table1 VALUES (variable1);  
END //  
DELIMITER ;

在存储过程间传递全局范围的用户变量

1.  mysql> CREATE PROCEDURE p1()   SET @last_procedure='p1';  
2.  mysql> CREATE PROCEDURE p2() SELECT CONCAT('Last procedure was ',@last_procedure);  
3.  mysql> CALL p1( );  
4.  mysql> CALL p2( );  
5.  +-----------------------------------------------+  
6.  | CONCAT('Last procedure was ',@last_proc       |  
7.  +-----------------------------------------------+  
8.  | Last procedure was p1                         |  
9.  +-----------------------------------------------+

查看当前数据库的存储过程:

show procedure status;

来看这段代码

DROP PROCEDURE IF EXISTS proc3;
DELIMITER //  
CREATE PROCEDURE proc3()  
  begin 
    declare x1 varchar(5) default 'outer';  
    begin 
    declare x1 varchar(5) default 'inner';  
    select x1 as qwe;
    end;  
    select x1 as qwe;
  end //  
DELIMITER ;

CALL proc3();

此时显示的是x1=inner...

一个简单的流程控制的存储过程

drop procedure if exists proc4;
DELIMITER //  
CREATE PROCEDURE proc4 (in parameter INT)  
  begin 
    declare var int;  
    declare asd int;
    set var=parameter+1;  
    case var  
        when 0 then  
          set asd = 11; 
          select asd as qwe;  
        when 1 then 
          set asd = 12;   
          select asd as qwe;  
        else   
          set asd = 13; 
          select asd as qwe;  
    end case;  
  end //  
DELIMITER ;

call proc4(0);

存储过程的概念其实很简单,但是想要写出很好的存储过程需要一定的coding skill,大家可以慢慢学习。。

2 触发器

触发器是一个特殊的存储过程,不同的是存储过程要用CALL来调用,而触发器不需要使用CALL,也不需要手工启动,只要当一个预定义的事件发生的时候,就会被MYSQL自动调用。

drop trigger ins_sum
SET @qqq=0;
CREATE TABLE account2(acct_num INT ,amount INT);
CREATE TRIGGER ins_sum BEFORE INSERT ON account2
FOR EACH ROW SET @qqq=@qqq+new.amount;

INSERT INTO account2 VALUES(1,3),(2,5);
SELECT @qqq as qwe;

这个触发器的意思是说每次往account2里面插入数据时,更改@qqq的值,注意new是值的插入的那一行。

触发器中new和old的作用

  • 针对update操作,new表示的是更新后的值,old表示的是原来的数据。
  • 针对insert操作,new表示的是插入的值。
  • 针对delete操作,old表示的是删除后的值。
    本例子是insert,操作是before。

关于mysql变量定义可以看这篇文章.

创建有多个执行语句的触发器,语法如下:

DELIMITER |
 
CREATE TRIGGER testref BEFORE INSERT ON test1
  FOR EACH ROW BEGIN
    INSERT INTO test2 SET a2 = NEW.a1;
    DELETE FROM test3 WHERE a3 = NEW.a1;  
    UPDATE test4 SET b4 = b4 + 1 WHERE a4 = NEW.a1;
  END
|

一次插入操作导致3个表发生变化。。。

我们来考虑一个更为实际的问题,有一张表记录着我进货水果详细,还有一张表是对我进货水果种类的统计,此时我进货了10个apple回来,那么这2张表该如何变化。

CREATE TRIGGER FRUIT BEFORE INSERT ON FRUIT_DETAIL
     FOR EACH ROW BEGIN
              UPDATE FRUIT_STATISTIC SET COUNT = COUNT + NEW.IN_NUM         
              WHERE FRUIT_NAME = NEW.NAME
END

上面这个就表示了这个过程。

下面这个例子表示了一个删除的触发器

-- 删除触发器
mysql> delimiter $$
mysql> create trigger tab1_delete_after after delete
    -> on tab1 for each rows
    -> BEGIN
    ->   delete from tab2 where tab2_id = old.tab1_id;
    -> END
    -> $$
Query OK, 0 rows affected (0.01 sec)

delete from tab1 where tab1_id = 12
mysql> delimiter ;

注意这里我们用的是old,删除时就使用old。

下面这个例子表示了一个更改的触发器

-- 更新学生表的同时也更新记录表
delimiter $$
mysql> create trigger student1_update_after after update
    -> on student1 for each row
    -> BEGIN
    ->  if new.student_id != old.student_id then
    ->   update update_student1 set student_id = new.student_id, update_date = now()
    ->   where student_id = old.student_id;
    ->  end if;
    -> END
    -> $$
delimiter ;

update student1 set student_id = 23 where name = 小明

我们把名为小明的学生学号给改了。。。那么这时候会在学生记录表也作出变更。

今天的讲解就到这里,相信大家觉得这些对比后台代码还是很简单的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容