凤凰平台注册开户_凤凰彩票app下载安装_凤凰彩票投注网

热门关键词: 凤凰平台注册开户,凤凰彩票app下载安装,凤凰彩票投注网

MySQL游标循环取出空值的BUG,变量和条件

作者: MySQL数据库  发布:2019-10-13

上午同事要本身写个MySQL去除重复数据的SQL,想起来上次写过一篇MySQL去除重复数据的博客,使用导入导出加独一索引完结的,然则那种格局对事情影响极大,所以再一次写贰个积攒进程来删重复数据,这一写就写了四个中午,这种BUG确实是很令人心寒和浪费时间的。

MySQL 变量和规范,MySQL变量条件

MySQL心得7-1-存款和储蓄进度

这里把流程简便的描述一下,删重复数据的逻辑很粗大略:

概述  

 变量在蕴藏进度中会平日被使用,变量的施用方法是四个重大的知识点,特别是在定义法则这块比较重大。

 mysql版本:5.6

 

1.基于重复判别标准寻找重复记录的小不点儿主键(常常是ID列)。

变量定义和赋值  

#创建数据库
DROP DATABASE IF EXISTS Dpro;
CREATE  DATABASE Dpro
CHARACTER SET utf8
;

USE Dpro;

#创建部门表
DROP TABLE IF EXISTS Employee;
CREATE TABLE Employee
(id INT NOT NULL PRIMARY KEY COMMENT '主键',
 name VARCHAR(20) NOT NULL COMMENT '人名',
 depid INT NOT NULL COMMENT '部门id'
);

INSERT INTO Employee(id,name,depid) VALUES(1,'陈',100),(2,'王',101),(3,'张',101),(4,'李',102),(5,'郭',103);

declare定义变量

在仓库储存进程和函数中经过declare定义变量在BEGIN...END中,且在说话此前。並且能够由此重复定义三个变量

只顾:declare定义的变量名不可能带‘@’符号,mysql在这里点做的确实相当不够直观,往往变量名会被错成参数恐怕字段名。

DECLARE var_name[,...] type [DEFAULT value]

例如:

DROP PROCEDURE IF EXISTS Pro_Employee;
DELIMITER $$
CREATE PROCEDURE Pro_Employee(IN pdepid VARCHAR(20),OUT pcount INT )
READS SQL DATA
SQL SECURITY INVOKER
BEGIN
DECLARE pname VARCHAR(20) DEFAULT '陈';
SELECT COUNT(id) INTO pcount FROM Employee WHERE depid=pdepid;

END$$
DELIMITER ;

SET变量赋值 

SET除了能够给已经定义好的变量赋值外,还能钦命赋值并定义新变量,且SET定义的变量名能够带‘@’符号,SET语句的岗位也是在BEGIN ....END之间的口舌此前。

1.变量赋值

SET var_name = expr [, var_name = expr] ...

DROP PROCEDURE IF EXISTS Pro_Employee;
DELIMITER $$
CREATE PROCEDURE Pro_Employee(IN pdepid VARCHAR(20),OUT pcount INT )
READS SQL DATA
SQL SECURITY INVOKER
BEGIN
DECLARE pname VARCHAR(20) DEFAULT '陈';
SET pname='王';
SELECT COUNT(id) INTO pcount FROM Employee WHERE depid=pdepid AND name=pname;

END$$
DELIMITER ;

CALL Pro_Employee(101,@pcount);

  SELECT @pcount;

凤凰彩票投注网 1

 2.透过赋值定义变量

DROP PROCEDURE IF EXISTS Pro_Employee;
DELIMITER $$
CREATE PROCEDURE Pro_Employee(IN pdepid VARCHAR(20),OUT pcount INT )
READS SQL DATA
SQL SECURITY INVOKER
BEGIN
DECLARE pname VARCHAR(20) DEFAULT '陈';
SET pname='王';
SET @ID=1;
SELECT COUNT(id) INTO pcount FROM Employee WHERE depid=pdepid AND name=pname;
SELECT @ID;

END$$
DELIMITER ;

CALL Pro_Employee(101,@pcount);

凤凰彩票投注网 2

  1. 使用存款和储蓄进度的独到之处有:

2.在适合重新条件的记录中,把主键大于最小主键的笔录整个删掉就可以。

SELECT ... INTO语句赋值

 通过select into语句能够将值赋予变量,也足以之间将该值赋值存款和储蓄过程的out参数,下边包车型地铁囤积进程select into就是里面将值赋予out参数。

DROP PROCEDURE IF EXISTS Pro_Employee;
DELIMITER $$
CREATE PROCEDURE Pro_Employee(IN pdepid VARCHAR(20),OUT pcount INT )
READS SQL DATA
SQL SECURITY INVOKER
BEGIN
DECLARE pname VARCHAR(20) DEFAULT '陈';
DECLARE Pid INT;
SELECT COUNT(id) INTO Pid FROM Employee WHERE depid=pdepid AND name=pname;
SELECT Pid;

END$$
DELIMITER ;

CALL Pro_Employee(101,@pcount);

本条蕴藏进度便是select into将值赋予变量;

 凤凰彩票投注网 3

表中并不曾depid=101 and name='陈'的笔录。 

 

假设笔者有如下表,须求删除start_time和end_time都一样的重复记录。

条件  

规范的功能常常用在对点名条件的拍卖,举个例子我们碰到主键重复报错后该如什么地方理。 

概念法则

 定义条件就是开始时期定义某种错误状态或许sql状态的名称,然后就可以援用该标准名称开做标准管理,定义准绳平日用的比比较少,平日会直接放在标准管理个中。

DECLARE condition_name CONDITION FOR condition_value

