整型数
类型 |
占用的存储空间(单位:字节) |
无符号数取值范围 |
有符号数取值范围 |
含义 |
TINYINT |
1 |
0 ~ 2⁸-1 |
-2⁷ ~ 2⁷-1 |
非常小的整数 |
SMALLINT |
2 |
0 ~ 2¹⁶-1 |
-2¹⁵ ~ 2¹⁵-1 |
小的整数 |
MEDIUMINT |
3 |
0 ~ 2²⁴-1 |
-2²³ ~ 2²³-1 |
中等大小的整数 |
INT (别名:INTEGER ) |
4 |
0 ~ 2³²-1 |
-2³¹ ~ 2³¹-1 |
标准的整数 |
BIGINT |
8 |
0 ~ 2⁶⁴-1 |
-2⁶³ ~ 2⁶³-1 |
大整数 |
浮点数
类型 |
占用的存储空间(单位:字节) |
绝对值最小非0值 |
绝对值最大非0值 |
含义 |
FLOAT |
4 |
±1.175494351E-38 |
±3.402823466E+38 |
单精度浮点数 |
DOUBLE |
8 |
±2.2250738585072014E-308 |
±1.7976931348623157E+308 |
双精度浮点数 |
规定位数
1 2
| FLOAT(M, D) DOUBLE(M, D)
|
其中 M(1~255) 代表该小数的总体有效位。 D(0~30) 代表小数位的有效位数。其中M 的值必须不小于 D 。如果不规定,就按默认的最大值进行存储。
虽然可以对浮点数位数进行指定,但是存储的空间都是不变的。
浮点数的结构如下,是凭借指数和尾数来进行存储的(二进制的科学计数法),对于一些无法直接转换成二进制的数,是不精确的。
定点数
为了解决浮点数不精确的问题,定点数接将小数部分直接存储,使用时就不会出现精度损失的情况。
类型 |
占用的存储空间(单位:字节) |
取值范围 |
DECIMAL(M, D) |
取决于M和D |
取决于M和D |
定点数的存储结构如下:
其中,从小数点位置起,向前向后每九个十进制位划分为一组进行存储。
其中十进制位数对应存储字节数如下表:
组中包含的十进制位数 |
占用存储空间大小(单位:字节) |
1或2 |
1 |
3或4 |
2 |
5或6 |
3 |
7或8或9 |
4 |
所以这个数的存储总字节数为:2 + 4 + 2 = 8 个字节。
无符号数
在原数值类型后加一个单词 UNSIGNED
就构成了无符号数(正数)。
注:无符号的整数范围比有符号数的整数的正数范围大一倍,但是受到浮点数的存储格式的影响,无符号浮点数的整数范围并不会提升。
日期与时间
类型 |
存储空间要求 |
取值范围 |
格式 |
含义 |
YEAR |
1字节 |
1901~2155 |
YYYY |
年份值 |
DATE |
3字节 |
‘1000-01-01’ ~ ‘9999-12-31’ |
YYYY-MM-DD |
日期值 |
TIME |
3字节 |
‘-838:59:59’ ~ ‘838:59:59’ |
hhh:mm:ss[.uuuuuu] |
时间值 |
DATETIME |
8字节 |
‘1000-01-01 00:00:00’ ~ ‘9999-12-31 23:59:59’ |
YYYY-MM-DD hh:mm:ss[.uuuuuu] |
日期加时间值 |
TIMESTAMP |
4字节 |
‘1970-01-01 00:00:01’ ~ ‘2038-01-19 03:14:07’ |
YYYY-MM-DD hh:mm:ss[.uuuuuu] |
时间戳 |
MySQL5.6.4
之后开始TIME
、DATETIME
、TIMESTAMP
支持六位小数位秒(毫秒,微秒)。
例:DATETIME(3)
表示精确到微秒, DATETIME(5)
表示精确到 10 微秒,默认 DATETIME
为 DATETIME(0)
,即精确到秒。
其中占用的存储空间与定点数占用的空间类似。需要在原本的存储空间上占用额外的空间。
保留的小数秒位数 |
额外需要的存储空间要 |
0 |
0字节 |
1或2 |
1字节 |
3或4 |
2字节 |
5或6 |
3字节 |
例:DATETIME(3)
需要占用的空间为 3 + 2 个字节。
注:DATETIME
中的时间部分表示的是一天内的时间(00:00:00 ~ 23:59:59),而 TIME
表示的是一段时间,而且可以表示负值。
TIMESTAMP
:时间戳存储的时间,可以随着时区的变化而变化。
字符串
不同编码方式的字符存储长度是不同的。
固定编码:例如 ASCII
采用 1 个字节来编码一个字符,ucs2
采用 2 个字节来编码一个字符。
变长编码:utf8
采用 1~3
个字节来编码一个字符,gb2312
采用 1~2
个字节来编码一个字符。utf8mb4
使用1~4个字节来编码一个字符(MySQL中的 utf8mb4
才是真正意义上的 utf8
)。
类型 |
最大长度 |
存储空间要求 |
含义 |
CHAR(M) |
M个字符 |
M×W个字节 |
固定长度的字符串 |
VARCHAR(M) |
M个字符 |
L+1 或 L+2 个字节 |
可变长度的字符串 |
TINYTEXT |
2⁸-1 个字节 |
L+1个字节 |
非常小型的字符串 |
TEXT |
2¹⁶-1 个字节 |
L+2 个字节 |
小型的字符串 |
MEDIUMTEXT |
2²⁴-1 个字节 |
L+3个字节 |
中等大小的字符串 |
LONGTEXT |
2³²-1 个字节 |
L+4个字节 |
大型的字符串 |
M
代表该数据类型最多能存储的字符数量。
L
代表实际存储的字符数量。
W
代表在该特定字符集下,编码一个字符最多需要的字节数。
CHAR(M)
中如果占用的字符数不足 M
(1~255)个,用空格补足空位,但是这样会浪费存储空间。
为了解决这个问题,我们可以使用 VARCHAR(M)
,可以存储的字符量理论上是 1~65535
,但是由于 MySQL
中还有一个规定(表中某一行包含的所有列中存储的数据大小总共不得超过65535个字节),所以能够容纳的字符数量是小于65535的。
VARCHAR
的组成
各种 TEXT
类型也是变长类型,也是由实际内容和内容占用字节数组成的。但 MySQL
的每行至多 65535 个字节这个规定对于 TEXT
是不奏效的。
二进制类型
类型 |
字节数 |
含义 |
BIT(M) |
近似为(M+7)/8 |
存储M个比特位的值 |
主要用于存储单个或多个比特位。
M
的取值范围为 1~64,当省略时默认为1。但是 MySQL
是以字节为单位存储数据的,若不足一个字节会补足为整数个字节。
类型 |
存储空间 |
含义 |
BINARY(M) |
M字节 |
存储M个字节 |
VARBINARY(M) |
L+1 / L+2 字节 |
存储最多M个字节 |
与 CHAR(M)
和 VARCHAR(M)
类似,只不过一个是用来存储字符,另一个是用来存储字节的。
另外还有 TINYBLOB
、 BLOB
、 MEDIUMBLOB
、 LONGBLOB
是针对数据量很大的二进制数据提出的,比如图片、音频、压缩文件这类数据。与 TEXT
类似,同样,一个是用来存储字符,另一个是用来存储字节的。
特殊类型
ENUM类型
枚举类型,表示在给定的字符串列表里选择一个,例如 ENUM('男', '女')
;
SET类型
集合类型,表示可以在给定的字符串列表里选择多个,例如 SET('LOL', 'DOTA2', 'CS:GO')
;
特点
EMUN
和 SET
都是两种特殊的字符串类型,在从字符串列表中单选或多选元素的时候会用得到它们。
隐式类型转换
如果数据的类型与上下文不符合,MySQL
会对数据进行转换。
例如:
-
把操作数类型转换为适合操作符计算的相应类型。
1+‘2’ = 3
-
将函数参数转换为该函数期望的类型。
concat(“1”, 2) -> “12”
-
存储数据时,把某个值转换为某个列需要的类型。
注:
-
MySQL
会尽量把值转换为表达式中需要的类型,而不是产生错误。
-
在运算时会自动提升操作数的类型。
100(TINYINT)+100(TINYINT)
在运算过程中,MySQL
自动将操作数类型提升为 BIGINT
,防止运算结果太大导致无法计算。
我们可以使用 CAST
函数对数据进行显式的转换。
内置函数
文本处理函数
名称 |
调用示例 |
示例结果 |
描述 |
LEFT |
LEFT('abc123', 3) |
abc |
给定字符串从左边取指定长度的子串 |
RIGHT |
RIGHT('abc123', 3) |
123 |
给定字符串从右边取指定长度的子串 |
LENGTH |
LENGTH('abc') |
3 |
给定字符串的长度 |
LOWER |
LOWER('ABC') |
abc |
给定字符串的小写格式 |
UPPER |
UPPER('abc') |
ABC |
给定字符串的大写格式 |
LTRIM |
LTRIM(' abc') |
abc |
给定字符串左边空格去除后的格式 |
RTRIM |
RTRIM('abc ') |
abc |
给定字符串右边空格去除后的格式 |
SUBSTRING |
SUBSTRING('abc123', 2, 3) |
bc1 |
给定字符串从指定位置截取指定长度的子串 |
CONCAT |
CONCAT('abc', '123', 'xyz') |
abc123xyz |
将给定的各个字符串拼接成一个新字符串 |
日期时间处理函数
名称 |
调用示例 |
示例结果 |
描述 |
NOW |
NOW() |
2019-08-16 17:10:43 |
返回当前日期和时间 |
CURDATE |
CURDATE() |
2019-08-16 |
返回当前日期 |
CURTIME |
CURTIME() |
17:10:43 |
返回当前时间 |
DATE |
DATE('2019-08-16 17:10:43') |
2019-08-16 |
将给定日期和时间值的日期提取出来 |
DATE_ADD |
DATE_ADD('2019-08-16 17:10:43', INTERVAL 2 DAY) |
2019-08-18 17:10:43 |
将给定的日期和时间值添加指定的时间间隔 |
DATE_SUB |
DATE_SUB('2019-08-16 17:10:43', INTERVAL 2 DAY) |
2019-08-14 17:10:43 |
将给定的日期和时间值减去指定的时间间隔 |
DATEDIFF |
DATEDIFF('2019-08-16', '2019-08-17'); |
-1 |
返回两个日期之间的天数(负数代表前一个参数代表的日期比较小) |
DATE_FORMAT |
DATE_FORMAT(NOW(),'%m-%d-%Y') |
08-16-2019 |
用给定的格式显示日期和时间 |
在 DATE_ADD
或 DATE_SUB
时,需要注意增减的单位。
时间单位 |
描述 |
MICROSECOND |
毫秒 |
SECOND |
秒 |
MINUTE |
分钟 |
HOUR |
小时 |
DAY |
天 |
WEEK |
星期 |
MONTH |
月 |
QUARTER |
季度 |
YEAR |
年 |
DATE_FORMAT
需要记住占位符的含义:
格式符 |
描述 |
%b |
简写的月份名称(Jan、Feb、…、Dec) |
%D |
带有英文后缀的月份中的日期(0th、1st、2nd、…、31st)) |
%d |
数字格式的月份中的日期(00、01、02、…、31) |
%f |
微秒(000000-999999) |
%H |
二十四小时制的小时 (00-23) |
%h |
十二小时制的小时 (01-12) |
%i |
数值格式的分钟(00-59) |
%M |
月份名(January、February、…、December) |
%m |
数值形式的月份(00-12) |
%p |
上午或下午(AM代表上午、PM代表下午) |
%S |
秒(00-59) |
%s |
秒(00-59) |
%W |
星期名(Sunday、Monday、…、Saturday) |
%w |
周内第几天 (0=星期日、1=星期一、 6=星期六) |
%Y |
4位数字形式的年(例如2019) |
%y |
2位数字形式的年(例如19) |
数值操作
名称 |
调用示例 |
示例结果 |
描述 |
ABS |
ABS(-1) |
1 |
取绝对值 |
Pi |
PI() |
3.141593 |
返回圆周率 |
COS |
COS(PI()) |
-1 |
返回一个角度的余弦 |
EXP |
EXP(1) |
2.718281828459045 |
返回e的指定次方 |
MOD |
MOD(5,2) |
1 |
返回除法的余数 |
RAND |
RAND() |
0.7537623539136372 |
返回一个随机数 |
SIN |
SIN(PI()/2) |
1 |
返回一个角度的正弦 |
SQRT |
SQRT(9) |
3 |
返回一个数的平方根 |
TAN |
TAN(0) |
0 |
返回一个角度的正切 |
聚集函数
函数名 |
描述 |
COUNT |
返回某列的行数 |
MAX |
返回某列的最大值 |
MIN |
返回某列的最小值 |
SUM |
返回某列值之和 |
AVG |
返回某列的平均值 |
聚集函数,一般是用来统计信息的。并且聚集函数统计的都是符合条件语句查询的。
COUNT
有两种用法:
COUNT(*)
:对表中行的数目进行计数,不管列的值是不是 NULL
。
COUNT(列名)
:对特定的列进行计数,会忽略掉该列为 NULL
的行。
COUNT(1)
:每一行记一个数字 1
, 然后统计 1
的个数。
使用 DISTINCT
过滤重复数据。
SELECT (DISTINCT <col_name>) FROM <table_name>;
数据库操作
1 2 3 4 5 6
| SHOW DATABASES; CREATE DATABASE <db_name>; CREATE DATABASE <db_name> IF NOT EXISTS; USE <db_name>; DROP DATABASE <db_name>; DROP DATABASE <db_name> IF EXISTS;
|
表操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| SHOW TABLES;
CREATE TABLE <table_name> ( col_name1 col_type [col_attrs], …… col_namen col_type [col_attrs] );
CREATE TABLE <table_name> ( …… ) COMMENT 'SOME_COMMITS';
CREATE TABLE IF NOT EXISTS <table_name> ( …… ); DROP TABLE [IF EXISTS] <table_name>;
DESCRIBE <table_name>; DESC <table_name>; EXPLAIN <table_name>; SHOW COLUMNS FROM <table_name>; SHOW FIELDS FROM <table_name>;
SHOW CREATE TABLE <table_name>;
ALTER TABLE [db1.]table_1 RENAME TO [db2.]table_2; RENAME TABLE [db1.]table_1 TO [db2.]table_2, [db3.]table_3 TO [db4.]table_4, ……;
ALTER TABLE <tablr_name> ADD COLUMN <col_name> <col_type> [col_attrs] [{FIRST | AFTER <col_name>}];
ALTER TABLE <table_nmae> DROP COLUMN <col_name>;
ALTER TABLE <table_nmae> MODIFY <col_name> <col_type> [<col_attrs>]; ALTER TABLE <table_name> CHANGE <old_col_name> <new_col_name> <col_type> [<col_attrs>];
ALTER TABLE <table_name> MODIFY <col_name> <col_type> <col_attrs> { FIRST | AFTER <col_name> };
<col_name> <col_type> DEAFULT <default_value>;
<col_name> <col_type> NOT NULL;
<col_name> <col_type> UNIQUE; -- 列声明 UNIQUE [constraint_name] (列名1, 列名2,……); UNIQUE KEY [constraint_name] (列名1, 列名2,……);
<col_name> <col_type> PRIMARY KEY; -- 列声明,这种方法能且仅能规定一个主键 PRIMARY KEY(col_name1, col_name2, ……);
CONSISTENT [foreign_key_name] FOREIGN KEY(col_name1, col_name2, ……) REFERENCES father_table(father_col1,father_col2, ……);
<col_name> <col_type> AUTO_INCREMENT;
<col_name> <col_type> [col_attrs] COMMENT "comments";
TINYINT: 4 INT: 11 <col_name> INT(10) UNSIGNED ZEROFILL; -- 其中的10就是显示宽度
|
增删改查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
| SELECT <col_name1 as alias_name1,col_name2 as alias_name2,……> FROM <table_name>; SELECT DISTINCT <col_names> FROM <table_name>; SELECT <col_names> FROM <table_name> LIMIT [<start_col>.]<select_col_number>; SELECT <col_names1> FROM <table_name> ORDER BY <col_names2> [ ASC | DESC ]; =, !=/(<>), >, <, <=, >=, BETWEEN, NOT BETWEEN IN/NOT IN (ele1, ele2, ……); IS NULL, IS NOT NULL LIKE , NOT LIKE +, -, *, /, DIV(取商), %, -(负号) AND, OR, XOR, () GROUP BY <col_name>; 1. 作用于分组列 GROUP BY <col_name> HAVING <col_name>="???"; 2. 作用于分组的聚合函数 GROUP BY <col_name1> HAVING MAX(<col_name2>)>?; GROUP BY <col_name1> ORDER BY(MAX(<col_name2>)>) [{ ASC | DESC }]; GROUP BY <col_name_wide>, <col_name_detail>; 1. 分组列中含有 NULL 值,那么 NULL 也会作为一个独立的分组存在。 2. 嵌套分组,聚集函数将作用在最后的那个分组列上。 3. 如果查询语句中存在 WHERE 子句和 ORDER BY 子句,那么 GROUP BY 子句必须出现在 WHERE 子句之后, ORDER BY 子句之前。 4. 非分组列不能单独出现在检索列表中(可以被放到聚集函数中)。 5. GROUP BY子句后也可以跟随表达式(但不能是聚集函数)。MySQL会根据这个表达式的值来对记录进行分组,并且查询列表中的表达式和GROUP BY子句中的表达式必须完全一样。 SELECT CONCAT(<col_name1>, "1"), COUNT(*) FROM <table_name> GROUP BY CONCAT(<col_name1>, "1"); 6. WHERE 语句在分组前对数据过滤, HAVING 语句在分组后对分组数据进行过滤。 SELECT [DISTINCT] <col_names> [FROM table_name] [WHERE <conditions>] [GROUP BY <col_names> ] [HAVING <conditions>] [ORDER BY <col_name>] [LIMIT start_line, lines] SELECT <col_names> FROM <table_name> WHERE <col_name = > (<a_select_statement_to_get_a_value>); SELECT <col_names> FROM <table_name> WHERE <col_name IN > (<a_select_statement_to_get_a_col_values>); SELECT <col_names1> FROM <table_name> WHERE <col_names2 = >(<a_select_statement_to_get_a_row_of_col_name2>) SELECT <col_names1> FROM <table_name> WHERE <col_names2 IN >(<a_select_statement_to_get_rows_of_col_name2>) SELECT <col_names> FROM <table_name> WHERE [NOT] EXIST (<a_select_statement_to_get_some_value>); SELECT [<table_name1>.]<col_names>, [<table_name2>].<col_names> …… FROM <table_name1>,<table_name2>; SELECT <col_names> FROM <table_name1> [ INNER | CROSS] JOIN <table_name2> ON <conditions> [WHERE conditions] SELECT <col_names> FROM <table_name1> { LEFT | RIGHT } [OUTER] JOIN <table_name2> ON <conditions> [WHERE conditions] Ex. SELECT t1.col1, t2..col2, t3.col3 FROM t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.col1 = t2.col2 AND t2.col2 = t3.col3;· 或 SELECT t1.col1, t2..col2, t3.col3 FROM t1 INNER JOIN t2 ON t2.col2 = t1.col1 INNER JOIN t3 ON t2.col2 = t2.col2; (SELECT <t1_col_1>, <t1_col_2> FROM t1 <where_statement>) UNION [ALL] (SELECT <t2_col_1>, <t2_col_2> FROM t2 <where_statement>) ORDER BY <col_of_result> [ASC | DESC] LIMIT <col_number>;
INSERT INTO <table_name> VALUES(col1_val1,col2_val1...), (col1_val2,col2_val2...)...; INSERT INTO <table_name>(col_names) VALUES(col_vals1), (col_vals2)...;
DELETE FROM <table_name> [where_statement] [order_statement] [limit_statement];
UPDATE <table_name> SET <col_name1>="col_val1", <col_name2>="col_val2"... [where_statement] [order_statement] [limit_statement];
|
视图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
CREATE VIEW <view_name> AS <select_statement>; CREATE VIEW <view_name>(view_col1, view_col2...) AS SELECT <tb_col1>, <tb_col2>... FROM tb;
SELECT * FROM <view_name>;
SHOW TABLES; SHOW CREATE VIEW <view_name>;
DROP VIEW <view_name>;
|
变量与语句结束分隔符
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| SELECT @var; SET @var = "str"; SET @var = (select_statement); <select_statement> into @var; -- 与上面的语句效果相同 SELECT <col_name1>,<col_name2> FROM <table_name> LIMIT 1 INTO @var1, @var2;
delimiter EOF SELECT * FROM t1 LIMIT 1; SELECT * FROM t2 LIMIT 1; SELECT * FROM t3 LIMIT 1; EOF
|
存储例程
存储函数与存储过程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
| 1. 存储例程(Stored Routine) (1) 存储函数(Stored Function) (2) 存储过程(Stored Procedure) 2. 触发器(Trigger) 3. 事件(Event)
CREATE FUNCTION <function_name>)(param_name param_type, ...) RETURN <return_value_type> BEGIN <functoion_body> END DECLARE var1, var2... <data_type> [DEFAULT <val>]; IF <bool_statement> THEN statements... [ELSEIF <bool_statement> THEN statements...] ... [ELSE statemants] END IF; WHILE <bool_statements> DO statements... END WHIEL; REPEAT statements... UNTIL <bool_statement> END REPEAT; LOOP statements... END LOOP; flag:LOOP IF <bool_statement> THEN LEAVE flag; END IF; statements... END LOOP; SELECT <function_name>(params...); SHOW FUNCTION STATUS [like_statement]; SHOW CREATE FUNCTION <function_name>; DROP FUNCTION <function_name>; CREATE PROCEDURE <procedure_name>([[IN | OUT | INOUT]param_name param_type,...]) BEGIN statements... END; CALL <procedure_name>([param_name param_type,...]); SHOW PROCEDURE STATUS [like_statement]; SHOW CREATE PROCEDURE <procedure_name>; DROP PROCEDURE <procedure_name>; CREATE TRIGGER <triggrt_name> { BEFORE | AFTER } { INSERT | DELETE | UPDATE } ON <table_name> FOR EACH ROW BEGIN statements END SHOW TRIGGERS; SHOW CREATE TRIGGER <trigger_name>; DROP TRIGGER <trigger_name>; CREATE EVENT <event_name> ON SCHEDULE { AT <a_concrete_time>| EVERY <time_interval> [STARTS datetime][END datetime] } DO BEGIN statements; END SHOW EVENTS; SHOW CREATE EVENT <event_name>; DROP EVENT <event_name>;
|
游标
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| DECLARE <cursor_name> CURSOR FOR <select_statement>; { OPEN | CLOSE } <cursor_name>; -- 关闭游标将会释放相关资源,使用完就可以将其关闭,如果不关闭,在 END 语句结束后也会释放资源。 FETCH <cousor_name> INTO var1, var2, var3; -- 获取记录中的值,并将其按列的顺序赋值给变量,变量的类型和数量和列应该相同 CREATE PROCEDURE proc1() BEGIN DECLARE <vars var_type>; DECLARE <cursor_name> CURSOR FOR <select_statement>; OPEN <cursor_name>; FETCH <cursor_name> INTO <vars>; -- 游标会自动移动到下一个 SELECT <vars>; END; DECLARE CONTINUE HANDLER FOR NOT FOUND [BEGIN] <handle_statement> [END]
|