mysql 存储过程学习

存储过程框架

 

DEMILITER $$ -- 重定义符

 

DROP PROCEDURE IF EXISTS store_procedure$$ -- 如果存在此名的存储过程,先删除

 

CREATE PROCEDURE store_procedure() -- 创建名为store_procedure的存储过程

 

BEGIN -- 开始

 

-- 内容

 

END$$ -- 结束

 

DEMILITER ; -- 恢复;为分隔符

 

在使用复合语句时,必须考虑和解决这样一个问题:复合语句块里的语句必须以分号(;)彼此隔开,但因为分号同时也是mysql程序默认使用的语句分隔符,所以在使用mysql程序定义存储程序时会发生冲突。解决这个问题的办法是使用DELIMITER命令把mysql程序的语句分隔符重定义为另一个字符或字符串。

 

 

 

注释:

 

两个连字符加一个空格的单行注释,如:-- 注释

 

类似C语言的多行注释,如:/*注释

 

*/

 

 

 

变量:

 

变量声明:

 

DECLARE 变量名;

 

示例:DECLARE my_integer INT;

 

变量声明同时初始化:

 

DECLARE 变量名 DEFAULT 变量初始化值;

 

示例:DECLARE my_integer INT DEFAULT 0;

 

变量赋值:

 

SET 变量名=值;

 

示例:SET my_integer=1;

 

常用的MySQL数据类型 

 

数据类型 

解释 

相应值的示例 

INT, INTEGER 

32位整数。取值范围为-21亿到+21亿,如果是非符号数,值可以达到42亿,但这样做就不能包括负数 

123,345 -2,000,000,000 

BIGINT 

64位整数。取值范围为-9万亿到+9万亿或者非负的0到18万亿 

9,000,000,000,000,000,000 -9,000,000,000,000,000,000 

FLOAT 

32位浮点数。取值范围为1.7e38 to 1.7e38或者非负的0到3.4e38 

0.00000000000002 17897.890790 -345.8908770 1.7e21 

DOUBLE 

64位浮点数。取值范围接近无限(1.7e308) 

1.765e203 -1.765e100 

DECIMAL(precision,scale) NUMERIC(precision,scale) 

定点数。存储情况取决于precision,能保存可能出现的数字范围。 NUMERIC通常用来保存重要的十进制数,例如现金 

78979.00 -87.50 9.95 

 

 

 

DATE 

日期类型,没有详述时间 

‘1999-12-31‘ 

DATETIME 

日期和时间,时间精确到秒 

‘1999-12-31 23:59:59‘ 

CHAR(length) 

定长字符串。值会被空白填充至制定长度,最大长度为255字节 

‘hello world ‘ 

VARCHAR(length) 

最大长度为64K的可变字符串 

‘Hello world‘ 

BLOB, TEXT 

最大64K长度,BLOB用来保存2进制数据,TEXT用来保存文本数据 

任何能想象的内容 

LONGBLOB, LONGTEXT 

BLOB和TEXT的加长版本,存储能力达4GB 

任何能想象的内容,但比BLOB和TEXT能存放更大的长度 

 

 

 

用户变量(全局变量):

 

可以跨存储过程使用;

 

DECALRE @g_variable INT DEFAULT 0;

 

 

 

参数:

 

参数类型分为输入(IN,默认)、输出(OUT)、输入输出(INOUT)三种类型;

 

存储函数只能用输入(IN)模式,但可以有一个返回值,对于需要返回多个值的功能,只能采用存储过程;

 

示例:存储过程计算平方根

 

DEMILITER $$

 

DROP PROCEDURE sqrt_store_procedure

 

CREATE PROCEDURE sqrt_store_procedure(IN in_num INT, OUT out_num FLOAT)

 

BEGIN

 

SET out_num=SQRT(in_num);

 

END$$

 

DEMILITER ;

 

 

 

操作符:

 

数学操作符

 

操作符 

描述 

用例 

加 

SET var1=2+2; à 4 

减 

SET var2=3-2; à 1 

乘 

SET var3=3*2; à 6 

除 

SET var4=10/3; à 3.3333 