condition_value:
    SQLSTATE [VALUE] sqlstate_value
  | mysql_error_code

1.一向不定义法则:

DROP PROCEDURE IF EXISTS Pro_Employee_insert;
DELIMITER $$
CREATE PROCEDURE Pro_Employee_insert()
MODIFIES SQL DATA
SQL SECURITY INVOKER
BEGIN
SET @ID=1;
INSERT INTO Employee(id,name,depid) VALUES(1,'陈',100);
SET @ID=2;
INSERT INTO Employee(id,name,depid) VALUES(6,'陈',100);
SET @ID=3;

END$$
DELIMITER ;

#执行存储过程
CALL Pro_Employee_insert();

#查询变量值
SELECT @ID,@X;

凤凰彩票投注网 4

 报主键重复的失实,此中1062是主键重复的错误代码,2两千是sql错误状态

凤凰彩票投注网 5

2.定义管理标准

DROP PROCEDURE IF EXISTS Pro_Employee_insert;
DELIMITER $$
CREATE PROCEDURE Pro_Employee_insert()
MODIFIES SQL DATA
SQL SECURITY INVOKER
BEGIN
#定义条件名称,
DECLARE reprimary CONDITION FOR 1062;
#引用前面定义的条件名称并做赋值处理
DECLARE EXIT HANDLER FOR reprimary SET @x=1;
SET @ID=1;
INSERT INTO Employee(id,name,depid) VALUES(1,'陈',100);
SET @ID=2;
INSERT INTO Employee(id,name,depid) VALUES(6,'陈',100);
SET @ID=3;

END$$
DELIMITER ;

CALL Pro_Employee_insert();

SELECT @ID,@X;

在施行存款和储蓄进度的手续中并未报错,可是由于本人定义的是exit,所以在遇见报错sql就告一段落往下实践了。

凤凰彩票投注网 6

接下去看看continue的不如

DROP PROCEDURE IF EXISTS Pro_Employee_insert;
DELIMITER $$
CREATE PROCEDURE Pro_Employee_insert()
MODIFIES SQL DATA
SQL SECURITY INVOKER
BEGIN
#定义条件名称,
DECLARE reprimary CONDITION FOR SQLSTATE '23000';
#引用前面定义的条件名称并做赋值处理
DECLARE CONTINUE HANDLER FOR reprimary SET @x=1;
SET @ID=1;
INSERT INTO Employee(id,name,depid) VALUES(1,'陈',100);
SET @ID=2;
INSERT INTO Employee(id,name,depid) VALUES(6,'陈',100);
SET @ID=3;

END$$
DELIMITER ;

CALL Pro_Employee_insert();

SELECT @ID,@X;

其间浅蓝标识的是和方面不一致的地点,这里定义法则使用的是SQL状态,也是主键重复的事态;并且这里运用的是CONTINUE正是超过错误继续往下实行。

凤凰彩票投注网 7

凤凰彩票投注网 8

准则处理

条件管理正是中间定义语句的谬误的管理,省去了前头定义法规名称的步子。

DECLARE handler_type HANDLER FOR condition_value[,...] sp_statement

handler_type:
    CONTINUE| EXIT| UNDO

condition_value:
    SQLSTATE [VALUE] sqlstate_value
  | condition_name
  | SQLWARNING
  | NOT FOUND
  | SQLEXCEPTION
  | mysql_error_code

handler_type:相遇错误是一而再往下实践或然终止,前段时间UNDO还没用到。

CONTINUE:继续往下实践

EXIT:终止试行

condition_values:错误状态

SQLSTATE [VALUE] sqlstate_value:正是前方讲到的SQL错误状态,比如主键重复状态SQLSTATE '2两千'

condition_name:上边讲到的定义法规名称;

SQLWA陆风X8NING:是对富有以01发轫的SQLSTATE代码的笔记,比如:DECLARE CONTINUE HANDLE智跑 FOSportage SQLWAPRADONING。

NOT FOUND:是对具有以02从头的SQLSTATE代码的笔记。

SQLEXCEPTION:是对富有未有被SQLWA奥迪Q3NING或NOT FOUND捕获的SQLSTATE代码的笔记。

mysql_error_code:是错误代码,比如主键重复的错误代码是1062,DECLARE CONTINUE HANDLE景逸SUV FO奥德赛 1062

 

语句:

DROP PROCEDURE IF EXISTS Pro_Employee_insert;
DELIMITER $$
CREATE PROCEDURE Pro_Employee_insert()
MODIFIES SQL DATA
SQL SECURITY INVOKER
BEGIN

#引用前面定义的条件名称并做赋值处理
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET @x=2;
#开始事务必须在DECLARE之后
START TRANSACTION ;
SET @ID=1;
INSERT INTO Employee(id,name,depid) VALUES(7,'陈',100);
SET @ID=2;
INSERT INTO Employee(id,name,depid) VALUES(6,'陈',100);
SET @ID=3;

IF @x=2 THEN
  ROLLBACK;
ELSE
  COMMIT;
END IF;  

END$$
DELIMITER ;

#执行存储过程
CALL Pro_Employee_insert();
#查询
SELECT @ID,@X;

凤凰彩票投注网 9

通过SELECT @ID,@X能够清楚存款和储蓄进度已经施行到了最终,可是因为存款和储蓄进度前边有做回滚操作整个讲话进行了回滚,所以ID=7的切合条件的笔录也被回滚了。

(1)存款和储蓄进度在劳动器端运营,实施进程快。

凤凰彩票投注网 10

总结  

