这里主要贴一下自定义函数.

在数据库操作中, 特别是超出一些头晕目眩一些的种类, 不可防止的,
会用到函数/自定义函数, 大概存储进程. 

实际上项目中, 自定义函数和仓库储存进程是越少越好, 因为这几个事物多了,
也是三个相当不便保障的地点. 

生机勃勃、自定义函数

  1. 例子

mysql提供的函数, 不在这里意气风发篇讲了, 这里最首要贴一下自定义函数.
 前台js插件里面有一个zTree,
不明白咱们知不知道道, 效果是那样的:

图片 1

这种布局的数目, 在数据库中, 小编通常会规划到叁个表中

create table ztree
(
    id int(11) not null PRIMARY key auto_increment,
    name varchar(20) not null comment '节点名称',
    pid int(11) not null comment '父节点id'
) comment '树形表';

然后插入数据:

图片 2

生龙活虎经你拿到叁个节点A,
想要获取A上边包车型地铁节点(不只是子节点哦), 那么通过二个自定义函数来做,
能平价大多.

delimiter $
DROP FUNCTIONIF EXISTS GetChildNodes ;
CREATE FUNCTION `GetChildNodes` (`rootId` INT) RETURNS VARCHAR (1000)
BEGIN
    DECLARE res VARCHAR (1000) DEFAULT '-1'; 
    DECLARE temp VARCHAR (1000) DEFAULT CAST(rootId AS CHAR);
    -- SET res = '' ;
    -- SET DECLARE = CAST(rootId AS CHAR) ;
    WHILE temp IS NOT NULL DO

        SET res = CONCAT(res, ',', temp) ; 

        SELECT GROUP_CONCAT(id) INTO temp FROM ztree WHERE FIND_IN_SET(pid, temp) > 0 ;

    END WHILE ; 
    RETURN res ;
    END$
delimiter ;

 这里, 作者将res的值默认为-1, 那样的话, 就能够在查询的时候,
将以此结果拼入sql中, 依然比较便利的. 

mysql中, 自定义函数的调用, 使用 select, 接下来, 就看一下事先的成果:

SELECT GetChildNodes (2);

图片 3

 

  1. 语法

自定义函数与仓库储存进程有八个很精晓之处, 正是, 自定义函数是有重返值的,
而且需求经过return的主意重返. 而存款和储蓄进度未有return重返值. 不过,
程序在施行存款和储蓄进度的时候, 其实是足以获取叁个结出集的.

这里主要贴一下自定义函数.。语法:

  create function 函数名 (参数名 参数类型) returns 参数类型

  begin

  return result;

这里主要贴一下自定义函数.。  end

 1) 自定义函数字传送参加存款和储蓄进度分歧, 无需钦命 in/out. 

这里主要贴一下自定义函数.。 2) 自定义函数能够用到别的sql语句中, 能够独自使用,
也能够混入别的sql中选择

 

二、存款和储蓄进度

既然如在此以前边已经讲了自定义函数的语法, 这这里就先上存储进程的语法, 以便相比

  1. 语法

这里主要贴一下自定义函数.。  CREATE PROCEDURE 存款和储蓄进程名称 (IN 参数名 参数类型, OUT 参数名
参数类型)

  begin

  end

此地的参数都以非必得的, 能够有 IN/OUT 都以足以未有的

从语法格式上看, 与自定义函数的框架大概是同风姿浪漫的, 只是里面包车型地铁细节区别.

1) 存储进度未有return重临值, 可是却得以因此OUT的方法, 来改良传入的参数,
能够看作是豆蔻年华种重回值, 

2) 存储进度在end在此以前, 能够加上一句 select语句, 以便程序读取到结果集.
所以存款和储蓄进度能回去的值其实越来越多

3) 并无法混入其他sql中动用, 只可以因而 call 的法子, 单独行使

 

  1. 例子

事先的等级次序中, 小编赶过一个生成流水号的功效. 那个时候,
笔者是通过依赖数据库的章程, 来生成流水号的. 

笔者这里的流水号, 由前缀, 时间, 流水码 三部分组成

先建一张流水号表

CREATE TABLE `serialno` (
  `Id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Id',
  `Pre` varchar(10) NOT NULL COMMENT '编号',
  `Description` varchar(10) DEFAULT NULL COMMENT '说明',
  `Res` varchar(20) DEFAULT NULL COMMENT '流水号(不加编号的)',
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='流水号表'

有了这张表, 就能够起来储存进度了.

delimiter $
drop PROCEDURE if EXISTS p_GetSerialNo;
CREATE PROCEDURE `p_GetSerialNo`(IN preValue VARCHAR(10), IN preDate VARCHAR(10),IN des varchar(20), in length int)
BEGIN
    DECLARE  t_error INT DEFAULT 0;
    DECLARE  resValue VARCHAR(20) DEFAULT NULL;
    -- DECLARE
    --     CONTINUE HANDLER FOR SQLEXCEPTION,
    --     SQLWARNING,
    --     NOT FOUND
    -- SET t_error = 1;

    START TRANSACTION;

    SELECT Res INTO resValue FROM serialno WHERE Pre=preValue;
    IF resValue IS NULL  THEN
        SET resValue= CONCAT(preDate, LPAD(1, length, '0'));
        INSERT INTO serialno (Pre, Description, Res) VALUES (preValue, des, resValue);
    ELSE
        IF preDate =  (SUBSTRING(resValue,1,8) + '0') THEN
            SET resValue = CAST(resValue AS SIGNED) + 1;
            if preDate <> SUBSTRING(resValue,1,8) THEN
                set t_error = -1;
            end if;
        ELSE
            SET resValue= CONCAT(preDate, LPAD(1, length, '0'));
        END IF;
        UPDATE serialno SET Res = resValue WHERE Pre = preValue;
    END IF;

    #IF t_error = 1 then 
    IF @@error_count <> 0 | t_error <> 0 THEN
        ROLLBACK;
        select t_error;
    ELSE 
        COMMIT;
        SELECT CONCAT(preValue, resValue);
    END IF;
END $
delimiter ;

那边的参数preValue为前缀,
preDate为8位的日期,格式如:”20141227″, 参数des为验证, 此处并不插足逻辑,
只是翻新二个字段. 最终多个length字段, 表示流水号的位数.
流水号的位数不能够安装的太过小, 得视专门的职业来鲜明. 当流水号溢出时,
会重临-1.

OK, 来看一下效益:

call p_GetSerialNo( 'b', '20170101',  'b', 4);

图片 4

 

You may also like...

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图