目录
别名
子查询
exists
连接查询
视图
联集
case
日期时间函数
空值和无值
regexp正则表达式
存储过程
死锁
常见的错误代码
在 MySQL 查询时,当表的名字比较长或者表内某些字段比较长时,为了方便书写或者,多次使用相同的表,可以给字段列或表设置别名。使用的时候直接使用别名,简洁明了,增强可读性
语法:
对于字段的别名:
select 原字段 as 修改字段,原字段 as 修改字段 from 表名 ;
#as 可以省略。
例子:
(root@localhost) [jianghu]> select name as n,classid as c from Dragon;#对于列的别名
如果表的长度比较长,可以使用 AS 给表设置别名,在查询的过程中直接使用别名临时设置表的别名为其他
对于表的别名:
select 表格别名.原字段 as 修改字段[,表格别名.原字段 as 修改字段]from 原表名 as 表格别名 ;
#as可以省略
(root@localhost) [jianghu]> select d.name as n ,d.classid as c from Dragon d;
将聚合函数字段 设置成平均值
(root@localhost) [jianghu]> select *,avg(age) '平均值' from Dragon; +-----+-----------+------+--------+--------------+---------+-----------+ | Did | Name | Age | Gender | MasterId | ClassId | 平均值 | +-----+-----------+------+--------+--------------+---------+-----------+ | 1 | 风清扬 | 56 | 男 | 独孤求败 | 1 | 35.1905 | +-----+-----------+------+--------+--------------+---------+-----------+ 1 row in set (0.01 sec)
使用场景:
1、对复杂的表进行查询的时候,别名可以缩短查询语句的长度
2、多表相连查询的时候(通俗易懂、减短sql语句长度)
此外,AS 还可以作为连接语句的操作符。
创建t1表,将Dragon表的查询记录全部插入test1表
#可以使用as直接创建,不继承 特殊键
create table test2 (select * from Dragon);
(root@localhost) [jianghu]> create table test1 as select * from Dragon; Query OK, 21 rows affected (0.02 sec) Records: 21 Duplicates: 0 Warnings: 0
继承特殊键
(root@localhost) [jianghu]> create table test3 like Dragon; Query OK, 0 rows affected (0.01 sec)
子查询也被称作内查询或者嵌套查询,是指在一个查询语句里面还嵌套着另一个查询语句。
子查询语句是先于主查询语句被执行的,其结果作为外层的条件返回给主查询进行下一 步的查询过滤。
子查询:在SQL语句嵌套着查询语句,性能较差,基于某语句的查询结果再次进行的查询
语法:
select 字段 from 表1 where 字段2 [比较运算符] (select 字段1 from 表格2 where 条件)
#比较运算符 可以是 = > < >= <= 也可以是文字运算符 like in between
例子:
同一张表中,
(root@localhost) [jianghu]> select * from Dragon where age in (select age from Dragon where age>30); +-----+--------------+------+--------+--------------+---------+ | Did | Name | Age | Gender | MasterId | ClassId | +-----+--------------+------+--------+--------------+---------+ | 1 | 风清扬 | 56 | 男 | 独孤求败 | 1 | | 2 | 萧远山 | 34 | 男 | 2 | 3 | | 5 | 张三丰 | 100 | 男 | 2 | 1 | | 10 | 独孤求败 | 66 | 男 | 1 | 1 | | 11 | 郭靖 | 33 | 男 | 2 | 5 | | 20 | xxx | 50 | 男 | 2 | 1 | | 21 | xxx | 50 | 男 | null | 1 | | 22 | xxx | 50 | 男 | NULL | NULL | +-----+--------------+------+--------+--------------+---------+ 8 rows in set (0.00 sec)
不同表
Dragon表
(root@localhost) [jianghu]> select * from Dragon; +-----+--------------+------+--------+--------------+---------+ | Did | Name | Age | Gender | MasterId | ClassId | +-----+--------------+------+--------+--------------+---------+ | 1 | 风清扬 | 56 | 男 | 独孤求败 | 1 | | 2 | 萧远山 | 34 | 男 | 2 | 3 | | 3 | 东方不败 | 25 | 女 | 7 | 2 | | 4 | 萧峰 | 21 | 男 | 6 | 3 | | 5 | 张三丰 | 100 | 男 | 2 | 1 | | 6 | 令狐冲 | 25 | 男 | 3 | 2 | | 7 | 杨过 | 18 | 男 | 3 | 3 | | 8 | 小龙女 | 20 | 女 | 3 | 3 | | 9 | 张无忌 | 27 | 男 | 1 | 8 | | 10 | 独孤求败 | 66 | 男 | 1 | 1 | | 11 | 郭靖 | 33 | 男 | 2 | 5 | | 12 | 黄蓉 | 25 | 女 | 2 | 5 | | 13 | 胡一刀 | 21 | 男 | 3 | 8 | | 14 | 袁承志 | 19 | 男 | 5 | 3 | | 15 | 虚竹 | 19 | 男 | 3 | 1 | | 16 | 石破天 | 24 | 男 | 1 | 1 | | 17 | 段誉 | 28 | 男 | 1 | 1 | | 18 | 阿青 | 28 | 女 | 3 | 5 | | 20 | xxx | 50 | 男 | 2 | 1 | | 21 | xxx | 50 | 男 | null | 1 | | 22 | xxx | 50 | 男 | NULL | NULL | +-----+--------------+------+--------+--------------+---------+ 21 rows in set (0.00 sec)one_db表
(root@localhost) [jianghu]> select * from one_db; +----+--------------+------+--------+-------+ | id | name | age | Gender | oneid | +----+--------------+------+--------+-------+ | 1 | 陆小凤 | 26 | 男 | 2 | | 2 | 西门吹雪 | 28 | 男 | 3 | | 3 | 楚留香 | 28 | 男 | 18 | | 4 | 李寻欢 | 28 | 男 | 15 | | 5 | 木道人 | 56 | 男 | 6 | | 6 | 沈浪 | 30 | 男 | 8 | +----+--------------+------+--------+-------+ 6 rows in set (0.00 sec)#显示one_db 表中 oneid小于3的
(root@localhost) [jianghu]> select * from Dragon where classid in (select oneid from one_db where oneid<3); +-----+--------------+------+--------+----------+---------+ | Did | Name | Age | Gender | MasterId | ClassId | +-----+--------------+------+--------+----------+---------+ | 3 | 东方不败 | 25 | 女 | 7 | 2 | | 6 | 令狐冲 | 25 | 男 | 3 | 2 | +-----+--------------+------+--------+----------+---------+ 2 rows in set (0.00 sec)计算平均年龄
(root@localhost) [jianghu]> select avg(age) from Dragon; +----------+ | avg(age) | +----------+ | 35.1905 | +----------+ 1 row in set (0.00 sec找到大于平均年龄的人
(root@localhost) [jianghu]> select * from one_db where age>(select avg(age) from Dragon); +----+-----------+------+--------+-------+ | id | name | age | Gender | oneid | +----+-----------+------+--------+-------+ | 5 | 木道人 | 56 | 男 | 6 | +----+-----------+------+--------+-------+ 1 row in set (0.00 sec)显示 Dragon 表中 name和age 字段中大于 one_db表中的平均值
(root@localhost) [jianghu]> select name,age from Dragon where age>(select avg(age) from one_db); +--------------+------+ | name | age | +--------------+------+ | 风清扬 | 56 | | 萧远山 | 34 | | 张三丰 | 100 | | 独孤求败 | 66 | | 郭靖 | 33 | | xxx | 50 | | xxx | 50 | | xxx | 50 | +--------------+------+ 8 rows in set (0.00 sec)
这个关键字在子查询时,主要用于判断子查询的结果集是否为空。如果不为空, 则返回 值;反之,则返回 不存在
(root@localhost) [jianghu]> select * from Dragon where exists (select oneid from one_db where oneid<1); Empty set (0.00 sec)
inner join on(内连接)只返回两个表中联结字段的相等的行
left join on(左连接): 返回包括左表中的所有记录和右表中联结字段相等的记录
right join on(右连接): 返回包括右表中的所有记录和左表中联结字段相等的记录
内连接
(root@localhost) [jianghu]> (root@localhost) [jianghu]> select * from Dragon inner join one_db on Dragon.classid=one_db.oneid; +-----+--------------+------+--------+----------+---------+----+--------------+------+--------+-------+ | Did | Name | Age | Gender | MasterId | ClassId | id | name | age | Gender | oneid | +-----+--------------+------+--------+----------+---------+----+--------------+------+--------+-------+ | 2 | 萧远山 | 34 | 男 | 2 | 3 | 2 | 西门吹雪 | 28 | 男 | 3 | | 3 | 东方不败 | 25 | 女 | 7 | 2 | 1 | 陆小凤 | 26 | 男 | 2 | | 4 | 萧峰 | 21 | 男 | 6 | 3 | 2 | 西门吹雪 | 28 | 男 | 3 | | 6 | 令狐冲 | 25 | 男 | 3 | 2 | 1 | 陆小凤 | 26 | 男 | 2 | | 7 | 杨过 | 18 | 男 | 3 | 3 | 2 | 西门吹雪 | 28 | 男 | 3 | | 8 | 小龙女 | 20 | 女 | 3 | 3 | 2 | 西门吹雪 | 28 | 男 | 3 | | 9 | 张无忌 | 27 | 男 | 1 | 8 | 6 | 沈浪 | 30 | 男 | 8 | | 13 | 胡一刀 | 21 | 男 | 3 | 8 | 6 | 沈浪 | 30 | 男 | 8 | | 14 | 袁承志 | 19 | 男 | 5 | 3 | 2 | 西门吹雪 | 28 | 男 | 3 | +-----+--------------+------+--------+----------+---------+----+--------------+------+--------+-------+ 9 rows in set (0.00 sec)左连接,就是左边数据全部有,右边符合条件的显示出来
(root@localhost) [jianghu]> select * from Dragon left join one_db on Dragon.classid=one_db.oneid;右连接:右边全部数据,左边符合条件的显示出来
(root@localhost) [jianghu]> select * from Dragon right join one_db on Dragon.classid=one_db.oneid;
---- CREATE VIEW ----视图,可以被当作是虚拟表或 存储查询结果的表。
#视图跟表格的不同是,表格中有实际储存资料,而视图是建立在表格之上的一个架构,它本身并不实际储存资料。#临时表在用户退出出或同步数据库的连接断开后就自动消失了,而视图不会消失。
视图不含有数据,只存储它的定义,它的用途一般可以简化复杂的查询。
比如你要对几个表进行连接查询,而且还要进行统计排序等操作,写SQL语句会很麻烦的,
用视图将几个表联结起来,然后对这个视图进行查询操作,就和对一个表查询一样,很方便。语法:
create view “视图表名” as select 语句;例子:
(root@localhost) [jianghu]> create view v_test as select d.name from Dragon d inner join one_db o onn o.oneid=d.classid;查看视图表
show tables;删除视图表
drop view 视图名字(root@localhost) [jianghu]> drop view v_test; Query OK, 0 rows affected (0.01 sec)
视图表 本身并不实际存储数据 只是保存一个select语句查询结果
---- UNION ----
联集,将两个sQL语句的结果合并起来,两个sqL语句所产生的字段需要是同样的数据类型;
UNION:生成结果的资料值将没有重复,且按照字段的顺序进行排序
语法:select 语句1 union select 语句2select 语句1 union all select 语句2
例子:
(root@localhost) [jianghu]> select did,name,age,Gender from Dragon union select id,name,age,Gender from one_db;+-----+--------------+------+--------+ | did | name | age | Gender | +-----+--------------+------+--------+ | 1 | 风清扬 | 56 | 男 | | 2 | 萧远山 | 34 | 男 | | 3 | 东方不败 | 25 | 女 | | 4 | 萧峰 | 21 | 男 | | 5 | 张三丰 | 100 | 男 | | 6 | 令狐冲 | 25 | 男 | | 7 | 杨过 | 18 | 男 | | 8 | 小龙女 | 20 | 女 | | 9 | 张无忌 | 27 | 男 | | 10 | 独孤求败 | 66 | 男 | | 11 | 郭靖 | 33 | 男 | | 12 | 黄蓉 | 25 | 女 | | 13 | 胡一刀 | 21 | 男 | | 14 | 袁承志 | 19 | 男 | | 15 | 虚竹 | 19 | 男 | | 16 | 石破天 | 24 | 男 | | 17 | 段誉 | 28 | 男 | | 18 | 阿青 | 28 | 女 | | 20 | xxx | 50 | 男 | | 21 | xxx | 50 | 男 | | 22 | xxx | 50 | 男 | | 1 | 陆小凤 | 26 | 男 | | 2 | 西门吹雪 | 28 | 男 | | 3 | 楚留香 | 28 | 男 | | 4 | 李寻欢 | 28 | 男 | | 5 | 木道人 | 56 | 男 | | 6 | 沈浪 | 30 | 男 | +-----+--------------+------+--------+ 27 rows in set (0.00 sec)注意 字段 数据类型 要一致 int和int char和char
是sql 用来 作为 if-then-else 之类的关键字
语法:
select
需要显示的字段名1 '可以自定义',
需要显示的字段名2 '可以自定义',
case
when 条件1 then 结果1
when 条件2 then 结果2
else
end '显示结果的字段名'
条件可以是一个 数值 或是公式 else 子句 不是必须的
mysql> select #语法
-> name '名字', #需要显示的字段
-> age '年龄', #需要显示的字段
-> case #语法
-> when age < 18 then '少年' #条件
-> when age < 30 then '青年' #条件
-> when age < 45 then '中年' #条件
-> else '老年' #条件
-> end '状态' #显示结果的字段名
-> from students;
例1:
(root@localhost) [jianghu]> select name, case when age<18 then '未成年' when age>=18 then '成年' endd '是否成年' from Dragon;例2:
(root@localhost) [jianghu]> select * , -> case -> when gender='男' then 'M' -> when gender='女' then 'F' -> end '性别' -> from one_db; +----+--------------+------+--------+-------+--------+ | id | name | age | Gender | oneid | 性别 | +----+--------------+------+--------+-------+--------+ | 1 | 陆小凤 | 26 | 男 | 2 | M | | 2 | 西门吹雪 | 28 | 男 | 3 | M | | 3 | 楚留香 | 28 | 男 | 18 | M | | 4 | 李寻欢 | 28 | 男 | 15 | M | | 5 | 木道人 | 56 | 男 | 6 | M | | 6 | 沈浪 | 30 | 男 | 8 | M | +----+--------------+------+--------+-------+--------+ 6 rows in set (0.00 sec)
字符串函数 | 描述 |
---|---|
curdate() | 返回当前时间的年月日 |
curtime() | 返回当前时间的时分秒 |
now() | 返回当前时间的日期和时间 |
month(x) | 返回日期 x 中的月份值 |
week(x) | 返回日期 x 是年度第几个星期 |
hour(x) | 返回 x 中的小时值 |
minute(x) | 返回 x 中的分钟值 |
second(x) | 返回 x 中的秒钟值 |
dayofweek(x) | 返回 x 是星期几,1 星期日,2 星期一 |
dayofmonth(x) | 计算日期 x 是本月的第几天 |
dayofyear(x) | 计算日期 x 是本年的第几天 |
#当前日期
(root@localhost) [jianghu]> select curdate(); +------------+ | curdate() | +------------+ | 2021-12-04 | +------------+ 1 row in set (0.00 sec)#当前时间的 时分秒
(root@localhost) [jianghu]> select curtime(); +-----------+ | curtime() | +-----------+ | 19:41:33 | +-----------+ 1 row in set (0.00 sec)
#当前时间 年月日时分秒(root@localhost) [jianghu]> select now(); +---------------------+ | now() | +---------------------+ | 2021-12-04 19:42:04 | +---------------------+ 1 row in set (0.00 sec)#返回月份
(root@localhost) [jianghu]> select month('2021-12-04'); +---------------------+ | month('2021-12-04') | +---------------------+ | 12 | +---------------------+ 1 row in set (0.00 sec)#返回一年中的第几个星期
(root@localhost) [jianghu]> select week('2021-12-04'); +--------------------+ | week('2021-12-04') | +--------------------+ | 48 | +--------------------+ 1 row in set (0.00 sec)#返回小时值
(root@localhost) [jianghu]> select hour('2021-12-04 19:44'); +--------------------------+ | hour('2021-12-04 19:44') | +--------------------------+ | 19 | +--------------------------+ 1 row in set (0.00 sec)#返回分钟的值
(root@localhost) [jianghu]> select minute('2021-12-05 14:30:9'); +------------------------------+ | minute('2021-12-05 14:30:9') | +------------------------------+ | 30 | +------------------------------+ 1 row in set (0.00 sec)#返回秒值
(root@localhost) [jianghu]> select second('2021-12-04 19:45:56'); +-------------------------------+ | second('2021-12-04 19:45:56') | +-------------------------------+ | 56 | +-------------------------------+ 1 row in set (0.00 sec)
#返回星期几(root@localhost) [jianghu]> select dayofweek('2021-12-04'); +-------------------------+ | dayofweek('2021-12-04') | +-------------------------+ | 7 | +-------------------------+ 1 row in set (0.00 sec)#返回月中某天的值
(root@localhost) [jianghu]> select dayofmonth('2021-12-05'); +--------------------------+ | dayofmonth('2021-12-05') | +--------------------------+ | 5 | +--------------------------+ 1 row in set (0.00 sec)#返回一年中的 第几天
(root@localhost) [jianghu]> select dayofyear('2021-12-05'); +-------------------------+ | dayofyear('2021-12-05') | +-------------------------+ | 339 | +-------------------------+ 1 row in set (0.00 sec)
NULL
值和空值区别如下:
空值的长度为 0,不占用空间的;而 NULL 值的长度是 NULL,是占用空间的。
IS NULL 或者 IS NOT NULL,是用来判断字段是不是为 NULL 或者不是 NULL,不能查出是不是空值的。
空值的判断使用=’’或者<>’’来处理。
在通过 count()计算有多少记录数时,如果遇到 NULL 值会自动忽略掉,遇到空值会加入到记录中进行计算。mysql> select length(null),length(' '),length('abc');
+--------------+-------------+---------------+
| length(null) | length(' ') | length('abc') |
+--------------+-------------+---------------+
| NULL | 1 | 3 |
+--------------+-------------+---------------+mysql> select length(null),length(''),length('abc');
+--------------+------------+---------------+
| length(null) | length('') | length('abc') |
+--------------+------------+---------------+
| NULL | 0 | 3 |
+--------------+------------+---------------+
1 row in set (0.00 sec)(root@localhost) [jianghu]> select * from Dragon where name is not null; +-----+--------------+------+--------+--------------+---------+ | Did | Name | Age | Gender | MasterId | ClassId | +-----+--------------+------+--------+--------------+---------+ | 1 | 风清扬 | 56 | 男 | 独孤求败 | 1 | | 2 | 萧远山 | 34 | 男 | 2 | 3 | | 3 | 东方不败 | 25 | 女 | 7 | 2 | | 4 | 萧峰 | 21 | 男 | 6 | 3 | | 5 | 张三丰 | 100 | 男 | 2 | 1 | | 6 | 令狐冲 | 25 | 男 | 3 | 2 | | 7 | 杨过 | 18 | 男 | 3 | 3 | | 8 | 小龙女 | 20 | 女 | 3 | 3 | | 9 | 张无忌 | 27 | 男 | 1 | 8 | | 10 | 独孤求败 | 66 | 男 | 1 | 1 | | 11 | 郭靖 | 33 | 男 | 2 | 5 | | 12 | 黄蓉 | 25 | 女 | 2 | 5 | | 13 | 胡一刀 | 21 | 男 | 3 | 8 | | 14 | 袁承志 | 19 | 男 | 5 | 3 | | 15 | 虚竹 | 19 | 男 | 3 | 1 | | 16 | 石破天 | 24 | 男 | 1 | 1 | | 17 | 段誉 | 28 | 男 | 1 | 1 | | 18 | 阿青 | 28 | 女 | 3 | 5 | | 20 | xxx | 50 | 男 | 2 | 1 | | 21 | xxx | 50 | 男 | null | 1 | | 22 | xxx | 50 | 男 | NULL | NULL | +-----+--------------+------+--------+--------------+---------+ 21 rows in set (0.00 sec)(root@localhost) [jianghu]> select * from Dragon where classid is null; +-----+------+------+--------+----------+---------+ | Did | Name | Age | Gender | MasterId | ClassId | +-----+------+------+--------+----------+---------+ | 22 | xxx | 50 | 男 | NULL | NULL | +-----+------+------+--------+----------+---------+ 1 row in set (0.00 sec)
匹配模式 | 描述 | 实例 |
---|---|---|
^ | 匹配文本的开始字符 | ‘^bd’ 匹配以 bd 开头的字符串 |
$ | 匹配文本的结束字符 | ‘qn$’ 匹配以 qn 结尾的字符串 |
. | 匹配任何单个字符 | ‘s.t’ 匹配任何s 和t 之间有一个字符的字符串 |
* | 匹配零个或多个在它前面的字符 | ‘fo*t’ 匹配 t 前面有任意个 o |
+ | 匹配前面的字符 1 次或多次 | ‘hom+’ 匹配以 ho 开头,后面至少一个m 的字符串 |
字符串 | 匹配包含指定的字符串 | ‘clo’ 匹配含有 clo 的字符串 |
p1|p2 | 匹配 p1 或 p2 | ‘bg|fg’ 匹配 bg 或者 fg |
[...] | 匹配字符集合中的任意一个字符 | ‘[abc]’ 匹配 a 或者 b 或者 c |
[^...] | 匹配不在括号中的任何字符 | [^ab] 匹配不包含 a 或者 b 的字符串 |
{n} | 匹配前面的字符串 n 次 | ‘g{2}’ 匹配含有 2 个 g 的字符串 |
{n,m} | 匹配前面的字符串至少 n 次,至多m 次 | f{1,3}’ 匹配 f 最少 1 次,最多 3 次 |
存储过程优势:
封装性
通常完成一个逻辑功能需要多条 SQL 语句,而且各个语句之间很可能传递参数,所以,编写逻辑功能相对来说稍微复杂些,而存储过程可以把这些 SQL 语句包含到一个独立的单元中,使外界看不到复杂的 SQL 语句,只需要简单调用即可达到目的。并且数据库专业人员可以随时对存储过程进行修改,而不会影响到调用它的应用程序源代码
可增强 SQL 语句的功能和灵活性
存储过程可以用流程控制语句编写,有很强的灵活性,可以完成复杂的判断和较复杂的运算。
可减少网络流量
由于存储过程是在服务器端运行的,且执行速度快,因此当客户计算机上调用该存储过程时,网络中传送的只是该调用语句,从而可降低网络负载。
提高性能
当存储过程被成功编译后,就存储在数据库服务器里了,以后客户端可以直接调用,这样所有的 SQL 语句将从服务器执行,从而提高性能。但需要说明的是,存储过程不是越多越好,过多的使用存储过程反而影响系统性能
提高数据库的安全性和数据的完整性
存储过程提高安全性的一个方案就是把它作为中间组件,存储过程里可以对某些表做相关操作,然后存储过程作为接口提供给外部程序。这样,外部程序无法直接操作数据库表,只能通过存储过程来操作对应的表,因此在一定程度上,安全性是可以得到提高的。
使数据独立
数据的独立可以达到解耦的效果,也就是说,程序可以调用存储过程,来替代执行多条的 SQL 语句。这种情况下,存储过程把数据同用户隔离开来,优点就是当数据表的结构改变时,调用表不用修改程序,只需要数据库管理者重新编写存储过程即可。
语法:
CREATE PROCEDURE <存储过程名> ( [过程参数[,…] ] ) <过程体>
[过程参数[,…] ] 格式
<过程名>:尽量避免与内置的函数或字段重名
<过程体>:语句
[ IN | OUT | INOUT ] <参数名><类型>1) 过程名
存储过程的名称,默认在当前数据库中创建。若需要在特定数据库中创建存储过程,则要在名称前面加上数据库的名称,即 db_name.sp_name。
需要注意的是,名称应当尽量避免选取与 MySQL 内置函数相同的名称,否则会发生错误。2) 过程参数
存储过程的参数列表。其中,<参数名>为参数名,<类型>为参数的类型(可以是任何有效的 MySQL 数据类型)。当有多个参数时,参数列表中彼此间用逗号分隔。存储过程可以没有参数(此时存储过程的名称后仍需加上一对括号),也可以有 1 个或多个参数。
MySQL 存储过程支持三种类型的参数,即输入参数、输出参数和输入/输出参数,分别用 IN、OUT 和 INOUT 三个关键字标识。其中,输入参数可以传递给一个存储过程,输出参数用于存储过程需要返回一个操作结果的情形,而输入/输出参数既可以充当输入参数也可以充当输出参数。3) 过程体
存储过程的主体部分,也称为存储过程体,包含在过程调用的时候必须执行的 SQL 语句。这个部分以关键字 BEGIN 开始,以关键字 END 结束
在 MySQL 中,服务器处理 SQL 语句默认是以分号作为语句结束标志的。然而,在创建存储过程时,存储过程体可能包含有多条 SQL 语句,这些 SQL 语句如果仍以分号作为语句结束符,那么 MySQL 服务器在处理时会以遇到的第一条 SQL 语句结尾处的分号作为整个程序的结束符,而不再去处理存储过程体中后面的 SQL 语句,这样显然不行。
为解决以上问题,通常使用 DELIMITER 命令将结束命令修改为其他字符。语法格式如下: delimiter $$
语法说明如下:
$$ 是用户定义的结束符,通常这个符号可以是一些特殊的符号,如两个“?”或两个“¥”等。
当使用 DELIMITER 命令时,应该避免使用反斜杠“\”字符,因为它是 MySQL 的转义字符成功执行这条 SQL 语句后,任何命令、语句或程序的结束标志就换为两个??
mysql > DELIMITER ??
若希望换回默认的分号“;”作为结束标志,则在 MySQL 命令行客户端输入下列语句即可
mysql > DELIMITER ;
注意:DELIMITER 和分号“;”之间一定要有一个空格delimiter ??
CREATE PROCEDURE 存储过程名()
BEGIN
执行的sql语句 1 ;
执行的sql语句 2 ;
end ??delimiter(一定要加空格,一定要加空格,一定要加空格);
call 存储过程名
示例(不带参数的创建)
##创建存储过程##
DELIMITER $$ #将语句的结束符号从分号;临时改为两个$$(可以自定义)
CREATE PROCEDURE Proc() #创建存储过程,过程名为Proc,不带参数
-> BEGIN #过程体以关键字 BEGIN 开始
-> create table mk (id int (10), name char(10),score int (10)); #过程体语句
-> insert into mk values (1, 'wang',13); #过程体语句
-> select * from mk; #过程体语句
-> END $$ #过程体以关键字 END 结束DELIMITER ; #将语句的结束符号恢复为分号
mysql> delimiter //
mysql> create procedure data()
-> begin
-> select now();
-> end //
Query OK, 0 rows affected (0.00 sec)mysql> delimiter ;
mysql> call data;
+---------------------+
| now() |
+---------------------+
| 2021-12-01 17:36:43 |
+---------------------+
1 row in set (0.00 sec)Query OK, 0 rows affected (0.00 sec)
delimiter @@
create procedure proc (in inname varchar(40))
begin
select * from info where name=inname;
end @@delimiter ;
call proc2('wangwu');
条件判断
if then else ..... end if
delimiter $$
create procedure proc6(in var int)
begin
if var>10 then
update students set age=age+1 where stuid=1;
end if;
end $$
delimiter ;
call proc(11)
循环 while do....end whilecreate table testlog (id int auto_increment primary key,name char(10),age int default 20);
delimiter $$
create procedure ky15()
begin
declare i int;
set i = 1;
while i <= 100000
do insert into testlog(name,age) values (concat('zhou',i),i);
set i = i +1;
end while;
end$$delimiter ;
select concat(zhou,1);
select * from testlog limit 10;
##查看存储过程##
格式:
SHOW CREATE PROCEDURE [数据库.]存储过程名; #查看某个存储过程的具体信息
SHOW CREATE PROCEDURE proc1##删除存储过程##
存储过程内容的修改方法是通过删除原有存储过程,之后再以相同的名称创建新的存储过程。DROP PROCEDURE IF EXISTS Proc;
是指两个或两个以上的事务在执行过程中,因争夺资源而造成的一种互相等待的现象。就是所谓的锁资源请求产生了回路现象,即死循环,此时称系统处于死锁状态或系统产生了死锁。常见的报错信息为“Deadlock found when trying to get lock...”。
在实际应用中,我们要尽量防止死锁等待现象的发生,下面介绍几种避免死锁的方法:
如果不同程序会并发存取多个表,或者涉及多行记录时,尽量约定以相同的顺序访问表,这样可以大大降低死锁的发生。
业务中要及时提交或者回滚事务,可减少死锁产生的概率。
在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁产生概率。
对于非常容易产生死锁的业务部分,可以尝试使用升级锁粒度,通过表锁定来减少死锁产生的概率(表级锁不会产生死锁)。
错误代码 | 说 明 |
---|---|
1004 | 无法创建文件 |
1005 | 无法创建数据表、创建表失败 |
1006 | 无法创建数据库、创建数据库失败 |
1007 | 无法创建数据库,数据库己存在 |
1008 | 无法删除数据库,数据库不存在 |
1009 | 不能删除数据库文件导致删除数据库失败 |
1010 | 不能删除数据目录导致删除数据库失败 |
1011 | 删除数据库文件时出错 |
1012 | 无法读取系统表中的记录 |
1013 | 无法获取的状态 |
1014 | 无法获得工作目录 |
1015 | 无法锁定文件 |
1016 | 无法打开文件 |
1017 | 无法找到文件 |
1018 | 无法读取的目录 |
1019 | 无法为更改目录 |
1020 | 记录已被其它用户修改 |
1021 | 硬盘剩余空间不足,请加大硬盘可用空间 |
1022 | 关键词重读,更改记录失败 |
1023 | 关闭时发生错误 |
1025 | 更改名字时发生错误 |
1032 | 记录不存在 |
1036 | 数据表是只读的,不能对它进行修改 |
1037 | 系统内存不足,请重启数据库或重启服务器 |
1042 | 无效的主机名 |
1044 | 当前用户没有访问数据库的权限 |
1045 | 不能连接数据库,用户名或密码错误 |
常见的客户端错误代码及说明如下所示:
2000 | 未知 MySQL 错误 |
---|---|
2001 | 不能创建 UNIX 套接字(%d) |
2002 | 不能通过套接字“ %s”(%d)连接到本地 MySQL 服务器, self 服务未启动 |
2003 | 不能连接到 %s ”(%d )上的 MySQL 服务器,未启动 mysql 服务 |
2004 | 不能创建 TCP/IP 接字(%d) |
2005 | 未知的 MySQL 服务器主机“ %s”(%d) |
2007 | 协议不匹配,服务器版本=%d,客户端版本=%d |
2008 | MySQL 客户端内存溢出 |
2009 | 错误的主机信息 |
2010 | 通过 UNIX 套接字连接的本地主机 |
2012 | 服务器握手过程中出错 |
2013 | 查询过程中丢失了与 SQL 服务器的连接 |
2014 | 命令不同步,现在不能运行该命令 |
2024 | 连接到从服务器时出错 |
2025 | 连接到主服务器时出错 |
2026 | SSL 连接错误 |