变量的行使不仅仅只有那几个,在光标中规格也是贰个很好的机能,刚才测量检验的是continue假使使用EXIT的口舌句实施完“SET @ID=2;”就不往下执行了,前面的IF也不被实施总体语句不会被回滚,可是选拔CONTINE当出现谬误后或许会往下举办假使后边的讲话还会有不菲的话整个回滚的过程将会十分长,在这里边能够行使循环,当出现错误立即退出循环实施后边的if回滚操作,在下一篇讲循环语句会写到,应接关切。

 

 

备注:

    作者:pursuer.chen

    博客:http://www.cnblogs.com/chenmh

本站点所有随笔都是原创,欢迎大家转载;但转载时必须注明文章来源,且在文章开头明显处给明链接。

《欢迎交流讨论》

变量和准星,MySQL变量条件 概述 变量在存款和储蓄进度中会平常被选用,变量的采用方法是三个根本的知识点,非常是在定义法规那块比较重...

 

那便是说存款和储蓄进程如下:

(2)存储进度实施一回后,其奉行安顿就驻留在高速缓冲存储器,在这后的操作中,只需从高速缓冲存款和储蓄器中调用已编写翻译好的二进制代码试行,升高了系统性子。

DELIMITER //
DROP PROCEDURE IF EXISTS Del_Dup_FOR_TEST;
CREATE PROCEDURE Del_Dup_FOR_TEST()
BEGIN
DECLARE min_id INT;
DECLARE v_start_time,v_end_time DATETIME;
DECLARE v_count INT;
DECLARE done INT DEFAULT 0;
DECLARE my_cur CURSOR FOR SELECT start_time,end_time,min(id),count(1) AS count FROM leo.test GROUP BY start_time,end_time HAVING count>1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN my_cur;
  myloop: LOOP
  FETCH my_cur INTO v_start_time,v_end_time,min_id,v_count;
  IF done=1 THEN
  LEAVE myloop;
  END IF;
  DELETE FROM leo.test WHERE start_time=v_start_time AND end_time=v_end_time AND id>min_id;
  COMMIT;
  END LOOP myloop;
CLOSE my_cur;
END;
//
DELIMITER ;

 

逻辑很清晰,正是根据重复判别规范依次删掉重复组中主键大于最小主键的笔录们。

(3)确定保障数据库的安全。使用存款和储蓄进程能够成功具备数据库操作,并可经过编制程序方式决定上述操作对数据库音讯访问的权能。  www.2cto.com  

而是在编写制定进程中却遇上一个很恶心的BUG,小编最先的剧情是那样写的:

 

DELIMITER //
DROP PROCEDURE IF EXISTS Del_Dup_FOR_TEST;
CREATE PROCEDURE Del_Dup_FOR_TEST()
BEGIN
DECLARE min_id INT;
DECLARE start_time,end_time DATETIME;
DECLARE count INT;
DECLARE done INT DEFAULT 0;
DECLARE my_cur CURSOR FOR SELECT start_time,end_time,min(id),count(1) AS count FROM leo.test GROUP BY start_time,end_time HAVING count>1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN my_cur;
  myloop: LOOP
  FETCH my_cur INTO start_time,end_time,min_id,count;
  IF done=1 THEN
  LEAVE myloop;
  END IF;
  DELETE FROM leo.test WHERE start_time=start_time AND end_time=end_time AND id>min_id;
  COMMIT;
  END LOOP myloop;
CLOSE my_cur;
END;
//
DELIMITER ;

2.创办存储进程能够选取create procedure语句。

不等的某些在于变量定义的名号,即:

 

FETCH INTO的变量名相对无法是你定义CUPRADOSO本田CR-V时SQL语句查出来的列名可能列别名,也就说您定义的变量名既无法是表中已经存在的列名,也不能够是你定义游标时用过的小名(如本例中的count),只要贰个规范不契合,FETCH INTO就把全数的变量赋NULL值,那一点你能够品味在FETCH INTO后加一句Select打字与印刷变量名验证。

要在MySQL 5.第11中学开创存款和储蓄进程,必得具有CREATE routine权限。要想查看数据库中有如何存款和储蓄进程,能够动用SHOW PROCEDURE STATUS命令。要翻开某个存款和储蓄进度的具体消息,可利用SHOWCREATE PROCEDURE sp_name命令,其中sp_name是储存进程的名号。

在询问到那么些BUG从前去官方网站页面特地看了须臾间是还是不是是小编的语法有不当: ,确信语法没难点,但尾数第二条争辨呈现或者是列名的隐蔽BUG,最终一条批评理论了BUG说法,但从没主意本身要么依照BUG REPORT做了以上修改,然后功用就平常了。

 

至于此BUG的BUG报告页面详见MySQL BUG:#28227 和 BUG:#5967

CREATE PROCEDURE的语法格式:

那么再回头看一下官方网站文档下的末梢一条探讨,初阶作者以为最后一条反驳BUG的褒贬完全部都是聊天,是哪个傻X说那不是个BUG的?后来精心想了想,他俩都对,那真的也算个BUG,傻X的也是自己。

 

贴一下页面下最后两条商量(结束2018.08.01):

CREATE PROCEDURE sp_name ([proc_parameter[,...]])

Posted by Brent Roady on May 9, 2012
It should be noted that the local variable names used in FETCH [cursor] INTO must be different than the variable names used in the SELECT statement 
defining the CURSOR. Otherwise the values will be NULL. 
In this example, 
DECLARE a VARCHAR(255);
DECLARE cur1 CURSOR FOR SELECT a FROM table1;
FETCH cur1 INTO a;
the value of a after the FETCH will be NULL.
This is also described here: http://bugs.mysql.com/bug.php?id=28227

