MySQL8.0与SQL server 2017都是关系型数据库,两者在原理与技术方面有极高的相似度。本文主要简述笔者在学习过程中发现的两者在变量和循环处理方面的异同点,如果读者知道还有其他区别的点,欢迎进行评论补充,大家一起交流学习,共同成长!
一、在SQL server 中,T-SQL 使用 DECLARE 语句声明变量,使用 SET 或 SELECT 语句给变量赋值。T-SQL 对变量的定义具有下列特殊的规则和要求:所有 T-SQL 变量名必须以 @ 开始,局部变量使用 @ 为前缀,而全局变量使用 @@ 为前缀。可用多条 DELCARE 语句定义多个变量,也可以在单条 DECLARE 语句中定义多个变量(变量之间用逗号分隔),例如:DECLARE @Prodname varchar(60),@Pid integer。所有变量在声明后其初始值均为 NULL 。注意,在 GO 语句之后,此前定义的变量全部失效。
可使用 SET 语句和 SELECT 语句给变量赋值,但这两个语句存在一些差异: SET 只能给单个变量赋值,要赋值给多个变量必须使用多条 SET 语句,而 SELECT 可在单条语句中给多个变量赋值。
DECLARE @Minprice money, @Maxprice money
/* 示例 1:使用两条 SET 语句给变量赋值。*/
SET @Maxprice=(SELECT MAX(UnitPrice) FROM Products)
SET @Minprice=(SELECT MIN(UnitPrice) FROM Products)
/* 使用一条 SELECT 语句将查询结果赋值给两个变量。*/
SELECT @Maxprice=MAX(UnitPrice), @Minprice=MIN(UnitPrice) FROM Products
/* 示例 2:如果单价为 10 的产品有 3 个,则不能使用 SET 赋值,因此下列 SET 语句运行出错。*/
DECLARE @ProductName varchar(30)
--SET @ProductName=(SELECT ProductName FROM Products Where UnitPrice=10)
/* 如果单价为 10 的产品有 3 个,使用 SELECT 语句赋值,这时变量被赋值三次,但最终
存放的是最后一个单价为 10 的产品名称,它覆盖了前两次的赋值。*/
SELECT @ProductName=ProductName FROM Products Where UnitPrice=10
PRINT @ProductName
二、MySQL 变量主要有用户自定义变量和系统变量两种类型。用户自定义变量又分为局部变量和用户变量,系统变量又分为全局变量和会话变量。这里不对系统变量展开讨论。
1.局部变量
MySQL 的局部变量类似于其他程序设计语言上用户自己定义的变量。局部变量用 declare语句声明,需要指定其数据类型,其作用范围在 begin 与 end 语句块之间。局部变量只能在存储过程、用户定义函数、游标和触发器的程序块中使用。
注意,MySQL 局部变量名称不能以@符号开头,每个变量声明语句必须以分号(;)结尾。 一条declare语句中可以定义多个数据类型相同的局部变量,变量之间用逗号分隔,例如:
declare x, y, z int;
declare s1, s2 varchar(255);
但不同数据类型的变量不能在单条 declare 语句中定义。例如:declare x int,y varchar(255);
这样声明变量是错误的。
所有局部变量在声明后其初始值均为 NULL,但在声明局部变量时可以为变量指定一个默认值(或称为初值)。例如,下列语句在声明变量时设置了一个默认值,这时三个变量的初值均为 100。同时为了避免局部变量名与表的列名之间的相互混绕,建议在定义局部变量时为其添加一个$前缀,declare $x, $y, $z int default 100;
2. 用户变量
用户变量以@为前缀命名,其作用范围为当前连接,即在整个 MySQL 连接过程中一直有效。用户变量在使用之前不能使用 declare 语句进行声明,而是直接对它赋值使用。
局部变量和用户变量的赋值方式相同,用 set 语句或 select 语句赋值,一条语句可以为多个变量赋值。例如:
set @x=100, @y:=200; SELECT @x:=100, @y:=200; 要注意的是,set 语句赋值时,使用“:=”(注意:冒号与等号之间不能有空格)或者“=”的方式都是可行的。而select语句赋值时,不能使用“=”的方式进行赋值,这虽然不会报错,但是并没有成功赋值。
/* 下列语句使用 3 条 SET 语句分别赋值 3 个变量。*/
set @x=(SELECT min(Unitprice) FROM Products where CategoryID='B');
set @y=(SELECT max(Unitprice) FROM Products where CategoryID='B');
set @z=(SELECT count(*) FROM Products where CategoryID='B');
/* 下列语句一次性赋值给 3 个变量。*/
SELECT min(Unitprice), max(Unitprice), count(*) into @x, @y, @z FROM Products
where CategoryID='B';
/* 下列语句在赋值给变量的同时也显示变量值。由于@x是使用“=”方式赋值,这是错误的赋值方式,其结果显示是0*/
SELECT @x=min(Unitprice), @y:=max(Unitprice), @z:=count(*) FROM Products where
CategoryID='B';
/* 下列语句在赋值给变量的同时也可以使用标题别名。*/
SELECT @x:=min(Unitprice) as x, @y=max(Unitprice) as y, @z:=count(*) as z FROM Products where CategoryID='B';
/* 当 SELECT 语句返回结果多余一行时,使用 SET 语句或 SELECT…INTO 方式赋值都会出现运行错误。
而第三条语句运行之后,@s 变量中的值为最后一个商品的商品名称。*/
--错误语句:set @s=(SELECT Productname FROM Products where CategoryID='B');
--错误语句:SELECT Productname into @s FROM Products where CategoryID='B';
SELECT @s:=Productname FROM Products where CategoryID='B';
三、 在SQL server 中,T-SQL 循环由 WHILE 语句完成。在 WHILE 语句中需要设置重复执行SQL 语句或语句块的条件。只要指定的条件为真,就重复执行语句,但可以使用 BREAK 和CONTINUE 控制 WHILE 循环中语句的执行。 WHILE 只重复跟在它后面的单条语句,如果要重复多行代码,可使用BEGIN 和 END 限定该语句块。
declare @sum int,@i int
set @sum=0
set @i=1
WHILE (@i<=1000) begin
set @sum=@sum+@i
set @i=@i+1
end
四、与其它程序设计语言一样,MySQL 支持循环,能够根据需要重复一个语句块。MySQL 循环有 WHILE DO ... END WHILE、REPEAT ... END REPEAT 和 LOOP ... END LOOP 三种形式。在循环语句中需要设置重复执行 SQL 语句或语句块的条件。只要指定的条件为真,就重复执行语句,但可以使用 BREAK 和 CONTINUE 控制 WHILE 循环中语句的执行。 T-SQL 循环也是可以嵌套的,如果嵌套了两个或多个 WHILE 循环,则内层的 BREAK 将退出到下一个外层循环。
1.先判断条件是否为真,条件为真时执行 SQL 语句,否则条件不成立时退出循环。
begin
declare $sum int default 0;
declare $i int;
set $i=1;
WHILE $i<=1000 DO
set $sum=$sum+$i;
set $i=$i+1;
END WHILE;
end
2.先执行 SQL 语句,再判断条件是否为真,当 until 条件为真时结束循环。
begin
declare $sum int default 0;
declare $i int;
set $i=1;
REPEAT
set $sum=$sum+$i;
set $i=$i+1;
UNTIL $i>1000 END REPEAT;
end
3.无限循环直到结束标识 leave 终止循环,当 leave 生效时,确定终止循环。 这个循环不太好理解。
begin
declare $sum int default 0;
declare $i int;
set $i=1;
point1:LOOP
set $sum=$sum+$i;
if ($i>=1000) then LEAVE point1;
end if;
set $i=$i+1;
END LOOP;
end