DIV 

整除 

SET var5=10 DIV à3; 3 

模 

SET var6=10%3; à 1 

 

 

 

比较操作符

 

 

 

操作符 

描述 

示例 

示例结果 

是否大于 

1>2 

False 

是否小于 

2<1 

False 

<= 

是否小于等于 

2<=2 

True 

>= 

是否大于等于 

3>=2 

True 

BETWEEN 

是否位于两个值之间 

5 BETWEEN 1 AND 10 

True 

NOT BETWEEN 

是否不位于两个值之间 

5 NOT BETWEEN 1 AND 10 

False 

IN 

值位于列表中 

5 IN (1,2,3,4) 

False 

NOT IN 

值不位于列表中 

5 NOT IN (1,2,3,4) 

True 

等于 

2=3 

False 

<>, != 

不等于 

2<>3 

False 

<=> 

Null安全等于(如果两个值均为Null返回TRUE) 

NULL<=>NULL 

True 

LIKE 

匹配简单模式 

"Guy Harrison" LIKE "Guy%" 

True 

REGEXP 

匹配扩展正则表达式 

"Guy Harrison" REGEXP "[Gg]reg" 

False 

IS NULL 

值为空 

0 IS NULL 

False 

IS NOT NULL 

值不为空 

0 IS NOT NULL 

True 

 

 

 

逻辑操作符

 

AND操作符比较两个逻辑表达式,并且只在两个表达式都为真是才返回TRUE。

 

AND 

TRUE 

FALSE 

NULL 

TRUE 

TRUE 

FALSE 

NULL 

FALSE 

FALSE 

FALSE 

NULL 

NULL 

NULL 

NULL 

NULL 

 

OR操作符比对两个逻辑表达式,并且只要其中的一个表达式为真即返回TRUE。

 

OR 

TRUE 

FALSE 

NULL 

TRUE 

TRUE 

TRUE 

TRUE 

FALSE 

TRUE 

FALSE 

NULL 

NULL 

TRUE 

NULL 

NULL 

 

XOR操作符只有在两个值不完全为真时才返回TRUE。

 

XOR 

TRUE 

FALSE 

NULL 

TRUE 

FALSE 

TRUE 

NULL 

FALSE 

TRUE 

FALSE 

NULL 

NULL 

NULL 

NULL 

NULL 

 

 

 

位操作符

 

操作符 

用途 

OR 

AND 

<< 

Shift bits to left 

>> 

Shift bits to right 

NOT or invert bits 

 

 

 

 

 

条件执行:

 

IFCASE

 

示例:IF

 

DECLARE count INT DEFAULT 0;

 

IF price > 100) THEN

 

count = 0;

 

ELSEIF (prict >= 30 AND prict <= 100) THEN

 

count=1;

 

ELSE

 

count=2;

 

END IF;

 

 

 

示例:CASE

 

DECLARE count INT DEFAULT 0;

 

CASE enum_type

 

WHEN ‘A’ THEN

 

count=1;

 

WHEN ‘B’ THEN

 

count=2;

 

ELSE -- 未满足’A’、’B’的情况下,执行ELSE流程

 

count=3;

 

END CASE;

 

在没有ELSE的情况下,如果enum_type没有’A’、’B’的情况,会抛出一个异常:ERROR 1339 (20000): Case not found for CASE statement 

 

CASE语句中的WHEN表达式也可以是条件,如:

 

CASE price

 

WHEN (price > 200) THEN

 

count=1;

 

WHEN ((price > 100) AND (price <= 200)) THEN

 

count=2;

 

ELSE

 

count=3;

 

END CASE;

 

 

 

循环:

 

简单循环LOOPEND LOOP

 

当条件为真时,继续执行的循环WHILEEND WHILE

 

循环直至条件为真:REPEATUNTIL

 

三种循环都可以用LEAVE子句来终止循环;

 

示例:LOOP

 

DECLARE count INT DEFAULT 0;

 

my_loop: LOOP

 

SET count=count+1;

 

IF (count=10)

 

LEAVE my_loop;

 

END IF;

 