Posted by Jérémi Lassausaie on February 3, 2015
Answer for Brent Roady :
I don't see any bug in the bahaviour described.
DECLARE a VARCHAR(255);
/* you declare a variable "a" without a specified default value, a=NULL */
DECLARE cur1 CURSOR FOR 
SELECT a FROM table1;
/* You declare a cursor that selects "a" FROM a table */
OPEN cur1;
/* You execute your cursor query, a warning is raised because a is ambiguously defined but you don't see it */
FETCH cur1 INTO a;
/* you put your unique field in your unique row into a (basically you do "SET a=a;") so a is still NULL */
There is no bug report, just a misunderstanding.

 

Brent蒙受的风貌与自个儿同一,并列出了BUG Report的链接。

   [characteristic ...] routine_body

Jeremi(测度只怕是个程序猿)回答,那是多个眼看的误会,当你表明了变量a(开始值为NULL),然后FETCH INTO a就一定于set a=a,在其他程序语言中那都以无解的。

 

所以在编辑存款和储蓄进度中为定义的变量加个前缀标志是很好的习于旧贯,想起在此以前Oracle写存款和储蓄进程着实都加v_前缀,SQL Server 都用@前缀,现在轮到mysql却忽略了,确实供给牢记下。

其中,proc_parameter的参数如下:

 

[ IN | OUT | INOUT ] param_name type

 

characteristic特征如下:

 

  language SQL

 

 | [NOT] DETERMINISTIC

 

 | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }

 

 | SQL SECURITY { DEFINER | INVOKER }

 

 | COMMENT 'string'

 

说明:

 

●   sp_name:存储进程的名号,暗许在现阶段数据库中创制。供给在一定数据库中成立存款和储蓄进程时,则要在名称前边加上数据库的称谓,格式为:db_name.sp_name。值得注意的是,这几个称号应当尽量幸免取与MySQL的放置函数一样的称呼,不然会生出错误。

 

 ●   proc_parameter:存款和储蓄过程的参数,param_name为参数名,type为参数的项目,当有八个参数的时候中间用逗号隔离。存款和储蓄进度能够有0个、1个或多个参数。MySQL存款和储蓄进度扶助三种档期的顺序的参数:输入参数、输出参数和输入/输出参数,关键字分别是IN、OUT和INOUT。输入参数使数码能够传递给一个仓库储存进度。当要求回到贰个答案或结果的时候,存款和储蓄进度使用输出参数。输入/输出参数不仅可以够充任输入参数也足以充任输出参数。存款和储蓄进程也能够不加参数,但是名称前边的括号是不可省略的。

 

注意:参数的名字绝不等于列的名字,不然即便不会回去出错新闻,然则存款和储蓄进程中的SQL语句会将参数名看做列名,进而吸引不可预言的结果。

 

characteristic:存款和储蓄进程的有些特点设定,下边一一介绍:

 

language sql:表明编写那些蕴藏进程的言语为SQL语言,近日来说,MySQL存款和储蓄过程还无法用外界编制程序语言来编排,相当于说,那一个选项能够不点名。今后将会对其扩大,最有相当大可能率首先个被帮忙的言语是PHP。  www.2cto.com  

deterministic:设置为DETERMINISTIC表示存款和储蓄进度对同一的输入参数产生同样的结果,设置为NOT DETERMINISTIC则代表会生出不鲜明的结果。暗中同意为NOTDETERMINISTIC。

 

contains SQL:表示存款和储蓄进度不含有读或写多少的说话。NO SQL表示存款和储蓄进程不包括SQL语句。reads SQL DATA表示存储进程包罗读数据的话语,但不带有写多少的语句。modifies SQL DATA表示存款和储蓄进度富含写多少的口舌。借使这么些特色未有明确性给定,暗中同意的是CONTAINS SQL。

 

SQL SECU奥迪Q5ITY:SQL SECU福特ExplorerITY特征能够用来钦点期存款款和储蓄进程采取创制该存款和储蓄进度的客商(DEFINEEvoque)的许可来实施,如故选取调用者(INVOKE奥迪Q5)的许可来实行。暗中同意值是DEFINECR-V。

 

COMMENT 'string':对存储进程的呈报,string为描述内容。这几个音信方可用SHOWCREATE PROCEDURE语句来展示。

 

●   routine_body:那是储存进程的本位部分,也称之为存款和储蓄进程体。里面含有了在经过调用的时候必需实行的口舌,那么些有些总是以begin起头,以end甘休。当然,当存储进度体中独有三个SQL语句时得以大约BEGIN-END标志。

 

  1.   在初叶创立存款和储蓄进度此前,先介绍一个很实用的授命,即delimiter命令。在MySQL中,服务器管理语句的时候是以分集团为了却标记的。但是在开立存款和储蓄进度的时候,存款和储蓄进程体中恐怕含有两个SQL语句,各种SQL语句都是以分集团为结尾的,那时服务器管理程序的时候蒙受第三个分集团就能够以为程序甘休,那势必是不行的。所以这里运用DELIMITE奥德赛命令将MySQL语句的了断标记修改为任何标识。

 

DELIMITECRUISER语法格式为:DELIMITE途睿欧 $$

 

表明:$$是客商定义的终结符,日常那个符号能够是部分特种的标记,如八个“#”,八个“¥”、数字、字母等都足以。当使用DELIMITE索罗德命令时,应该制止使用反斜杠(“”)字符,因为那是MySQL的转义字符。

 

例:创制存款和储蓄进度,完结的效力是删除贰个一定学生的新闻。

 

DELIMITER $$

 

CREATE PROCEDURE DELETE_STUDENT(IN XH CHAR(6))

 

BEGIN

 

