一、SQL语言基础
1.1 常量与变量
常量也称为文字值或标量值,是指程序运行中始终不变的量。在 SQL 程序设计过程中,定义常量的格式取决于它所表示的值的数据类型。
常量类型 | 常量表示说明 |
字符串常量 | 包括在单引号或双引号中,由字母(a~z,A~Z)、数字(0~9)、特殊符号组成。 |
十进制整型常量 | 使用不带小数点的十进制数据表示。示例:1234、321、+123、-123 |
十六进制整型常量 | 使用前缀0x后跟十六进制数字串表示。 |
日期常量 | 使用单引号将日期时间字符串括起来。MySQL是按年-月-日的顺序表示日期的。中间分隔符可以用-,也可以用/、\、@、%等特征符号。 |
实型常量 | 有定点表示和浮点表示两种方式。示例:123.4、-123.4、19E24、-83E2 |
位字段值 | 使用b'value'符号写位字段值。value是一个用0和1写成的二进制值。例如:b'0'显示空白,b'1'显示一个笑脸图标。示例:select bin(b'111101'+0),oct(b'111101'+0) |
布尔常量 | 布尔常量只包含两个可能的值:TRUE和FALSE。FALSE的数字值为0,TRUE的数字值为1。 |
NULL值 | NULL可适用于各种列类型,它通常表示'没有值'、'无数据'等意义,并且不同于数字类型的0或字符串类型的空字符床。 |
变量就是在程序执行的过程中,其值是可变的。在MySQL中,存在三种类型的变量:
- 系统变量
- 用户变量
- 局部变量
系统变量可以分为全局(global)变量和会话(session)变量两种。
1.1.1 全局变量和会话变量
全局变量由MySQL启动时由服务器自动将它们初始化为默认值,这些默认值可以通过更改 my.ini 文件来更改。
会话变量在每次建立一个新的链接的时候,由MySQL来初始化。MySQL会将当前所有全局变量的值复制一份作为会话变量。也就是说,如果在建立会话以后,没有手动更改过全局变量和会话变量的值,所有这些变量的值都是一样的。
全局变量和会话变量区别在于,全局变量主要影响整个MySQL实例的全局配置。大部分全局变量都作为MySQL的服务器调节参数存在。对全局变量的修改会影响到整个服务器,但是对会话变量的修改,只会影响到当前会话,也就是当前数据的连接。
大多数的系统变量应用于其他SQL语句中时,必须在名字前加两个@符号,而为了与其他产品保持一致,某些特定的系统变量是要省略这两个@符号的。
CURRENT_DATE -- 系统日期 CURRENT_TIME -- 系统时间 CURRENT_TIMESTAMP -- 系统日期和时间 CURRENT_USER -- SQL用户的名字 @@VERSION -- 当前MySQL版本信息 例子: select @@version as '当前MySQL的版本', current_date;
a.显示系统变量清单
SHOW VARIABLES --显示系统变量清单 语法: show [global|session] variables [like '字符串']; -- 字符串可以使用通配符"%"和"_"。 show global variables; -- 显示所有的全局变量, 如果global缺省,默认显示会话变量 show variables like 'a%'; -- 显示已a开头的所有全局变量
b.修改系统变量的值
在MySQL中,有些系统变量的值是不可修改的,比如@@VERSION和系统日期。而有些系统变量可以通过 SET 语句来修改,其语法格式如下:
SET system_var_name = expression | [global | session] system_var_name = expression | @@ [global. | session.] system_var_name = expression;
其中,system_var_name 为系统变量名,expression为系统变量设定的新值。名称的前面可以添加global或session等关键字。
指定了global或@@global.关键字的是全局系统变量,指定了session或@@session.关键字的是会话系统变量,session和@session.与local和@@local.的含义是一样的。如果在使用系统变量时不指定关键字,则默认为会话变量。
想要更改全局变量的值,需要拥有SUPER权限。
例子:将全局系统变量sort_buffer_size的值改为250000。
SET @@global.sort_buffer_size = 250000;
例子:对于当前会话,把系统变量 SQL_SELECT_LIMIT 的值设置为100。
SET @@SESSION.SQL_SELECT_LIMIT = 100; SELECT @@LOCAL.SQL_SELECT_LIMIT;
上面这个例子中,关键字SESSION放在系统变量的名字前面(SESSION和LOCAL可以通用)。这明确表示会话系统变量 SQL_SELECT_LIMIT 和 SET 语句语句指定的值一致。但是,名为 SQL_SELECT_LIMIT 的全局系统变量的值仍然不变。同样地,改变了全局系统变量的值,同名的会话系统变量的值保持不变。
如果想将一个系统变量的值设置为MySQL的默认值,可以使用default关键字。
SET @@LOCAL.SQL_SELECT_LIMIT = DEFAULT;
1.1.2 用户变量
用户可以在表达式在使用自己定义的变量,这样的变量叫做用户变量。
用户可以现在用户变量中保存值,然后再引用它,这样可以将值从一个语句传递到另一个语句。在使用用户变量之前,必须定义和初始化。如果使用没有初始化的变量,它的值为 NULL。
用户变量和连接有关。也就是说,一个客户端定义的变量不能被其他客户端看到或使用。当客户端退出时,该客户端连接的所有变量将释放。用户变量被引用时要在其名称前加上标志@。
定义和初始化一个用户变量可以使用 SET 或 SELECT 语句,其语法格式大致如下:
SET @user_variable1 [:] = expression1 [, variable2 = expression2, ...];
或
SELECT @user_variable1 : = expression1 [, variable2 = expression2, ...];
其中,user_variable1、user_variable2为用户变量名,用户变量名可以由当前字符集的文字数字字符、'.'、'_'和'$'组成。当变量名中需要包含一些特殊符号(比如空格、#等)时,可以使用双引号或单引号将整个变量括起来。expressiion1、expression2为要给变量赋的值,可以是常量、变量或表达式。
对于 SET 语句,可以使用'='或':='作为分配符。分配给每个变量的值可以是整数、实数、字符串或 NULL 值。也可以用 SELECT 语句代替 SET 语句来为用户变量分配一个值。在这种情况下,分配符必须是':=',而不能是'=',因为在非 SET 语句中'='被视为比较操作符。
例:创建用户变量name并赋值为"小明"。
SET @name = '小明'; 或 SELECT @name := '小明';
@符号必须放在一个用户变量的前面,以便将它和列名区分开。
SET @user1 = 1, @user2 = 2, @user3 = 3;
查询用户变量
SELECT @USER1, @user2, @user3, @name;
1.1.3 局部变量
局部变量的作用范围在begin...end的语句块中。可以使用declare语句进行定义,然后可以为变量进行赋值。赋值的方法和用户变量相同。但与用户变量不同的是,用户变量是以'@'开头,局部变量不用该符号。需要注意的是,局部变量与begin...end语句块、控制流程语句只能用于、存储过程、触发器和事务的定义中。
在MySQL中,定于局部变量的方法如下:
DECLARE var_name [, ...] type [DEFAULT value];
其中,var_name是局部变量的名称,这里可以同时定义多个变量。type,用来指定变量的类型。DEFAULT value子句将变量默认值设为value,没有使用DEFAULT子句,默认值为NULL;
例:变量名myvar,数据类型int,默认值为10.
DECLARE myvar =int DEFAULT 10;
例:给局部变量myvar赋值100.
SET myvar = 100;
1.2 表达式
在SQL语言中,表达式就是常量、变量、列名、复杂计算、运算符和函数组成。一个表达式通常都有返回值。与常量和变量一样,表达式的值也具有某种数据类型。根据表达式值的类型,表达式可以分为字符串表达式、数值表达式和日期型表达式。
1.3 SQL 流程控制语句
结构化程序设计语言的基本结构是顺序结构、条件分支结构和循环结构。顺序结构是一种自然结构,条件分支结构和循环结构需要根据程序的执行情况对程序的执行顺序进行调整和控制。在 SQL 语言中,流程控制语句就是用来控制程序执行流程的语句,也称流控制语句或控制流语句。在MySQL中,这些流程控制语句和局部变量只能在存储过程或函数、触发器、事务的定义中。
1.3.1 BEGIN...END 语句块
BEGIN...END 可以定义SQL语句块,这些语句块作为一组语句执行,允许语句嵌套。关键之 BEGIN 定义 SQL 语句的起始位置,END定义 SQL语句的结尾。
BEGIN { sql_statement|statemen_block; } END;
其中,sqlz_statement是使用语句块定义的任何有效的 SQL 语句;statement_block是使用语句块定义的任何有效的 SQL语句块。
1.3.2 IF...ELSE 条件语句
用于指定 SQL 语句的执行条件。如果条件为真,这执行条件表达式后面的 SQL 语句。当条件为假,则用 ELSE 关键字指定要执行的 SQL 语句。
IF search_condition THEN
statement_list
[ELSEIF search_condition THEN statement_list] ...
[ELSE statement_list]
END IF;
其中,search_condition是反馈 true 或 false 的逻辑表达式。如果逻辑表达式含有 SELECT 语句,必须要括号将 SELECT 语句括起来。
例:查询计算机系的办公室位置。如果查询结果为空,则显示"办公地点不详",否则显示其办公地点。
IF (select office from department where deptname = '计算机工程系') is null THEN BEGIN select '办公地点不详' as '办公地点'; END; ELSE select office from department where deptname = '计算机工程系'; END IF;
if...else语句进行嵌套,即在 SQL 语句块可能包含一个或多个if...else语句。
1.3.3 CASE 分支语句
CASE 关键字可根据表达式的真假来确定是否返回某个值,可以允许使用表达式的的任何位置使用这一关键字。使用 CASE 语句可以进行多个分子的选择,CASE 语句具有如下两种格式。
简单格式:将某个表达式与一组简单表达式进行比较以确定结果。
CASE input_expression
WHEN when_expression THEN result_expression;
[...n]
[ELSE else_result_expression;]
END CASE;
上述语句说明如下:
a. input_expression:使用 CASE 语句时所计算的表达式,可以是任何有效的表达式。
b. when_expression:用来和input_expression表达式作比较的表达式,input_expression和每个 when_expression表达式的数据类型必须相同,或者可以隐形转换。
c. result_expression:指当inpue_expression=when_expression取值为true时,需要反馈的表达式。
d. else_result_expression:指当inpue_expression=when_expression取值为false时,需要反馈的表达式。
搜索格式:计算一组布尔表达式以确定结果。
CASE
WHEN Boolean_expression THEN result_expression
[...n]
[ELSE else_result_expression;]
END CASE;
语句中参数的含义与 CASE 简单结果的参数含义类似。
例:统计学生不及格门数,利用 CASE 语句显示档次。
declare dj int default 0; SELECT count(*) into dj from sc WHERE degree<60; CASE WHEN dj >= 100 THEN SELECT '不及格门数较多' AS '档次'; WHEN dj >= 50 AND dj < 100 SELECT THEN '不及格门数一般' AS '档次'; WHEN DJ > 1 AND dj < 50 THEN SELECT '不及格门数较少' AS '档次'; ELSE SELECT '没有不及格的' AS '档次'; END CASE;
1.3.4 循环语句
a. WHILE...END WHILE语句
WHILE语句是设置重复执行 SQL 语句或语句块的条件。当指定的条件为真时,重复执行循环语句。可以在循环体内设置 LEAVE 和 ITERATE 语句,以便控制循环语句的执行过程。
[begin_label:] WHILE Boolean_expression DO {sql_statement|statement_block}; [LEAVE bgein_label;] {sql_statement|statement_block}; [ITERATE begin_label;] {sql_statement|statement_block}; END WHILE;
LEAVE begin_label:用于从 WHILE 循环中退出,将执行出现在 END WHILE 关键字后面的任何语句块,END WHILE 关键字为循环结束标记。
ITERATE begin_label:用于跳出本次循环,然后直接进入下一次循环,忽略 ITERATE 语句后的任何语句。
例:使用 WHILE 语句求和
SET @i = 1, @sum = 0; WHILE @i <= 100 DO BEGIN SET @sum = @sum + @i; SET @i = @i + 1; END; END WHILE; SELECT @sum;
和 IF...ELSE 语句一样,WHILE 语句也可以嵌套,即循环体仍然可以包含一条或多条 WHILE 语句。
b. REPEAT...END REPEAT 语句
REPEAT语句是在执行操作后检查结果。而 WHILE 语句则是执行前进行检查。
[begin_label:] REPEAT {sql_statement|statement_block}; [LEAVE begin_label;] {sql_statement|statement_block}; [ITERATE begin_label;] {sql_statement|statement_block}; UNTIL Boolean_expression END REPEAT;
例:求和
SET @i = 1, @sum = 0; REPEAT BEGIN SET @sum = @sum + @i; SET @i = @i + 1; END; UNTIL @i > 100 END REPEAT; SELECT @sum;
c. LOOP...END LOOP语句
LOOP 语句可以使某些特定的语句重复执行,实现一个简单的循环。但是 LOOP 语句本身没有停止循环的语句,必须是遇到 LEAVE 语句才能停止循环。
begin_label: LOOP {sql_statement|statement_block}; LEAVE begin_label; {sql_statement|statement_block}; [ITERATE begin_label;] {sql_statement|statement_block}; END LOOP;
例:求和
SET @i= 1, @sum = 0; add_sum: LOOP BEGIN SET @sum = @sum + 1; SET @i = @i + 1; END; IF @i > 100 THEN LEAVE add_sum; END LOOP; SELECT @sum;
1.4 条件和处理程序的定义
特定条件需要特定处理。这些条件可能涉及错误以及子程序中的一般控制流程。定义条件和处理程序是事先定义程序执行过程中可能遇到的问题,并且可以在处理程序中定义解决这些问题的办法。这种方式可以提前预测可能出现的问题,并提出解决办法,这样可以增强程序处理问题的能力,避免程序异常停止。MySQL中都是通过 DECLARE 关键字来定义条件和处理程序。
1.4.1 定义条件
MySQL中都是通过 DECLARE 关键字来定义条件和处理程序。
DECLARE condition_name CONDITION FOR condition_value;
condition_value:
SQLSTATE [VALUE] sqlstate_value | mysql_error_code;
其中,condition_name 表示条件的名称。condition_value 表示条件的类型,有sqlstate_value参数和mysql_error_code参数,都可以表示MySQL的错误。sqlstate_value表示长度为5的字符串类型错误代码,mysql_error_code表示数值类型错误代码。
例如ERROR 1146(42S02)中,sqlstate_value的值是42S02,mysql_error_code的值是1146。
例:定义错误 "ERROR 1146(42S02)"的名称为can_not_find。
# 方法一:使用sqlstate_value DECLARE con_not_find CONDITION FOR SQLSTATE '42S02'; # 方法二:使用mysql_error_code DECLARE can_not_find CONDITION FOR 1146;
1.4.2 定义处理程序
MySQL中可以使用DECLARE 关键字定义处理程序。
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 参数指明错误的处理方式,该参数有3个取值。这三个值分别是CONTINUE、EXIT、UNDO,CONTINUE表示遇到错误不进行处理,继续向下执行;EXIT表示与到错误后,马上退出;UNDO表示遇到错误后撤回之前的操作,MySQL中暂时还不支持UNDO这种处理方式。
通常情况下,执行过程中遇到错误应当立即停止执行下面的语句,并且撤回前面的操作。但是,MySQL中现在还不能支持UNDO操作。因此,遇到错误时最好执行EXIT操作。如果事先能够预测错误类型,并进行相应的处理,那么可以执行CONTINUE操作。
condition_value 参数指明错误类型,该参数有6个取值。
a. SQLSTATE [VALUE] sqlstate_value:包含5个字符的字符串错误值。
b. condition_name: 表示有 DECLARE CONDITION 定义的错误条件名称。
c. SQLWARNING:表示所有已01开头的sqlstate_value.
d. NOT FOUND: 表示所有已02开头的sqlstate_value值。
e. SQLEXCEPTION:表示所有没有对SQLWARNING或NOT FOUND 捕获的sqlstate_value值。
f. mysql_error_code:表示数据类型错误代码。
sp_statement参数表示一些存储过程或函数的执行语句。在遇到定义的错误时,需要执行的存储过程或函数。
下面是定义处理程序的几种方式,代码如下:
#方法1:捕获sqlstate_value DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SET @info = 'CAN NOT FIND'; #方法2:捕获mysql_error_code DECLARE CONTINUE HANDLER FOR 1146 SET @info = 'CAN NOT FIND'; #方法3:先定义条件,然后调用 DECLARE can_not_find CONTINUE FOR 1146; DECLARE CONTINUE HANDLER FOR can_not_find SET @info = 'CAN NOT FIND'; 方法4:使用SQLWARNING DECLARE NXIT HANDLER FOR SQLWARNING SET @info = 'CAN NOT FIND'; 方法5:使用NOT FOUND DECLARE NXIT HANDLER FOR NOT FOUND SET @info = 'CAN NOT FIND'; 方法6:使用SQLEXCEPTION DECLARE NXIT HANDLER FOR EXCEPTION SET @info = 'CAN NOT FIND';
上述代码是6种定义处理程序的方法。
方法1:捕获sqlstate_value值。如果遇到sqlstate_value的值为42S02,执行 CONTINUE 操作,并且输出 "CAN NOT FIND" 信息。
方法2:捕获 mysql_error_code 值。如果遇到 mysql_error_code的值为1146,执行 CONTINUE 操作,并且输出 "CAN NOT FIND" 信息。
方法3:先定义条件,然后再调用条件。这里先定义can_not_find条件遇到1146错误就执行CONTINUE操作。
方法4:使用SQLWARNING。SQLWARNING捕获所有以01开头的sqlstate_value值,然后执行 EXIT 操作,并输出 "CAN NOT FIND" 信息。
方法5:使用 NOT FOUND。NOT FOUND 捕获所有以02开头的sqlstate_value值,然后执行 EXIT 操作,并输出 "CAN NOT FIND" 信息。
方法6:使用 SQLEXCEPTION。SQLEXCEPTION捕获所有没有被SQLWARNING或NOT FOUND 捕获的sqlstate_value值,然后执行 EXIT 操作,并且输出 "ERROR" 信息。
例:定义条件和处理程序,具体代码如下:
-- 首先建立测试表test mysql>CREATE TABLE test (t1 int, primary key(t1)); mysql>DELIMITER // 重新定义命令结束符为// mysql>CREATE FORCEDURE handlertest() ->BEGIN ->DECLARE CONTINUE handler FOR SQLSTATE '23000' SET @X1=1; ->SET @x = 1; ->INSERT INTO test VALUES(1); ->SET @X=2; ->INSERT INTO test VALUES(1); ->SET @X=3; ->SELECT @x,@x1; ->END; ->// mysql>DELIMITER; -- 恢复原来的命令结束符; /* 调用存储过程 */ mysql>CALL handlertest(); +----+-----+ | @x | @x1 | +----+-----+ | 3 | 1 | +----+-----+
通过执行结果可以看出,程序执行完毕。如果没有 "DECLARE CONTINUE handler FOR SQLSTATE '23000' SET @x1=1;" 这一行,第二个INSERT语句因为PRIMARY KEY 强制而操作失败,MySQL会采取默认 (EXIT)处理方式,并且@x会返回2。
mysql> CALL handlertest(); 1062 - Duplicate entry '1' for key 'PRIMARY' mysql> select @x; +----+ | @x | +----+ | 2 | +----+
1.5 注释
注释是程序代码中不被执行的代码字符串,用于对代码进行说明或进行诊断的部分语句。在MySQL系统中,支持3中注释方法,即井字符(#)注释方式,双连线(--)注释方式和正斜杠星号字符(/*...*/)注释方式。
a. 井字符(#):从井字符当行尾都是注释内容。
b. 双连线字符(--):从双连线字符到行尾都是注释内容。注意:双连线后一定要加一个空格。
c. 正斜杠星号字符(/*...*/):开始注释对(/*)和结束注释对(*/)之间的所有内容均视为注释。
结束!