SELECT CONCAT(count, “ is select value”);

 

END LOOP my_loop;

 

SELECT “I can count to 10”;

 

 

 

ITERATE语句用来重新从循环头部开始执行,而不执行任何在循环中遗留下来的语句。

 

DECLARE count INT DEFAULT 0;

 

my_loop: LOOP

 

SET count=count+1;

 

IF (count=10)

 

LEAVE my_loop;

 

ELSEIF (MOD(count,2)=0)

 

ITERATE my_loop;

 

END IF;

 

SELECT CONCAT(count, “ is select value”);

 

END LOOP my_loop;

 

SELECT “I can count to 10 odd num”;

 

 

 

REPEAT……UNTIL循环,REPEAT循环的循环体总是能确保至少运行一次。

 

DECLARE count INT DEFAULT 0;

 

my_loop: REPEAT

 

SET count=count+1;

 

IF (MOD(count,2)<>0)

 

SELECT CONCAT(count, “ is select value”);

 

END IF;

 

UNTIL count=10

 

END LOOP my_loop;

 

SELECT “I can count to 10 odd num”;

 

 

 

WHILE循环,WHILE循环只有在条件为真是才执行循环。

 

DECLARE count INT DEFAULT 0;

 

my_loop: WHILE couunt<10) DO

 

SET count=count+1;

 

IF (MOD(count,2)<>0)

 

SELECT CONCAT(count, “ is select value”);

 

END IF;

 

END WHILE my_loop;

 

SELECT “I can count to 10 odd num”;

 

 

 

MYSql函数:

 

字符串函数 

 

这些函数主要对字符串变量执行操作,比方说:你可以连接字符串,在字符串中查找字符,得到子串和其他常规操作。

 

数学函数

 

这些函数主要对数字进行操作,比方说:你可以进行乘方(平方),三角函数(sin,cos),随机数函数和对数函数等。 

 

日期和时间函数 

 

折现函数主要的操作对象是日期和时间,比方说:你可以得到当前时间,从一个日期上加上或减去一个时间间隔,找出两个日期间的差异,获取某个确定的时间点(比如:得到一天中某时间的小时数)。

 

其它函数

 

这些函数包括了所有不容易被分入上面类别中函数。他们包括类型转换函数,流程控制函数(比如:CASE),信息反馈函数(比如服务器版本)和加密函数。

 

经常被使用的MySQL函数

 

 

 

函数 

描述 

ABS(number) 

返回提供数字的绝对值。比方说, ABS(-2.3)=2.3. 

CEILING(number) 

返回下一个最大整数,比方说, CEILING(2.3)=3. 

CONCAT(string1[,string2,string3,...]) 

返回所有提供字符串的连接形式的值 

CURDATE 

返回当前时间(不带时间) 

DATE_ADD(date,INTERVAL amount_type) 

给提供的时间值加上一个时间间隔并返回一个新时间。正确的形式有SECOND, MINUTE, HOUR, DAY, MONTH和YEAR 

DATE_SUB(date,INTERVAL interval_type) 

从提供的时间值上减去一个时间间隔并返回一个新的时间。正确的形式有SECOND, MINUTE, HOUR, DAY, MONTH和YEAR 

FORMAT(number,decimals) 

返回一个指定精确度的数值,并给与以1000为单位的分割(通常使用“,”) 

GREATEST(num1,num2[,num3, ... ]) 

返回所有提供参数中的最大数 

IF(test, value1,value2) 

测试一个逻辑条件,如果为真则返回value1,如果为假返回value2 

IFNULL(value,value2) 

返回第一个值,除非第一个值为空;这样的话返回第二个值 

INSERT(string,position,length,new) 

把一个字符串插入到另一个字符串中 

INSTR(string,substring) 

返回一个字符串中子串的位置 

ISNULL(expression) 

如果参数为空则返回1,否则返回0 

LEAST(num1,num2[,num3, ... ]) 

返回参数列表中的最小值 

LEFT(string,length) 

返回字符串最左边的部分 

LENGTH(string) 