DELETE FROM XS WHERE 学号=XH;

 

END $$

 

DELIMITER ;

 

证实:当调用那么些蕴藏进度时,MySQL遵照提供的参数XH的值,删除对应在XS表中的数据。

 

在非常重要字BEGIN和END之间钦定了积攒进程体,当然,BEGIN-END复合语句还是能够嵌套使用。

 

  1.  局地变量

 

在积攒进度中能够注明局地变量,它们得以用来存款和储蓄不时结果。要注明局地变量必需运用declare语句。在宣称局地变量的还要也得以对其赋八个初步值。

 

DECLARE语法格式:DECLARE var_name[,...] type [DEFAULT value]

 

说明:var_name为变量名;type为变量类型;default子句给变量钦定二个暗中认可值,假使不钦定默感到NULL的话。能够同期评释多少个门类同样的片段变量,中间用逗号隔断。

 

例: 声美赞臣个整型变量和多个字符变量。

 

DECLARE num INT(4);

 

DECLARE str1, str2 VARCHAR(6);

 

declare n char(10) default ‘abcdefg’;

 

证实:局地变量只可以在BEGIN…END语句块中声称。

 

有个别变量必须在蕴藏进度的开头就宣称,表明完后,能够在宣称它的BEGIN…END语句块中应用该变量,别的语句块中无法利用它。  www.2cto.com  

 

在蕴藏进度中也足以注明客商变量,不过千万不要将那多少个混淆。局地变量和顾客变量的差距在于:局地变量前边未有利用@符号,局地变量在其所在的BEGIN…END语句块管理完后就熄灭了,而顾客变量存在于全部会话当中。

 

  1.  使用SET语句赋值

 

要给一部分变量赋值能够选择SET语句,SET语句也是SQL自身的一部分。语法格式为:SET  var_name = expr [,var_name = expr] ...

 

例: 在蕴藏进程中给部分变量赋值。

 

SET num=1, str1= 'hello';

 

证实:与证明客户变量时差别,这里的变量名前边未有@符号。注意,例中的那条语句不可能独立实行,只好在仓库储存进程和仓储函数中动用。

 

  1. SELECT...INTO语句(重点)

 

应用那个SELECT…INTO语法能够把选定的列值直接存款和储蓄到变量中。由此,重临的结果只能有一行。语法格式为:

 

SELECT col_name[,...] INTO var_name[,...]  table_expr

 

说明:col_name是列名,var_name是要赋值的变量名。table_expr是SELECT语句中的FROM子句及末端的有的,这里不再陈述。

 

例: 在仓库储存进程体中将XS表中的学号为081101的上学的小孩子姓名和标准名的值分别赋给变量name和project。

 

SELECT 姓名,专业名 INTO name, project

 

   FROMXS;  WHERE 学号= '081101';

 

  1.  流程调节语句

 

在MySQL中,常见的进度式SQL语句能够用在叁个囤积进度体中。举个例子:IF语句、CASE语句、LOOP语句、WHILE语句、iterate语句和LEAVE语句。

 

(1)IF语句

 

IF-THEN-ELSE语句可根据差别的准则实践不相同的操作。

 

语法格式为:

 

IF 判定的尺度THEN 四个或八个SQL语句

 

[ELSEIF推断的标准化THEN二个或多少个SQL语句] ...

 

[ELSE二个或八个SQL语句]

 

END IF

 

评释:当剖断标准为真时,就实行相应的SQL语句。

 

IF语句不一致于系统的放置函数IF()函数,IF()函数只可以剖断三种情状,所以请不要混淆。

 

例: 成立XSCJ数据库的存款和储蓄进程,推断多个输入的参数哪多个越来越大。

 

DELIMITER $$  www.2cto.com  

 

CREATE PROCEDURE XSCJ.COMPAR

 

(IN K1INTEGER, IN K2 INTEGER, OUT K3 CHAR(6) )

 

BEGIN

 

IFK1>K2 THEN

 

    SET K3= '大于';

 

ELSEIFK1=K2 THEN

 

    SET K3= '等于';

 

ELSE

 

    SET K3= '小于';

 

ENDIF;

 

END$$

 

DELIMITER ;

 

证实:存款和储蓄进程中K1和K2是输入参数,K3是出口参数。

 

(2)CASE语句

 

前边已经介绍过了,这里介绍CASE语句在仓库储存进度中的用法,与从前略有差异。语法格式为:

 

CASE case_value

 

   WHEN when_value THEN statement_list

 

   [WHEN when_value THEN statement_list] ...

 

   [ELSE statement_list]

 

END CASE

 

或者:

 

CASE

 

   WHEN search_condition THEN statement_list

 

   [WHEN search_condition THEN statement_list] ...

 

   [ELSE statement_list]  www.2cto.com  

 

END CASE

 

评释:五个CASE语句平时能够出任贰个IF-THEN-ELSE语句。

 

先是种格式中case_value是要被决断的值或表明式,接下去是一多元的WHEN-THEN块,每一块的when_value参数内定要与case_value比较的值,假诺为真,就实施statement_list中的SQL语句。要是前方的每七个块都不相称就能实行ELSE块钦点的言语。CASE语句最终以END CASE甘休。

 

其次种格式中CASE关键字背后未有参数,在WHEN-THEN块中,search_condition钦赐了三个相比较表明式,表明式为真时推行THEN后边的说话。与第一种格式比较,这种格式能够实现尤其复杂的规范判定,使用起来更有益。

 

例: 创立贰个仓库储存进程,针对参数的两样,再次来到差别的结果。

 

DELIMITER $$

 

CREATE PROCEDURE XSCJ.RESULT

 

