-- 登录数据库
mysql -uroot –p 或
mysql -h127.0.0.1 --user=root --password=root
关键字:(创建(create)一个结构,修改(alter)一个结构,删除(drop 摧毁)一个结构);用于对操作对象(数据库,表,视图等)做创建,修改,删除等操作
//一、DDL之数据库操作:database
//1.创建数据库
create database 数据库名;//默认编码 utf-8
create database 数据库名 character set 字符集;//指定数据库的编码
//2.查看数据库
show databases;//查看服务器的所有数据库
show create database 数据库名;//查看某个数据库的定义的信息
//3.删除数据库
drop database 数据库名称;
//4.使用数据库
select database();//查看正在使用的数据库
use 数据库名;//使用某个数据库
//二、DDL之表操作:table
//1.创建表
//1.1地区表
CREATE TABLE `area` (
`a_id` int(8) NOT NULL auto_increment COMMENT '地区ID',
`a_name` varchar(32) default NULL COMMENT '地区名称',
PRIMARY KEY (`a_id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8
//1.2学校表
CREATE TABLE `school` (
`sc_id` int(8) NOT NULL auto_increment COMMENT '学校表的主键ID',
`sc_name` varchar(32) default NULL COMMENT '学校名称',
`a_id` int(8) default NULL COMMENT '所属区域外键',
PRIMARY KEY (`sc_id`)
) ENGINE=InnoDB AUTO_INCREMENT=158 DEFAULT CHARSET=utf8
//1.3学生表
CREATE TABLE `student` (
`s_id` int(8) NOT NULL auto_increment COMMENT '学生编号',
`s_name` varchar(32) default NULL COMMENT '学生姓名',
`s_sex` int(1) default NULL COMMENT '性别 0(女) 1(男)',
`s_birthday` date default NULL,
`s_examnum` varchar(32) default NULL,
`sc_id` int(8) default NULL,
PRIMARY KEY (`s_id`),
KEY `index_student_sname` (`s_name`)
) ENGINE=InnoDB AUTO_INCREMENT=39132 DEFAULT CHARSET=utf8
//2.查看表
show tables;//查看数据库中的所有表
select * from 表名;//查询当前表中所有的数据
desc 表名;//查看表结构
//3.删除表
drop table 表名;
//3.修改表结构
1.alter table 表名 add 列名 类型(长度) [约束];//新增字段
2.alter table 表名 modify 列名 类型(长度) [约束];//修改字段的类型长度及约束
3.alter table 表名 change 旧列名 新列名 类型(长度) [约束]//修改字段名称
4.alter table 表名 drop 列名;//删除字段
5.rename table 表名 to 新表名;//修改表名
关键字:insert(添加),delete(删除),update(修改)等
用于表中数据的增删改操作
//DML之数据操作语言
//1.插入表数据:insert
//A.向表中插入某些字段
insert into 表 (字段1,字段2,字段3,...) values (值1,值2,值3,...);
//B.向表中所有的字段设置值,要求:值的顺序与字段的顺序一致
insert into 表 values (值1,值2,值3,...);
//2.修改表数据:update
//A.更新所有记录的指定字段
update 表名 set 字段名=值,字段名=值,...;
//B.更新符合条件记录的指定字段
update 表名 set 字段名=值,字段名=值,... where 条件;
//3.删除表数据:delete
//A.如果删除表中的部分数据
delete from 表名 where 条件;//是从表中把数据一条一条的删除
//B.如果删除表中所有数据
delete from 表名;//是从表中把数据一条一条的删除,所以这样删除大表数据的时候一条一条删会很慢
truncate table 表名;//慎重使用:它不管表中有多少记录,它会先摧毁这个表结构,然后重建表结构,所以这样在删除大表数据的时候就会很快;
关键字:select,from,where等 查询(SELECT)
用于查询表中的数据
# 语法:select [distinct] * | 列名,列名 from 表 where 条件;
# 简单查询
select * from 表名; --查全表
select 字段1,字段2,…… from 表名; --按字段查找
-- 别名查询.使用的关键字是as(as可以省略的)
select 表别名.字段1,表别名.字段2,…… from 表名 表别名; --表别名
select 字段1 别名,字段2 别名,…… from 表名; --列别名(1.更清楚的标记这一列是什么 2.简化列名)
-- 去掉重复值
select distinct 字段 from 表名;
-- 查询结果是表达式(运算查询)
select 名称,价格 旧,(价格+10) 新 from 表名;
# 条件查询
-- 查询指定字段 = 指定值的所有信息
SELECT * FROM 表名 WHERE 字段名 = 值;
-- 查询指定字段 != 指定值的所有信息
SELECT * FROM 表名 WHERE 字段名 != 值;
-- 查询指定字段 > 指定值的所有信息
SELECT * FROM 表名 WHERE 字段名 > 值;
-- 查询指定字段 在指定范围内 的所有信息
SELECT * FROM product WHERE price >= 2000 AND price <=10000; --标准写法
SELECT * FROM product WHERE price BETWEEN 2000 AND 10000; --简易写法 效果一样
-- 查询指定字段<指定值 或 指定字段>指定值 的所有信息
select * from 表名 where 字段名 > 值 or 字段名 < 值;
--MySQL的模糊查询,Like语句中,%代表零个或多个任意字符,_代表一个字符,列如LIKE '%某字%';
-- 查询指定字段 含有某字的所有记录
select * from 表名 where 字段名 LIKE '%某字%';
-- 查询指定字段以'某字'开头的所有记录
select * from 表名 where 字段名 LIKE '某字%';
-- 查询指定字段 第二个字为'某字'的所有记录
select * from 表名 where 字段名 LIKE '_某字%';
-- 查询指定字段为空的记录
select * from 表名 where 字段名 is null;
-- 查询指定字段不为空的记录
select * from 表名 where 字段名 is not null;
# 排序查询
语法:SELECT * FROM 表名 ORDER BY 排序字段 ASC(升序 默认)|DESC 降序;
-- 按照指定字段(降序)排序
SELECT * FROM 表名 ORDER BY 排序字段 DESC;
-- 按照指定字段1(降序)排序的基础上,并按照指定字段2(降序)排序
SELECT * FROM 表名 ORDER BY 排序字段1 DESC,排序字段2 DESC;
-- 按照指定字段1去重基础上,按照指定字段2(降序)排序
SELECT DISTINCT 去重字段 FROM 表名 ORDER BY 排序字段 DESC;
# 聚合查询
SELECT COUNT(*) FROM 表名; --cout(*)包括了所有的列,相当于行数,在统计结果的时候,不会忽略NULL
SELECT COUNT(字段) FROM 表名; --count(列名)会统计该列字段在表中出现的次数,会忽略字段为null 的情况,即不统计字段为null 的记录
SELECT COUNT(1) FROM 表名; --COUNT(1)会统计表中的所有的记录数,不会忽略NULL,包含字段为null 的记录
-- 查询 指定字段>指定值 的总记录数
SELECT COUNT(*) FROM 表名 WHERE 指定字段 > 指定值;
-- 查询分类为 1 的所有商品的总和
SELECT SUM(price) FROM product WHERE c_id = 1;
-- 查询分类为2所有商品的平均价格
SELECT AVG(price) FROM product WHERE c_id = 2;
-- 查询商品的最大价格和最小价格
SELECT MAX(price),MIN(price) FROM product;
# 分组查询
语法:SELECT 字段1,字段2… FROM 表名GROUP BY分组字段 HAVING 分组条件;
分组操作中的having子语句,是用于在分组后对数据进行过滤的,作用类似于where条件。
having与where的区别:
having是在分组后对数据进行过滤;where是在分组前对数据进行过滤
having后面可以使用分组函数(统计函数);where后面不可以使用分组函数
-- 1 统计各个分类商品的个数
SELECT c_id ,COUNT(*) FROM product GROUP BY c_id;
-- 2 统计各个分类商品的个数,且只显示个数大于3的信息
SELECT c_id ,COUNT(*) FROM product GROUP BY c_id HAVING COUNT(*) > 3;
与用户相关的操作,比如创建,删除,权限修改等
用来定义数据库的访问权限和安全级别,及创建用户。
因为工作中的权限问题,所以应用较少,这里不演示。
一、约束条件分类:
1)not null :非空约束,保证字段的值不能为空
s_name VARCHAR(10) NOT NULL, #非空
2)default:默认约束,保证字段总会有值,即使没有插入值,都会有默认值!
age INT DEFAULT 18, #默认约束
3)unique:唯一,保证唯一性但是可以为空,比如座位号
s_seat INT UNIQUE,#唯一约束
4)check:检查性约束【MySQL不支持,语法不报错,但无效】
s_sex CHAR(1) CHECK(s_sex='男' OR s_sex='女'),#检查约束(Mysql无效)
5)primary key :主键约束唯一标识数据库表中的每条记录。同时保证唯一性和非空
添加主键约束:创建表时,在该字段描述处,声明指定字段为主键:
id INT PRIMARY KEY,#主建约束(唯一性,非空)
6)auto_increment(关键字)自动增长列:自动增长列类型必须是整形,自动增长列必须为键(一般是主键)
7)foreign key:外键约束,用于限制两个表的关系,保证从表该字段的值来自于主表相关联的字段的值!
teacher_id INT REFERENCES teacher(id) #这是外键,写在列级,Mysql无效
为了表明商品属于哪个分类,通常情况下,我们将在商品表上添加一列,用于存放分类c_id的信息,此列称为:外键;
此时“分类表category”称为:主表,“cid”我们称为主键。“商品表products”称为:从表,c_id称为外键。
外键特点:从表外键的值是对主表主键的引用。从表外键类型,必须与主表主键类型一致。
[外键名称] 用于删除外键约束的,一般建议“_fk”结尾
使用外键目的:保证数据完整性
# 声明外键约束的语法:
alter table 从表 add [constraint] [外键名称] foreign key (从表外键字段名) references 主表 (主表的主键);
# 删除外键约束的语法:
alter table 从表 drop foreign key 外键名称
##外键约束案例:
--添加约束:
alter table product add CONSTRAINT fk_product_cid FOREIGN key (c_id) REFERENCES category(cid);
--验证约束:
-- 1 向分类表中添加数据
insert into category values (null,'家用电器/电脑');
-- 2 向商品表中添加已经存在的商品类别的商品
INSERT INTO product VALUES(null,' 联想(Lenovo)威6 14英寸商务轻薄笔记本电脑(i7-8550U 8G 256G PCIe SSD FHD MX150 Win10 两年上门)鲨鱼灰',5999,1);
-- 3 向商品表中添加不存在的商品类别的商品 (报错,违反了主外键约束)
INSERT INTO product VALUES(null,'七匹狼休闲裤男2018秋装新款纯棉男士直筒商务休闲长裤子男装 2775 黑色 32/80A',299,2);
-- 4 删除指定分类(分类被商品使用) -- 执行异常(因为要删除的商品分类被外检表引用,所以会报错)
delete from category where cid = 1;
# 视图
为什么需要视图?满足不同的人员关注不同的数据,同时保证信息的安全性
概念:视图是一张虚拟表,表示一张表的部分数据或多张表的综合数据,其结构和数据是建立在对表的查询基础上;视图中不存放数据,数据存放在视图所引用的原始表中。
用途:筛选表中的行、防止未经许可的用户访问敏感数据、降低数据库的复杂程度、将多个物理数据库抽象为一个逻辑数据库。
此处需要注意:视图是一个虚拟表,视图是不允许出现重复列的!而且封装视图的查询结果中也不能用用子查询!这两点一定要切记!
# 创建视图语法
create view 视图名称 as <select语句>;
# 删除视图语法
drop view [if exists] 视图名称; //[if exists]删除前判断视图是否存在
# 查询视图语法
select * from 视图名称;
-- Mysql索引
索引技术就是为了让数据库 更快的定位一条数据所采用的一种查询性能优化技术。
索引是一种有效组 合数据的方式,为快速查找到指定记录。
作用:大大提高数据库的检索速度、改善数据库性能。
MySQL索引按存储类型分类B-树索引、哈希索引。
-- Mysql索引分类:
普通索引:基本索引类型;允许在定义索引的列中插入重复值和空值
唯一索引:索引列数据不重复;允许有空值
主键索引:主键列中的每个值是非空、唯一的;一个主键将自动创建主键索引
复合索引:将多个列组合作为索引
全文索引:支持值的全文查找;允许重复值和空值
空间索引:对空间数据类型的列建立的索引
-- MySql创建索引的语法
-- 普通索引
-- 直接创建普通索引:
CREATE INDEX indexName ON mytable(username(length));
-- 修改表结构的方式添加普通索引
ALTER table tableName ADD INDEX indexName(columnName);
-- 创建表的时候同时创建普通索引
CREATE TABLE `table` (字段1,字段2,……,INDEX [indexName] (username(length)));
-- 唯一索引
-- 直接创建唯一索引:
CREATE UNIQUE INDEX indexName ON mytable(username(length))
-- 修改表结构的方式添加唯一索引
ALTER table mytable ADD UNIQUE [indexName] (username(length))
-- 创建表的时候同时创建唯一索引
CREATE TABLE `table` (字段1,字段2,……,UNIQUE [indexName] (username(length)));
-- 使用ALTER 命令添加和删除索引
ALTER TABLE tbl_name ADD PRIMARY KEY (column_list): 该语句添加一个主键,这意味着索引值必须是唯一的,且不能为NULL。
ALTER TABLE tbl_name ADD UNIQUE index_name (column_list): 这条语句创建索引的值必须是唯一的(除了NULL外,NULL可能会出现多次)。
ALTER TABLE tbl_name ADD INDEX index_name (column_list): 添加普通索引,索引值可出现多次。
ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list):该语句指定了索引为 FULLTEXT ,用于全文索引。
mysql> ALTER TABLE testalter_tbl ADD INDEX (c); //在表中添加索引
mysql> ALTER TABLE testalter_tbl DROP INDEX c; //在 ALTER 命令中使用 DROP 子句来删除索引
-- 使用 ALTER 命令添加和删除主键
如果想要更改列的类型而不是名称, CHANGE语法仍然要求旧的和新的列名称,即使旧的和新的列名称是一样的
使用MODIFY来改变列的类型,此时不需要重命名
mysql> ALTER TABLE testalter_tbl MODIFY i INT NOT NULL; //确保该主键默认不为空(NOT NULL)
mysql> ALTER TABLE testalter_tbl ADD PRIMARY KEY (i); //添加主键索引
mysql> ALTER TABLE testalter_tbl DROP PRIMARY KEY; //删除主键
-- MySql删除索引的语法
DROP INDEX [indexName] ON mytable; //删除表时,该表的所有索引同时会被删除
-- MySql显示索引信息的语法
SHOW INDEX FROM table_name;
-- 索引案例:
-- 1. 学生表的学生姓名添加一个索引
create INDEX index_student_sname on student(s_name);
-- 2. 查看某个表的索引
show index from student;
--部分结果说明
Table:创建索引的表
Non_unique:索引是否非唯一
Key_name:索引的名称
Column_name:定义索引的列字段
Seq_in_index:该列在索引中的位置
Null:该列是否能为空值
Index_type:索引类型
-- 3. 删除索引
DROP INDEX index_student_sname on student;
-- 创建索引的指导原则
(一) 按照下列标准选择建立索引的列
1.频繁搜索的列
2.经常用作查询选择的列
3.经常排序、分组的列
4.经常用作连接的列(主键/外键)
(二) 请不要使用下面的列创建索引
1.仅包含几个不同值的列
2.表中仅包含几行
(三) 使用索引时注意事项
1.查询时减少使用*返回全部列,不要返回不需要的列
2.索引应该尽量小,在字节数小的列上建立索引
3.WHERE子句中有多个条件表达式时,包含索引列的表达式应置于其他条件表达式之前
4.避免在ORDER BY子句中使用表达式
# 表与表之间的关系:
一对多关系:一是主表,多是从表。比如部门与员工。
一对一关系:只是增加一个字段。比如人的身份证。
多对多关系:有一个中间表。比如用户与角色。
# 多表查询:语法如下
SELECT<字段名列表>FROM<表名或视图>
[inner join <表名或视图> on 条件]
[WHERE<查询条件>]
[GROUP BY<分组的字段名]
[ORDER BY<排序的列名>[ASC或DEsC
[LMIT[位置偏移量,]行数];
# 连接查询
1.交叉连接查询(基本不会使用-得到的是两个表的笛卡尔积) [了解]
2.内连接查询(使用的关键字 inner join -- inner可以省略)
内连接原理 : 内连接根据我们连接条件大大的缩小的笛卡尔积的范围;在内连接中只有主外键能够关联上的数据才能被查询出来!
隐式内连接:select * from A,B where 条件;
显示内连接:select * from A inner join B on 条件; (推荐写法)
3.外连接查询(使用的关键字 outer join -- outer可以省略)
外连接可以把关联查询的两张表的一张表作为主表,另外一张作为从表,而外链接使用保证主表的数据完整;
查询原理 : 左外连接查询是以left关键字左边的表为基准表,保证左表数据完整,如果右表没有与左表数据匹配的记录,那么右表将以一条null数据填充查询结果,保证左表的完整
左外连接:select * from A left outer join B on 条件;
右外语法: select * from A right outer join B on 条件;(了解)
-- 案例
-- 1.查询价格在一万以内名字中包含 '想' 的商品
隐式内连接:select * from category c,product p where c.cid = p.c_id and p.price <= 10000 and p.pname like '%想%';
显式内连接:分工明确 不容易写乱套
select * from category c
inner join product p on c.cid = p.c_id -- 此处设置管理
where p.price < 10000 and p.pname like '%想%'; -- 此处设置条件
-- 2.查询所有分类商品的个数
左外连接:
select c.cname,count(p.c_id) gs from category c
left join product p on c.cid = p.c_id
group by c.cname;
-- 子查询
定义:一条select语句结果作为另一条select语法一部分(查询条件,查询结果,表等)。
语法:select * from 表名 where 查询字段 >|<|= (查询条件,查询结果,表等);
-- 案例 : 查询和海尔洗衣机同样价格的商品
连接查询: 没法连接呀,发生在一张表的查询,关联字段也找不到,你叫我怎么连接?啊?怎么连接?
单行单列子查询:select * from product p where p.price = (select p.price from product p where p.pname like '%海尔%洗衣机%');
-- 案例 : 查询所有商品的商品类别名称
单行多列子查询:select * from category where cid in (select DISTINCT c_id from product);
-- 下面这条语句就是把一个查询结果直接封装为一个虚拟表a表 然后在封装的虚拟表a表的基础上又做查询 这种子查询叫做 多行多列子查询
多行多列子查询:select * from (select p.*,c.cname from product p inner join category c on p.c_id = c.cid) a where a.price > 10000
# 2018年XX市高考成绩管理与分析系统数据库实战
1.数据库结构介绍与准备
2.导入SQL脚本
3.SQL语句实战练习
# 难度 ★ 查询各表数据的基本情况
-- 查询地区表数据
select * from area;
-- 查询学校表数据
select * from school;
-- 查询学生表信息
select * from student;
-- 查询学生表信息
select * from `subject`;
-- 查询成绩表数据
select * from result;
-- 查询地区表数据的数据总量
select count(*) from area;
-- 查询学校表数据的数据总量
select count(*) from school;
-- 查询学生表数据的数据总量
select count(*) from student;
-- 查询科目表数据的数据总量
select count(*) from `subject`;
-- 查询成绩表数据的数据总量
select count(*) from result;
# 分页查询数据,难度 ★★
-- 查询前五条学生数据
select * from student limit 0,5;
-- 查询5-10条学生数据
select * from student limit 5,5;
-- 查询11-15条学生数据
select * from student limit 10,5;
-- 查询15-20条学生数据
select * from student limit 15,5;
-- 根据以上参数我们能得出以下公式:
-- 1) totalPage = totalCount%pageSize==0? totalCount/pageSize: totalCount/pageSize+1;
-- 2) limit的第一个参数 = (pageIndex-1)*pageSize;
-- 3) limit的第二个参数 = pageSize;
# 连接基础,难度 ★★★
-- 询每个地区的学校信息
select a.a_id,a.a_name,sc.sc_id,sc.sc_name from area a inner join school sc on a.a_id = sc.a_id;
-- 分页查询所有学生的基本信息以及所属院校和所属地区 分页展示 每页10条 展示第1页
select s.*,sc.sc_name,a.a_name from student s
inner join school sc on s.sc_id = sc.sc_id
inner join area a on sc.a_id = a.a_id
limit 0,10;
# 连接进阶,难度 ★★★★
-- 查询语文考试的前十名成绩
select * from `subject` s
inner join result r on s.su_id = r.su_id
where s.su_name='语文' order by r.r_score desc limit 0,10;
-- 查询总分前十名的成绩
select r.s_id,sum(r.r_score) zf from result r group by r.s_id order by zf desc limit 0,10;
select r.s_id,sum(r.r_score) zf from result r inner join `subject` su on r.su_id = su.su_id
group by r.s_id order by zf desc limit 0,10;
-- 显示上面SQL的考生姓名
select s.*,sum(r.r_score) zf from result r
inner join `subject` su on r.su_id = su.su_id
inner join student s on s.s_id = r.s_id
group by r.s_id order by zf desc limit 0,10;
-- 显示上面SQL的考生所在学校和所属地区
select s.*,sum(r.r_score) zf,sc.sc_name,a.a_name zf from result r
inner join `subject` su on r.su_id = su.su_id
inner join student s on s.s_id = r.s_id
inner join school sc on sc.sc_id = s.sc_id
inner join area a on a.a_id = sc.a_id
group by r.s_id order by zf desc limit 0,10;
# 实战基础,难度 ★★★★★
-- 统计一共有多少人参加高考,过一本线(大于等于550分),二本线(大于等于450分),专科线(大于等级250分的)分别有多少人;
-- 青铜写法
-- 总人数
select count(*) from (select * from result group by s_id) a;
-- 一本人数
select r.s_id,sum(r.r_score) zf from result r group by r.s_id having zf >=550;
select count(*) from (select r.s_id,sum(r.r_score) zf from result r group by r.s_id having zf >=550) a;
-- 二本人数
select r.s_id,sum(r.r_score) zf from result r group by r.s_id having zf >=450 and zf <550;
select count(*) from (select r.s_id,sum(r.r_score) zf from result r group by r.s_id having zf >=450 and zf <550) a;
-- 专科人数
select r.s_id,sum(r.r_score) zf from result r group by r.s_id having zf >=250 and zf <450;
select count(*) from (select r.s_id,sum(r.r_score) zf from result r group by r.s_id having zf >=250 and zf <450) a;
-- 未录取人数
select r.s_id,sum(r.r_score) zf from result r group by r.s_id having zf <250;
select count(*) from (select r.s_id,sum(r.r_score) zf from result r group by r.s_id having zf <250) a;
-- 王者写法
select
count(*) t,
sum(case when zf >=550 then 1 else 0 end) f,
sum(case when zf >=450 and zf <550 then 1 else 0 end) s,
sum(case when zf >=250 and zf <450 then 1 else 0 end) e,
sum(case when zf <250 then 1 else 0 end) o
from (select r.s_id,sum(r.r_score) zf from result r group by r.s_id) a;
上面的写法中除了我们认识的一些SQL语法外还出现了case wen 这种SQL结构:
case when 判断条件 then 条件成立执行 else 条件不成立执行 end.
CASE WHEN结构和Java中的f是一样的;
CASE WHEN就是 if then end就是if的大括号.
concat方法:select concat(country, "\t",num)as concat string from(将两个字段保存为一个字段)
# 实战高级,难度 ★★★★★★
-- 每个区参数考试人数
select a.*,count(*) from area a
inner join school sc on a.a_id = sc.a_id
inner join student st on sc.sc_id = st.sc_id
inner join (select distinct s_id from result) r on st.s_id = r.s_id
group by a.a_name;
-- 每个区的录取情况
select a.a_name,count(*) t,
sum(case when zf >=550 then 1 else 0 end) f,
sum(case when zf >=450 and zf <550 then 1 else 0 end) s,
sum(case when zf >=250 and zf <450 then 1 else 0 end) e,
sum(case when zf <250 then 1 else 0 end) o
from area a
inner join school sc on a.a_id = sc.a_id
inner join student st on sc.sc_id = st.sc_id
inner join (select s_id,sum(r_score) zf from result group by s_id) r on st.s_id = r.s_id
group by a.a_name;