返回字符串中的字节数。CHAR_LENGTH可以被用来返回字符数(这会在你使用多字节字符集是产生差异) 

LOCATE(substring,string[,number]) 

返回字符串中子串的位置,可选的第三个参数为在父字符串中开始搜索的位置 

LOWER(string) 

返回给定字符串的小写形式 

LPAD(string,length,padding) 

返回字符串 str, 其左边由字符串padding 填补到length 字符长度,第三个参数为填充字符 

LTRIM(string) 

删除所有字符串中的前缀空格 

MOD(num1,num2) 

返回第一个数除于第二个数后的模(余数部分) 

NOW 

返回当前日期和时间 

POWER(num1,num2) 

返回num1的num2次方 

RAND([seed]) 

返回一个随机数。seed可被用于随机数生成器的种子数 

REPEAT(string,number) 

返回一个重复number次string的字符串 

REPLACE(string,old,new) 

用new替换所有出现old的地方 

ROUND(number[,decimal]) 

舍去给定数值的指定精度的位数 

RPAD(string,length,padding) 

返回字符串 str, 其右边由字符串padding 填补到length 字符长度,第三个参数为填充字符

RTRIM(string) 

删除字符串尾部的空格 

SIGN(number) 

如果number小于0则返回-1,如果大于0则返回1,如果为0则返回0 

SQRT(number) 

返回number的平方根 

STRCMP(string1,string2) 

如果两个值相同则返回0,若根据当前分类次序,第一个参数小于第二个,则返回 -1,其它情况返回 1 。 

SUBSTRING(string,position,length) 

从字符串指定位置开始返回length个字符 

UPPER(string) 

将指定字符串转换为大写 

VERSION 

返回MySQL服务器当前版本号的字符串 

 

 

 

 

 

 

 

和数据库交互:

 

将一个SQL语句所返回的单个记录放入本地变量中;

 

创建一个“游标”来迭代SQL语句所返回的结果集;

 

执行一个SQL语句,将执行后的结果集返回给它的调用程序;

 

内嵌一个不返回结果集的SQL语句,如INSERTUPDATADELETE等;

 

将一个SQL语句所返回的单个记录放入本地变量中:SELECT INTO

 

示例:

 

DECLARE num INT;

 

SELECT NUM(price)

 

INTO num

 

FROM tabprice;

 

SELECT CONCAT(“Total Price is”, num);

 

 

 

游标

 

游标的声明必须在我们所有的变量声明之后。在的变量之前定义游标会产生一个1337错误。游标总是和SELECT语句配合使用。

 

DECLARE cur CURSOR FOR SELECT * FROM customers;

 

创建一个“游标”来迭代SQL语句所返回的结果集:CURSOR

 

查询多条记录数据;

 

示例:CURSOR

 

DECLARE done DEFAULT -1;

 

DECLARE nprice DEFAULT 0;

 

DECLARE cur1 CURSOR FOR

 

SELECT price FROM tabprice;

 

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1; -- 如果没有记录,错误处理no data to fetch条件,几乎所有的游标都要用到

 

SET done=0;

 

OPEN cur1;

 

my_loop: LOOP

 

FETCH cur1 INTO nprice; -- 循环从游标中取值

 

IF done=1)

 

LEAVE my_loop;

 

END IF;

 

END LOOP my_loop;

 

CLOSE cur1;

 

DEALLOCATE cur1; -- 释放游标

 

 

 

不使用no data to fetch的另一种解决方案@@FETCH_STATUS

 

@@fetch_statusMSSQL的一个全局变量

 

其值有以下三种,分别表示三种不同含义:【返回类型integer

 

0 FETCH 语句成功

 

-1 FETCH 语句失败或此行不在结果集中

 

-2 被提取的行不存在

 

@@fetch_status值的改变是通过fetch next from实现的

 

FETCH NEXT FROM Cursor

 

 

 

DECLARE Employee_Cursor CURSOR FOR

 

SELECT LastName, FirstName FROM Northwind.dbo.Employees

 

OPEN Employee_Cursor

 

FETCH NEXT FROM Employee_Cursor

 

WHILE @@FETCH_STATUS = 0

 