(IN str VARCHAR(4), OUT sex VARCHAR(4) )

 

BEGIN

 

 CASE str

 

   WHEN'M' THEN SET sex='男';

 

   WHEN'F' THEN SET sex='女';

 

   ELSE  SET sex='无';

 

   ENDCASE;

 

END$$

 

DELIMITER ;

 

例: 用第三种格式的CASE语句创立以上存款和储蓄进程。程序片段如下:

 

CASE

 

   WHENstr='M' THEN SET sex='男';

 

   WHENstr='F' THEN SET sex='女';

 

   ELSE  SET sex='无';

 

END CASE;

 

(3)循环语句

 

MySQL补助3条用来成立循环的语句:while、repeat和loop语句。在仓库储存进度中得以定义0个、1个或三个循环语句。

 

●   WHILE语句语法格式为:

 

[begin_label:] WHILE search_condition  DO

 

statement_list  www.2cto.com  

 

END WHILE [end_label]

 

表达:语句首先剖断search_condition是还是不是为真,不为真则奉行statement_list中的语句,然后重新张开决断,为真则继续循环,不为真则截止循环。begin_label和end_label是WHILE语句的标记。除非begin_label存在,否则end_label不可能被提交,并且只要双方都冒出,它们的名字必得是一律的。

 

例: 创制叁个带WHILE循环的积攒进度。

 

DELIMITER $$

 

CREATE PROCEDURE dowhile()

 

BEGIN

 

   DECLARE v1 INT DEFAULT5;

 

   WHILE  v1 > 0 DO

 

         SET v1 = v1-1;

 

   END WHILE;

 

END $$

 

DELIMITER ;

 

●   repeat语句格式如下:

 

[begin_label:] REPEAT

 

     statement_list

 

UNTIL search_condition

 

END REPEAT [end_label]

 

表明:REPEAT语句首先实践statement_list中的语句,然后判别search_condition是还是不是为真,为真则甘休循环,不为真则持续循环。REPEAT也可以被标注。

 

例: 用REPEAT语句创造一个如例7.9的积累进程。程序片段如下:

 

REPEAT

 

    v1=v1-1;

 

    UNTIL v1<1;

 

END REPEAT;

 

证实:REPEAT语句和WHILE语句的不同在于:REPEAT语句先实行语句,后张开判别;而WHILE语句是先判断,条件为真时才施行语句。

 

●   LOOP语句语法格式如下:

 

[begin_label:] LOOP

  www.2cto.com  

         statement_list

 

END LOOP [end_label]

 

表达:LOOP允许某一定语句或语句群的再次实施,完毕贰个回顾的循环构造,statement_list是内需重新实施的讲话。在循环内的讲话一向重复至循环被剥离,退出时常常伴随着三个LEAVE 语句。

 

LEAVE语句日常和BEGIN...END或循环一齐利用。结构如下:

 

LEAVE label ; label是话语中注明的名字,这几个名字是自定义的。加上LEAVE关键字就能够用来退出被标记的循环语句。

 

例: 创造一个带LOOP语句的囤积进度。

 

DELIMITER $$

 

CREATE PROCEDURE doloop()

 

BEGIN

 

    SET @a=10;

 

    Label: LOOP

 

          SET @[email protected];

 

          IF @a<0 THEN

 

              LEAVELabel;

 

          END IF;

 

    END LOOPLabel;

 

END$$

 

DELIMITER ;

 

循环语句中还恐怕有叁个iterate语句,它只好够出现在LOOP、REPEAT和WHILE语句内,意为“再一次循环”。它的格式为:ITERATE label

 

申明:该语句格式与LEAVE大致,不相同在于:LEAVE语句是偏离一个巡回,而ITERATE语句是双重开头贰个循环。

 

8.大家调用此存款和储蓄进度来查看最终结果。调用该存款和储蓄进程使用如下命令:CALL doloop();

 

接着,查看客户变量的值:  [email protected];

 

   语法格式:CALL sp_name([parameter[,...]])

 

说明:sp_name为存款和储蓄进程的称谓,假使要调用某些特定数据库的储存进度,则需求在前边加上该数据库的名目。parameter为调用该存款和储蓄进度选用的参数,这条语句中的参数个数必需一而再等于存款和储蓄进程的参数个数。  www.2cto.com  

 

例:创造二个仓库储存进度,有四个输入参数:XH和KCM,须求当某学生某门课程的实际业绩小于60分时将其学分修改为零,大于等于60分时将学分修改为此课程的学分。

 

DELIMITER $$

 

CREATE PROCEDURE XSCJ.DO_UPDATE(IN XHCHAR(6), IN KCM CHAR(16))

 

BEGIN

 

   DECLARE  KCH CHAR(3);

 

   DECLARE  XF TINYINT;

 

   DECLARE  CJ TINYINT;

 

 SELECT课程号, 学分 INTO KCH, XFFROM KC WHERE 课程名=KCM;

 

 SELECT成绩 INTO CJ FROM XS_KC WHERE 学号=XH AND 课程号=KCH;

 

   IF CJ<60 THEN

 

     UPDATE XS_KC SET 学分=0 WHERE 学号=XH AND 课程号=KCH;

 

   ELSE

 

     UPDATE XS_KC SET 学分=XF WHERE 学号=XH AND 课程号=KCH;

 

   END IF;

 

END$$

 

DELIMITER ;

 

  1.        存款和储蓄进度创立后须求删除时使用DROP PROCEDURE语句。

 

以前,必得承认该存款和储蓄进程未有任何借助关系,不然会招致别的与之提到的积存进度很小概运维。

 

语法格式为:  DROPPROCEDURE  [IF EXISTS] sp_name

 

