ciel717

一、自定义函数

1.1 创建

DELIMITER $$            #将语句的结束符号从分号;临时改为两个$$(可以是自定义)
CREATE FUNCTION 函数名([<参数1><类型1>[,<参数2><类型2>...]])   #定义函数
returns 数据类型         #定义返回值类型
-> BEGIN                #以关键字BEGIN开始
-> select * from chengshi;  #执行语句
-> RETURN 值;           #返回值
-> END $$               #以关键字END结束
DELIMITER;              #将语句的结束符号恢复为分号
  • 还可以有一些特别的选项,特别的选项写在return之后,begin之前,如:
    • comment:一个关于函数的描述
    • 还有一些比如sql security等选项

1.2 调用

-- 无参调用
select myselect3();
-- 传参调用
select myselect5("python");
select * from class where id=myselect5("python");

1.3 查看

查看函数创建语句:

show create function 函数名;

查看所有函数:

show function status [like \'pattern\'];

1.4 修改

函数的修改只能修改一些如comment的选项,不能修改内部的sql语句和参数列表。

alter function 函数名 选项;

1.5 删除

drop function 函数名;

1.6 案例

以下是拆分大整数为2幂的和算法

bigint目前支持最大值为

\[2^{62} = 4611686018427387904 \]

/*判断是否存在,如果存在就删除*/
DROP FUNCTION IF EXISTS binaryPow;
/*创建函数*/
create function binaryPow(num bigint(20))
/*返回值数据类型*/
RETURNS varchar(512)
begin
  /*参数二进制的变量*/
  DECLARE binaryNum VARCHAR(128) DEFAULT 0;
  /*自增变量*/
  DECLARE chooseNum int DEFAULT 0;
  /*返回值变量*/
  DECLARE returnNum varchar(255) DEFAULT 0;
  /*参数的长度*/
  DECLARE numLength varchar(255) DEFAULT 0;
  /*变量值*/
  DECLARE cur tinyint(1) DEFAULT 0;
  /*将参数转换成二进制并赋给binaryNum变量*/
  set binaryNum = bin(num);
  /*获得binaryNum长度赋给numLength*/
  set numLength = LENGTH(binaryNum);
  /*开启循环*/
  repeat
    /*分割binaryNum变量,每次获得1位*/
    set cur = substr(binarynum, numLength - chooseNum, 1);
    /*cur为0时,*/
    if cur > 0 then 
      if returnNum != 0 then
        set returnNum = CONCAT(returnNum,\',\',cast(POW(2,chooseNum) as signed int));
      end if;
      if returnNum = 0 then
        set returnNum = cast(POW(2,chooseNum) as signed int);
      end if;
    end if;
  /*递增*/
  set chooseNum = chooseNum + 1;
  UNTIL chooseNum = numLength end repeat;
  return returnNum;
end;

/*调用*/
SELECT binaryPow(4611686018427387904);

注意:declare定义的变量名不能和select查询的列名相同,否则赋值不成功

如果开启bin_log时,会报以下错误:

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;

id转列名称

SELECT
	b.id,
	GROUP_CONCAT( a.rule_desc ) AS rule_descs,
	binaryPow ( b.insurance_sup ) AS insurance_sups 
FROM
	m_examine_rule_dictionary a,
	m_product_car_rule b 
WHERE
	FIND_IN_SET( a.rule_decimal, binaryPow ( b.insurance_sup ) ) 
	AND a.type = 23 
	and (b.id = \'755118907085426688\')
GROUP BY
	b.id;

二、存储过程

存储过程是一组为了完成特定功能的SQL语句集合。

存储过程在使用过程中是将常用或者复杂的工作预先使用SQL语句写好并用一个指定的名称存储起来,这个过程经编译和优化后存储在数据库服务器中。当需要使用该存储过程时,只需要调用它即可。存储过程在执行上比传统SQL速度更快、执行效率更高。

2.1 创建

DELIMITER $$                     #将语句的结束符号从分号;临时改为两个$$(可以是自定义)
CREATE PROCEDURE Proc()          #创建存储过程,过程名为Proc,不带参数
-> BEGIN	                 #过程体以关键字 BEGIN 开始
-> select * from chengshi;	 #过程体语句
-> END $$                        #过程体以关键字 END 结束
DELIMITER ;                      #将语句的结束符号恢复为分号

2.2 调用

CALL Proc;

2.3 查看

SHOW CREATE PROCEDURE [数据库.]存储过程名;		#查看某个存储过程的具体信息
SHOW CREATE PROCEDURE Proc;
SHOW PROCEDURE STATUS LIKE \'%Proc%\' \G

2.4 修改

IN 输入参数:表示调用者向过程传入值(传入值可以是字面量或变量)
OUT 输出参数:表示过程向调用者传出值(可以返回多个值)(传出值只能是变量)
INOUT 输入输出参数:既表示调用者向过程传入值,又表示过程向调用者传出值(值只能是变量)

DELIMITER $$				
CREATE PROCEDURE Proc1(IN inname CHAR(16))		
-> BEGIN					
-> SELECT * FROM city WHERE Store_Name = inname;
-> END $$					
DELIMITER ;					

CALL Proc1(\'Boston\');

2.5 删除

存储过程内容的修改方法是通过删除原有存储过程,之后再以相同的名称创建新的存储过程

DROP PROCEDURE IF EXISTS Proc;    #仅当存在时删除,如果指定的过程不存在,则产生一个错误

2.6 控制语句

2.6.1 if-then-else

DELIMITER $$  
CREATE PROCEDURE Proc2(IN inid int)  
-> begin 
-> declare var int;  
-> set var=inid*2;   
-> if var>=10 then 
-> update t set id=id+1;  
-> else 
-> update t set id=id-1;  
-> end if;  
-> end $$

DELIMITER ;

2.6.2 循环while

DELIMITER $$  
CREATE PROCEDURE Proc3()
-> begin 
-> declare var int(10);  
-> set var=0;  
-> while var<6 do  
-> insert into t values(var);  
-> set var=var+1;  
-> end while;  
-> end $$  

DELIMITER ;

2.7 案例

-- subject_id 递增 start
/*判断是否存在,如果存在就删除*/
/*取一个系统中绝对不会用到的存储过程名称*/
drop procedure if exists tempProcedure_Test;
/*创建临时存储过程*/
create procedure tempProcedure_Test()
BEGIN
  /*declare定义的变量名不能和select查询的列名相同*/
  /*判断是否还有记录*/
  declare isDone int default 0;
  /*用于自增的变量*/
  declare intNumber BIGINT(20) default 190122100000177;
  /*每条记录循环时的临时ID*/
  declare tempId BIGINT(20);

  /*取出来所有需要循环的数据*/
  declare folderIds cursor for

  /*sql语句 开始*/
  SELECT
	a.id 
  FROM
	t_account_subject a,(
	SELECT
		account_id,
		subject_code,
		max( `year` ) `year` 
	FROM
		`t_account_subject` d 
	GROUP BY
		d.account_id,
		d.subject_code 
	ORDER BY
		d.YEAR DESC 
	) b 
  WHERE
	a.account_id = b.account_id 
	AND a.YEAR = b.YEAR 
	AND a.subject_code = b.subject_code 
	AND a.subject_id = 0;
  /*sql语句 结束*/

  /*如果不存在就设置为1,即为true*/
  declare continue handler for not FOUND set isDone = 1;

  /*OPEN*/
  open folderIds;
  REPEAT
  /*开始循环数据*/
  fetch folderIds into tempId;
    if not isDone THEN
      update t_account_subject set subject_id = intNumber where id = tempId;
      set intNumber = intNumber + 1;
    end if;
    until isDone end repeat;
  close folderIds; /*CLOSE,对应上面的open folderIds;*/
END;
/*调用下这个临时的存储过程*/
call tempProcedure_Test();
drop procedure tempProcedure_Test; /*使用完毕后要删除垃圾*/
-- subject_id 递增 end

总结

存储过程和函数主要区别

  1. 存储过程实现的功能要复杂一点,函数实现的功能针对性比较强;
    存储过程,功能强大,可以执行包括修改表等一系列数据库操作;
    用户定义函数不能用于执行一组修改全局数据库状态的操作。
  2. 对于存储过程来说可以返回参数,如记录集,函数只能返回值或者表对象;
    函数只能返回一个变量;而存储过程可以返回多个;
    存储过程的参数可以有IN,OUT,INOUT三种类型,而函数必须指定返回值,且参数默认为IN类型;
    存储过程声明时不需要返回类型,而函数声明时需要描述返回类型,且函数体中必须包含一个有效的RETURN语句。
  3. 存储过程,可以使用非确定函数,不允许在用户定义函数主体中内置非确定函数。
  4. 存储过程一般是作为一个独立的部分来执行( EXECUTE 语句执行),而函数可以作为查询语句的一个部分来调用(SELECT调用);
    由于函数可以返回一个表对象,因此它可以在查询语句中位于FROM关键字的后面。 SQL语句中不可用存储过程,而可以使用函数。
  5. 调用方式:
    函数 select my_fun() ;
    过程 call my_pro( ) ;

参考文章

分类:

技术点:

相关文章:

  • 2022-12-23
  • 2021-11-12
  • 2017-12-04
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-11-12
猜你喜欢
  • 2021-06-27
  • 2021-11-12
  • 2021-11-12
  • 2021-11-12
  • 2021-12-21
  • 2021-12-31
  • 2022-12-23
相关资源
相似解决方案