MySQL 基本语法
Posted swagger-ranger
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL 基本语法相关的知识,希望对你有一定的参考价值。
mysql 基本语法
MySQL本身自带4张表:
information_schema:数据库又称为信息架构,数据表保存了MySQL服务器所有数据库的信息。如数据库名,数据库的表,表栏的数据类型与访问权限等。
performance_schema:数据库主要用于收集数据库服务器性能参数,以便优化mysql数据库性能。
mysql:数据库是存储着已MySQL运行相关的基本信息等数据管理的数据库。
sys:数据库是mysql5.7增加的,通过这个库可以快速的了解系统的元数据信息
这个库可以方便DBA发现数据库的很多信息,提供解决性能瓶颈的信息。
登陆
mysql -u root -p
然后输入密码
或者将密码明文登陆
mysql -u root -p password
指定服务器-h
mysql -h localhost -u root -p password
-u 以什么用户登陆 root即以root用户登陆
-p 以密码登陆,有密码就输入密码没有密码就回车确认
数据库的创建与删除
创建
CREATE database 数据库名
删除
DROP database 数据库名
查看所有数据库
SHOW databases
切换数据库
use 数据库名
表的创建与删除
创建
CREATE TABLE 表名(字段1 数据类型[选项],字段2 数据类型[选项],...)
删除
DROP TABLE 表名
查看所有表
SHOW TABLES
表的修改
修改列的定义:
ALTER TABLE ... MODIFY
ALTER TABLE 表名 MODIFY 列名 数据类型;
追加列
ALTER TABLE ... ADD
ALTER TABLE 表名 ADD 列名 数据类型;
修改列名与定义
ALTER TABLE ... CHANGE
删除列
ALTER TABLE ... DROP
ALTER TABLE 表名 DROP 列名
表的复制
新建表复制已有的表的结构而不需要数据,使用LIKE关键字
CREATE TABLE 新表名 LIKE 旧表名
create table new_user_no_data like user;
新建表复制表的结构和数据
CREATE TABLE 新表名 SELECT * FROM 旧表名
create table new_user select * from user;
向已有的表中复制另一张表的数据
INSERT INTO 表名 SELECT * FROM 带数据的表
nsert into new_user_no_data select * from user;
示例:
#user表创建语句
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) NOT NULL COMMENT '用户名称',
`birthday` date DEFAULT NULL COMMENT '生日',
`sex` char(1) DEFAULT NULL COMMENT '性别',
`address` varchar(256) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=37 DEFAULT CHARSET=utf8;
#创建商品表
CREATE TABLE `items` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL COMMENT '商品名称',
`price` float(10,1) NOT NULL COMMENT '商品定价',
`detail` text COMMENT '商品描述',
`pic` varchar(64) DEFAULT NULL COMMENT '商品图片',
`createtime` datetime NOT NULL COMMENT '生产日期',
PRIMARY KEY (`id`) #<---------------------------指明items的唯一主键字段
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
#订单表orders创建语句
CREATE TABLE `orders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL COMMENT '下单用户id',
`number` varchar(32) NOT NULL COMMENT '订单号',
`createtime` datetime NOT NULL COMMENT '创建订单时间',
`note` varchar(100) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`),
CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION #<-----创建外键约束
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
#订单详情表orderdetail创建语句
CREATE TABLE `orderdetail` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`orders_id` int(11) NOT NULL COMMENT '订单id',
`items_id` int(11) NOT NULL COMMENT '商品id',
`items_num` int(11) DEFAULT NULL COMMENT '商品购买数量',
PRIMARY KEY (`id`),
#<--------创建外键约束----------->
CONSTRAINT `FK_orderdetail_1` FOREIGN KEY (`orders_id`) REFERENCES `orders` (`id`)
ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `FK_orderdetail_2` FOREIGN KEY (`items_id`) REFERENCES `items` (`id`)
ON DELETE NO ACTION ON UPDATE NO ACTION
外键约束
上面的示例中orders_id?和?items_id?分别的订单表orders和商品表items的主键,像这种属于其他表主键又存在于orderdetail表中的字段,称之为orderdetail的外键字段,使用外键的好处是可以使得两张表存在关联,保证数据的一致性和实现一些级联操作(级联操作:外键关联的表为主表,当主表发生改变,设置外键的从表也会发生改变,比如修改删除主表的内容从表也会被删除,或者当从表添加主表没有数据的数据时将添加失败)如每次购物时必须存在相对应的items_id商品数据才能创建订单详情的数据,因为没有商品也没有所谓的订单详情了,而每次可能会购买多种商品,而每种商品也将生成不同订单详情,而客户的购买行为属一次购买,因此订单详情汇聚成一个整体的订单(orders_id),也就是说一个订单详情只能属于一个订单,而一个订单可以拥有多个订单详情。在MySQL中,InnoDB引擎类型的表支持了外键约束,而外键的使用条件如下:
1.两个表必须使用InnoDB引擎
2.外键列必须建立了索引(关于索引后面分析,主键创建时会自动创建索引),MySQL 4.1.2以后的版本在建立外键时会自动创建索引
3.外键关系的两个表的列必须是数据类型相似,也就是可以相互转换类型的列,比如int和tinyint可以,但int和char则不可以;
外键语法:
[CONSTRAINT symbol] FOREIGN KEY [id] (index_col_name, …)
REFERENCES tbl_name (index_col_name, …)
[ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]
[ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]
注意该语法可以在 CREATE TABLE 和 ALTER TABLE 时使用,CONSTRAINT symbol,指明了约束标识符,在SQL排错时可能有不错的表现,如果不指明CONSTRAINT symbol,MYSQL会自动生成一个名字。两表间的更新删除时数据的同步可以使用ON DELETE、ON UPDATE 来表明相互间删除和更新事件触发后的影响,可设参数以下参数(假设主表是orders,从表是orderdetail):
RESTRICT、NO ACTION(默认行为)
删除:从表数据记录不存在时,主表数据记录才可以删除,如当从表orderdetail的数据被删除后主表的orders的数据才能被删除,否则无法删除。删除从表数据,主表数据不变
更新:从表记录数据不存在时,主表数据才可以更新。当更新从表数据,主表数据不变
CASCADE(级联)
删除:删除主表数据时自动删除从表数据。删除从表数据,主表数据不变
更新:更新主表数据时自动更新从表数据。更新从表数据,主表数据不变
SET NULL
删除:删除主表数据时自动更新从表对于数据值为NULL。删除从表数据,主表数据不变
更新:更新主表数据时自动更新从表数据值为NULL。更新从表数据数据,主表不变
表的增删改查
#insert 插入操作,列名和后面的数据要一一对应,但如果要插入所有的列时可以忽略列名
INSERT INTO 表名(列名1,列名2,...) VALUES (数据1,数据2...);
#update 更新操作
UPDATE 表名 SET 列名1=值1,列名2=值2,...WHERE 条件表达式;
#delete 删除操作
DELETE FROM 表名 WHERE 条件表达式
#select 查询操作
SELECT 列名1,列名2,... FROM 表名 [条件表达式]
查询
单独说下查询,增删改的操作语法结构相对简单,但查询常常会有很多种组合来获取不同的查询结果
查询变化主要在where对结果的过滤处理
|运算符 |描述|演示|
|---|---|---|
|= |相等|id = 15
|> |大于|id > 15
|< |小于|id < 15
|>= |大于等于|id >= 15
|<= |小于等于|id <= 15
|<> |不相等| id <> 15
|IS |[NOT] NULL 为NULL(不为NULL)| address is NULL
|[NOT]| LIKE |模糊查询,指向模糊查询目标 address LIKE ‘北京%‘
|[NOT]| BETWEEN |(不包含)包含在指定范围内 id BETWEEN 1 AND 15
|[NOT]| IN |包含在指定范围值内 id in (1,2,15,20)
NULL
NULL条件有点需要注意,在使用NULL条件检索时不能使用=号,必须使用 is 指明查询条件的值为空,当然如果是not null 那就是非空数据
mysql> select * from user where birthday is NULL;
LIKE
关键字like主要用于模糊查询,如下查询名称为‘任’开头的用户:
mysql> select username from user where username like ‘任%‘;
字符:
% :表示0个以上的所有字符
*:包括0的所有字符
_ :一个字符
BETWEEN
BETWEEN 是让我们可以运用一个范围 (range) 内抓出数据库中的值
mysql> select * from user where id between 1 and 15 ;
IN
表示某一组指明的数据,在括弧内可以有一或多个值,而不同值之间由逗点分开。值可以是数目或是文字。
#查询id为1,2,3的用户 mysql> select * from user where id in (1,2,3);
AND,OR
当需要在查询中使用多个条件组合时,可以使用AND 或者 OR ,其中指明两个条件必须成立,而OR则需要一个条件成立即可。注意:语句查询时对于AND和OR的使用以及计算顺序要特别注意,否则将会得到非预期的查询结果
ORDER BY
当希望查询出的数据按照一定的规律排序,此时ORDER BY就是很好的帮手了,如想让查询出来的数据按生日排序。
#ASC升序 DESC降序,如果有多个排序则用,隔开前面的排序优于后面的排序
mysql> select username,birthday from user where id > 15 order by birthday ASC, birthday DESC;
LIMIT
通过LIMIT可以获取到指定行数的记录。比如想获取前3条数据
mysql> select * from user limit 0 , 3;
GROUP BY
有时候可能需要依据某个字段进行查询结果分组,这时GROUP BY就显得很有用了,需要注意的是如果列中具有NULL值,则NULL将作为一个分组返回,如果列中有多个NULL值,它们将分为一组,并且GROUP BY 子句必须出现在WHERE子句之后,ORDER BY 语句之前。
#根据sex统计分组数量
mysql> select sex ,count(id) from user group by sex;
having
当需要对分组的数据进行过滤,从而指定包括哪些分组,排除哪些分组,比如根据sex字段进行user查询分组时想排除sex字段值为null的数据,此时需要指明一个条件进行过滤,可能我们已想到where 子语句,遗憾的是where并不能对数据进行分组过滤,因为where更多地是进行行数据的过滤而不是分组数据的过滤,实际上where并没有分组的概念。幸运的是,mysql提供另外的子语句having,having与where有点类似,只不过where是进行行数据过滤,而having是进行组数据过滤,即在分组后才进行数据过滤
#使用 having 排除sex为null的分组
mysql> select sex ,count(id) from user group by sex having sex is not null;
计算字段
计算字段就通过将原有select要查询的字段组合计算出来的字段,比如:
select Concat(username,‘(‘,birthday,‘)‘) from user where birthday is not null;
+-----------------------------------+
| Concat(username,'(',birthday,')') |
+-----------------------------------+
| 张曹宇(1990-08-05) |
mysql> select name , price ,price * 0.8 AS discount_price from items
| name | price | discount_price | <-----------字段的名称使用AS操作符创建别名
+------------------+---------+----------------+
| MacBook Air | 8298.9 | 6639.1 |
| MacBook Pro | 10982.0 | 8785.6 |
sql数据处理函数
文本处理函数 | 描述 |
---|---|
Concat(str1,str2,…) | 连接字符串 |
Left(str,len) | 从字符串的左端开始取得len长的子串 |
Right(str,len) | 从字符串的右端开始取得len长的子串 |
Length(str) | 返回串str的长度 |
Lower(str) | str转为小写 |
Upper(str) | str转为大写 |
Trim(str) | 去掉字符串str两边的空格 |
SubString(str,pos[,len]) | 取得字符串str中从pos位置开始的len长的子串 |
Replace(t1,t2,t3) | 把t1字符串中的t2换为t3 |
SubString(t,x,y) | 返回t中始于x的长为y的字符串 |
数值处理函数 | 描述 |
---|---|
Abs(num) | 返回一个数的绝对值 |
Mod(x,y) | 求x/y余数 |
Pow(x,n) | x的n次方 |
Rand() | 返回一个随机数 |
Round(n1,n2) | 返回数n1,它被四舍五入为n2位小数 |
Sqrt(num) | 返回一个数的平方根 |
Ceiling(num) | 基于num的值的下一个最大的整数 |
Floor(num) | 返回num的整数值 |
Format(n1,n2) | 返回格式化为一个数的n1,这个数带有n2位小数,并且每3位之间插入一个逗号 |
日期处理函数 | 描述 |
---|---|
Now | 当前时间(2017-04-08 17:06:45) |
CurDate() | 当前日期(2017-04-08) |
CurTime() | 当前时间(17:06:45) |
DateDiff(d1,d2) | 计算两个日期差值 |
AddDate() | 添加一个日期(天、周等) |
AddTime() | 添加一个时间(时、分等) |
date_format(d1,format) | 格式化日期 |
Date() | 返回日期时间的日期部分 |
Month() | 返回一个日期的月份部分 |
Year() | 返回一个日期的年份部分 |
Day() | 返回日期的天数部分 |
DayOfWeek() | 对于一个日期返回对于星期几 |
Hour() | 返回一个时间的小时部分 |
Minute() | 返回一个时间的分钟部分 |
Second() | 返回一个时间的秒部分 |
聚合函数
有些情况下我们可能只是需要查询结果的汇总数据而不是把每行每列检索出来,如确定表中的行数,获取表中每个字段的总和等,此时使用mysql提供的聚合函数就可很容易获得预期结果,一般常用的聚合函数如下:
日期处理| 描述 | 备注 |示例
|---|---|---| --- |
AVG(列名) |平均值| AVG函数是用来查找各种记录的一个字段的平均值,计算的字段是必须提供的,而且对于NULL值,AVG()函数将会忽略值为NULL的行 |select AVG(price) AS avg_price from items;
COUNT(列名) |总数量| COUNT用来统计行数,COUNT(*)对表中所有行包括null进行统计,COUNT(column)对特定列中的具有值的行进行统计,忽略NULL值 |select COUNT(*) AS count from user;
MAX(列名) |最大值| |select MAX(price) AS max_price ,MIN(price) AS min_price from items;
MIN(列名) |最小值| |` SUM(列名) |合计值| |
select SUM(items_num) AS items_sum_count from orderdetail; `
表关联
在实际开发中,单表查询并不能很好满足预期的需求,而通过多表关联查询则能实现预期的需求。
同时使用表关联,1.对于每个订单来说,相同的商品的信息都是一样的,因此如果把商品信息直接存放到订单表中,对于不同订单的相同商品的信息的存储将是重复的,这属于既浪费时间又浪费存储空间,完全没有必要。2.如果此时商品信息发生变化,对于商品表来说只需改变一次即可,但如果直接把商品信息存储到订单表中,那么重复的商品信息都将要修改,维护成本得不偿失呢,这也就是为什么需要关联表的原因。
但同时代价就是相对单表查询,多表联查的效率会降低。
内联
语法:
SELECT 列名1 ... FROM 表1 INNER JOIN 表2 ON 表1.外键 = 表2.外键 [WHERE / ORDER BY 语句等]
示例:
#关联orderdetail和items表查询出每个订单详情的商品名称,商品价格,购买数量,购买总价格
select tm.name , tm.price ,od.items_num, (tm.price * od.items_num) AS sum_price from orderdetail AS od inner join items AS tm on od.items_id = tm.id;
+-------------+---------+-----------+-----------+
| name | price | items_num | sum_price |
+-------------+---------+-----------+-----------+
| MacBook Air | 8298.9 | 1 | 8298.9 |
| MacBook Pro | 10982.0 | 3 | 32946.0 |
| 背包 | 200.0 | 4 | 800.0 |
| MacBook Pro | 10982.0 | 3 | 32946.0 |
+-------------+---------+-----------+-----------+
外联
外关联,又称外连接,分为左外连接和右外连接,实际上还有全外连接(左外结果+右外结果),但是mysql并不支持全外连接
左联
左联就是左边的表显示所有的信息而无论右边的表是否有对应的数据
语法:
SELECT 列名1 ... FROM 表1 LEFT [OUTER] JOIN 表2 ON 表1.外键 = 表2.外键 [WHERE / ORDER BY 语句等]
select u.username , o.number , o.createtime from user as u left join orders as o on u.id = o.user_id;
右联
右外连接的作用恰好与左外连接相反,即右边的表总是显示所有信息,无论左边的表是否有对应的数据,同样地,表间的顺序将影响查询结果
语法:
SELECT 列名1 ... FROM 表1 RIGHT [OUTER] JOIN 表2 ON 表1.外键 = 表2.外键 [WHERE / ORDER BY 语句等]
复杂关联查询
涉及超过两张表的关联查询
#3张表(orders,orderdetail,items)关联查询,number重复的原因很简单,每个订单会多条订单详情的信息
select o.number , tm.name , tm.price , od.items_num from (orders as o inner join orderdetail as od on o.id = od.orders_id ) inner join items as tm on od.items_id = tm.id ;
关联支持多重嵌套,比如:
select u.username , o.number , tm.name , tm.price , od.items_num from -> ( -> (orders as o inner join orderdetail as od on o.id = od.orders_id ) -> inner join items as tm on od.items_id = tm.id -> ) -> inner join user as u on o.user_id = u.id;
但不要使用太复杂或者过多嵌套的联结查询,那会导致效率极低
子查询
子查询就是嵌套在其他查询中的查询,其基本常用语法如下(并不限于这种类型,where语句的子查询比较常见罢了):
SELECT 列名1... FROM 表名 WHERE 列名 比较运算符 (SELECT 命令)
比如:
查询价格在平均价格之上的商品
select * from items -> where price > (select AVG(price) from items);
查询还没有下订单的用户
select username , address from user where id not in (select user_id from orders);
组合查询
组合查询就是把多个select查询语句的结果相结合,创建组合查询需要使用UNION操作符。
组合查询的规则:
-- UNION 必须由两条或者两条以上的select语句组成并使用 UNION 进行组合。
-- UNION 中的每个查询必须包含相同的列、表达式或者聚合函数,但出现顺序不必一样
-- 列数据类型必须兼容,但不必完全相同。
比如:
mysql> select id , name ,price from items where price < 3000
-> union <---union会帮我们过滤掉重复数据,如果不想过滤重复数据;可以用union all
-> select id , name ,price from items where id in (1,2,3);
本博客为Swagger-Ranger的笔记分享,文章会持续更新
文中源码地址: https://github.com/Swagger-Ranger
欢迎交流指正,如有侵权请联系作者确认删除: [email protected]
以上是关于MySQL 基本语法的主要内容,如果未能解决你的问题,请参考以下文章