说明:sp_name是要删减的蕴藏进程的名号。IF EXISTS子句是MySQL的增添,尽管程序或函数不设有,它防止爆发错误。

 

例: 删除存款和储蓄进程dowhile:DROP PROCEDURE IF EXISTS dowhile;

 

  1.  使用ALTE宝马X5 PROCEDURE语句能够修改存款和储蓄进程的一点特点。

 

语法格式为:ALTELacrosse PROCEDURE sp_name [characteristic ...]

 

其中,characteristic为:

  www.2cto.com  

{ CONTAINS SQL | NO SQL | READS SQLDATA | MODIFIES SQL DATA }

 

| SQL SECURITY { DEFINER | INVOKER }

 

| COMMENT 'string'

 

证实:characteristic是储存进度成立时的特征,在CREATE PROCEDURE语句中早就介绍过。只要设定了当中的值,存款和储蓄进程的性子就接着变动。

 

借使要修改存款和储蓄进程的开始和结果,能够行使先删除再重新定义存款和储蓄进程的方法。

 

例: 使用先删除后修改的主意修改例7.1第22中学的存储进程。

 

DELIMITER $$

 

DROP PROCEDURE IF EXISTS DO_QUERY;

 

CREATE PROCEDURE DO_QUERY()

 

BEGIN

 

SELECT * FROM XS;

 

END$$

 

DELIMITER ;

 

  ***11  现在为选看内容。。非器重!!

 

  1.  SQL语句中的错误提醒

 

在储存进程中拍卖SQL语句或许导致一条错误新闻。比如,向二个表中插入新的行而主键值已经存在,那条INSERT语句会形成伍个失误音讯,並且MySQL马上停下对存款和储蓄进程的拍卖。每一个错误消息都有贰个独一代码和三个SQLSTATE代码。举个例子,SQLSTATE 2两千属于如下的失误代码:

 

Error 1022, "Can't write;duplicate(重复) key intable"

 

Error 1048, "Column cannot benull"

 

Error 1052, "Column is ambiguous(歧义)"

 

Error 1062, "Duplicate entry forkey"

 

MySQL手册的“错误音信和代码”一章中列出了全体的失误新闻及它们分其余代码。

 

为了防止MySQL在一条错误音讯发出时就告一段落处理,须要选取到DECLAREhandler语句。该语句语句为错误代码证明了三个所谓的管理程序,它指明:对一条SQL语句的拍卖假诺形成一条错误音信,将会生出什么。

 

DECLARE HANDLEENVISION语法格式为:

 

DECLARE handler_type HANDLER FOR condition_value[,...]sp_statement

 

其中,handler_type为:

 

 Continue

 

| EXIT

 

| UNDO

 

condition_value为:

 

 SQLstate [VALUE] sqlstate_value

  www.2cto.com  

| condition_name

 

| SQLwarning

 

| NOT FOUND

 

| SQLexception

 

| mysql_error_code

 

说明:

 

●   handler_type:管理程序的档期的顺序,主要有两种:CONTINUE、EXIT和UNDO。对CONTINUE管理程序,MySQL不停顿存款和储蓄进度的管理。对于EXIT管理程序,当前   BEGIN...END复合语句的实施被截止。UNDO管理程序类型语句临时还不被扶助。

 

●  condition_value:给出SQLSTATE的代码表示。

 

   condition_name是拍卖标准的称号,接下去会讲到。

 

   SQLWA奥迪Q3NING是对持有以01最初的SQLSTATE代码的笔记。NOT FOUND是对具有以02发端的SQLSTATE代码的笔记。SQLEXCEPTION是对全体未有被SQLWA奥迪Q3NING或NOT FOUND捕获的SQLSTATE代码的笔记。当顾客不想为每种可能的失误新闻都定义二个管理程序时能够利用上述二种样式。

 

mysql_error_code是现实的SQLSTATE代码。除了SQLSTATE值,MySQL错误代码也被支持,表示的款式为:E途睿欧RO卡宴= 'xxxx'。

 

●   sp_statement:管理程序激活时将在推行的动作。

 

例: 创造三个存款和储蓄进度,向XS表插入一行数据('081101', '王民', 'Computer', 1, '壹玖捌捌-02-10',50 , NULL, NULL),已知学号081101在XS表中已存在。若是出现错误,程序继续拓宽。

 

USE XSCJ;

 

DELIMITER $$

 

CREATE PROCEDURE MY_INSERT ()

 

BEGIN

 

   DECLARECONTINUE HANDLER FOR SQLSTATE '23000' SET @x2=1;

 

   [email protected]=2;

 

   INSERTINTO XS VALUES('081101', '王民', '计算机', 1, '1990-02-10', 50 , NULL, NULL);

 

   [email protected]=3;  www.2cto.com  

 

END$$

 

DELIMITER ;

 

注脚:在调用存款和储蓄进度后,未相见错误新闻时管理程序未被激活,当施行INSERT语句现身出错新闻时,MySQL检查是不是为那一个错误代码定义了管理程序。假若有,则激活该管理程序,本例中,INSERT语句导致的荒谬音信刚好是SQLSTATE代码中的一条。接下来施行处理程序的附加语句(SET @x2=1)。此后,MySQL检查管理程序的门类,这里的门类为CONTINUE,由此储存进度持续管理,将客户变量x赋值为3。假使这里的INSERT语句可以施行,管理程序将不被激活,客商变量x2将不被赋值。

 

在乎:不能为同三个弄错信息在同一个BEGIN-END语句块中定义八个或更加多的管理程序。

 

为了增加可读性,能够接纳DECLARE CONDITION语句为多少个SQLSTATE或出错代码定义贰个名字,并且能够在处理程序中应用那一个名字。

 