BEGIN

 

FETCH NEXT FROM Employee_Cursor

 

END

 

CLOSE Employee_Cursor

 

DEALLOCATE Employee_Cursor

 

 

 

No data to fetch条件捕获在嵌套游标循环中使用比较复杂,有两种方案

 

1.在内循环结束时重置条件为0

 

DECLARE done DEFAULT -1;

 

DECLARE nprice DEFAULT 0;

 

DECLARE cur1 CURSOR FOR

 

SELECT price FROM tabprice;

 

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1; -- 如果没有记录,错误处理no data to fetch条件,几乎所有的游标都要用到

 

SET done=0;

 

OPEN cur1;

 

my_loop: LOOP

 

FETCH cur1 INTO nprice; -- 循环从游标中取值

 

DECLARE cur2 CURSOR FOR SELECT * FROM cumtomers;

 

OPEN cur2;

 

my_loop2: LOOP

 

FETCH cur2 INTO custom;

 

IF (done=1)

 

LEAVE my_loop2;

 

END IF;

 

END LOOP my_loop2;

 

CLOSE cur2;

 

DEALLOCATE cur2; -- 释放游标

 

SET done=0; -- 重置事件值

 

IF done=1)

 

LEAVE my_loop;

 

END IF;

 

END LOOP my_loop;

 

CLOSE cur1;

 

DEALLOCATE cur1; -- 释放游标

 

2.内循环封闭为一个块

 

DECLARE done DEFAULT -1;

 

DECLARE nprice DEFAULT 0;

 

DECLARE cur1 CURSOR FOR

 

SELECT price FROM tabprice;

 

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1; -- 如果没有记录,错误处理no data to fetch条件,几乎所有的游标都要用到

 

SET done=0;

 

OPEN cur1;

 

my_loop: LOOP

 

FETCH cur1 INTO nprice; -- 循环从游标中取值

 

cur2begin: BEGIN

 

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done2=1;

 

DECLARE cur2 CURSOR FOR SELECT * FROM cumtomers;

 

OPEN cur2;

 

my_loop2: LOOP

 

FETCH cur2 INTO custom;

 

IF (done2=1)

 

LEAVE my_loop2;

 

END IF;

 

END LOOP my_loop2;

 

CLOSE cur2;

 

DEALLOCATE cur2; -- 释放游标

 

END cur2begin;

 

IF done=1)

 

LEAVE my_loop;

 

END IF;

 

END LOOP my_loop;

 

CLOSE cur1;

 

DEALLOCATE cur1; -- 释放游标

 

 

 

 

 

在存储过程中调用另一个存储过程:

 

CALL 存储过程名;

 

 

 

存储函数:

 

函数的参数列表中模式只能为IN。OUT和INOUT参数不被允许。制定IN关键字是被允许也是缺省的;

 

函数必须返回一个值,它的类型被定义于函数的头部;

 

函数能被SQL语句所调用;

 

函数可能不返回任何结果集;

 

在程序的真正目的是比对值和需要返回值时或者你希望在SQL语句中创建用户自定义函数的时候更多的考虑使用存储函数,而不是存储过程;

 

框架:

 

DEMILITER $$ -- 重定义符

 

DROP FUNCTION IF EXISTS store_function$$ -- 如果存在此名的存储函数,先删除

 

CREATE FUNCTION store_function() RETURNS INT DETERMINITISTIC

 

 -- 创建名为store_procedure的存储函数

 

-- 

 

MySQL相较于存储过程,对于存储函数有更严格的规则。函数必须声明不修改SQL(使用NO SQL或者 READS SQL DATA子句)或者声明为DETERMINISTIC(如果服务器被允许开启二进制日志)。这个限制是为了防止当函数返回不确定值 时,数据库同步复制的不一致性,我们的样例例程使用了“deterministic”,这样我们就能确保在提供了相同的参数的情况下返回相同的值 

 

 

 

BEGIN -- 开始

 

-- 内容

 

RETURN(返回值);

 

END$$ -- 结束

 

DEMILITER ; -- 恢复;为分隔符

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。