DECLARE CONDITION语法格式为:

 

DECLARE condition_name CONDITION FORcondition_value

 

其中,condition_value:

 

 SQLSTATE [VALUE] sqlstate_value

 

| mysql_error_code

 

说明:condition_name是拍卖典型的称呼,condition_value为要定义小名的SQLSTATE或出错代码。

 

例: 修改上例中的存款和储蓄进度,将SQLSTATE '2两千' 定义成NON_UNIQUE,并在处理程序中动用这一个称谓。程序片段为:

 

BEGIN

 

   DECLARE NON_UNIQUE CONDITION FOR SQLSTATE '23000';

 

   DECLARE CONTINUE HANDLER FOR NON_UNIQUE SET @x2=1;

 

   SET @x=2;

 

   INSERT INTO XS VALUES('081101', '王民', '计算机', 1, '1990-02-10', 50 , NULL, NULL);

 

   SET @x=3;  www.2cto.com  

 

END;

 

  1.  游标

 

一条SELECT...INTO语句重回的是带有值的一行,那样能够把多少读取到存款和储蓄进程中。可是常规的SELECT语句重回的是多行数据,借使要管理它需求引进游标这一定义。MySQL帮助简单的游标。在MySQL中,游标应当要在仓库储存进度或函数中应用,不能独立在查询中利用。

 

选拔壹个游标须要用到4条卓绝的语句:DECLARE CU奥迪Q5SOMurano(注解游标)、OPEN CU福睿斯SO陆风X8(打开游标)、FETCH CUEvoqueSO哈弗(读取游标)和CLOSE CULacrosseSO大切诺基(关闭游标)。

 

设若利用了DECLARE CUQashqaiSOR语句注解了三个游标,那样就把它总是到了一个由SELECT语句再次来到的结果聚集。使用OPEN CORubiconSO奥迪Q7语句张开这几个游标。接着,能够用FETCH CUHavalSO瑞虎语句把爆发的结果一行一行地读取到存款和储蓄进程或存款和储蓄函数中去。游标也正是三个指针,它指向当前的一行数据,使用FETCH COEnclaveSO奥迪Q5语句能够把游标移动到下一行。当管理完全体的行时,使用CLOSECU大切诺基SOOdyssey语句关闭那几个游标。

 

(1)注明游标

 

语法格式:DECLAREcursor_name cursor for select_statement

 

说明:cursor_name是游标的名目,游标名称使用与表名同样的条条框框。select_statement是三个SELECT语句,重回的是单排或多行的数目。那几个讲话声澳优(Ausnutria Hyproca)个游标,也足以在积存进程中定义多个游标,可是二个块中的每多少个游标必需有独一的名字。

 

瞩目:这里的SELECT子句不可能有INTO子句。

 

下边包车型客车定义相符一个游标证明:

凤凰彩票投注网, 

DECLARE XS_CUR1 CURSOR FOR

 

   SELECT 学号,姓名,性别,出出生之日期,总学分

 

       FROM XS

 

       WHERE 专业名 = '计算机';

 

瞩目:游标只可以在存款和储蓄进度或存款和储蓄函数中动用,例中语句不可能独立运维。

 

(2)张开游标

 

扬言游标后,要选用游标从当中提取数据,就亟须先张开游标。在MySQL中,使用OPEN语句打开游标,其格式为:OPEN cursor_name

 

在程序中,多少个游标能够张开多次,由于别的的顾客或程序自个儿已经更新了表,所以每一遍展开结果可能两样。  www.2cto.com  

 

(3)读取数据

 

游标张开后,就能够利用fetch…into语句从中读取数据。

 

语法格式:FETCH cursor_nameINTO var_name [, var_name] ...

 

注解:FETCH ...INTO语句与SELECT...INTO语句具备一样的意义,FETCH语句是将游标指向的一整套数据赋给一些变量,子句中变量的数码必需等于阐明游标时SELECT子句中列的数额。var_name是寄放数据的变量名。

 

(4)关闭游标

 

游标使用完之后,要及时关门。关闭游标使用CLOSE语句,格式为:

 

CLOSE cursor_name语句参数的含义与OPEN语句中同样。

 

例如: CLOSE XS_CU奔驰M级2  将关门游标XS_CUR2。

 

例: 创立叁个存款和储蓄进程,计算XS表中央银行的多寡。

 

DELIMITER $$

 

CREATE PROCEDURE compute (OUT NUMBERINTEGER)

 

BEGIN

 

   DECLAREXH CHAR(6);

 

   DECLAREFOUND BOOLEAN DEFAULT TRUE;

 

   DECLARENUMBER_XS CURSOR FOR

 

     SELECT学号 FROM XS;

 

   DECLARECONTINUE HANDLER FOR NOT FOUND

 

     SETFOUND=FALSE;

 

   SETNUMBER=0;

 

   OPENNUMBER_XS;

 

   FETCHNUMBER_XS INTO XH;

  www.2cto.com  

   WHILEFOUND DO

 

     SETNUMBER=NUMBER+1;

 

     FETCHNUMBER_XS INTO XH;

 

   ENDWHILE;

 

   CLOSENUMBER_XS;

 

END$$

 

DELIMITER ;

 

 

作者 tianyazaiheruan

1. 利用存款和储蓄进度的长处有: (1)存款和储蓄进度在劳动器端运转,实行进程快。 (2)存款和储蓄过程施行三次后,其试行设计就...

本文由凤凰平台注册开户发布于MySQL数据库,转载请注明出处:MySQL游标循环取出空值的BUG,变量和条件

关键词:

上一篇:没有了
下一篇:没有了