文章较长,但很详细,大家选择性观看即可
数据库(Database,DB) 是按照数据结构来组织,存储和管理数据的仓库。
关系型数据库:使用关系模型把数据组织到数据表(table)中。现实世界可以用数据来描述。
主流的关系型数据库产品:Oracle(Oracle)、DB2(IBM)、SQL Server(MS)、MySQL(Oracle)。
数据表:数据表是关系数据库的基本存储结构,二维数据表有行(Row),和列(Column)组成,也叫作记录(行)和字段(列)。
数据库管理系统:
数据库管理系统(DataBase Management System,DBMS):指一种操作和管理数据库的大型软件,用于建立、使用和维护数据库,对数据库进行统一管理和控制,以保证数据库的安全性和完整性。用户通过数据库管理系统访问数据库中表内的数据
数据库和数据库管理系统的区别:
简单区别就是,数据库是一个技术门类,或者一个产品,主要用户存储数据,而管理系统就是管理这个数据库产品的工具系统。
ps:类型有很多,下面最常用的几个
整数:int
浮点数:double
日期:date datetime timestamp
字符串:varchar 省空间 char 效率高
大数据:blob text
说很多你是不是不知道?? ? 没有没有,真的多,而且用的真的挺少的
分类 | 类型名称 | 说明 |
---|---|---|
整数类型 | tinyInt | 很小的整数 |
smallint | 小的整数 | |
mediumint | 中等大小的整数 | |
int(integer) | 普通大小的整数 | |
bigint | 大整数 | |
小数类型 | float(m,d) | 单精度浮点数 |
double(m,d) | 双精度浮点数 | |
decimal(m,d) | 压缩严格的定点数(小数的精确运算)浪费空间 | |
日期类型 | year | YYYY 1901~2155 |
time | HH:MM:SS -838:59:59~838:59:59 | |
date | YYYY-MM-DD 1000-01-01~9999-12-3 | |
datetime | YYYY-MM-DD HH:MM:SS 1000-01-01 00:00:00~ 9999-12-31 23:59:59 | |
timestamp | YYYY-MM-DD HH:MM:SS 19700101 00:00:01 UTC~2038-01-19 03:14:07UTC | |
文本、二进制类型 | CHAR(M)(定长字符串) | M为0~255之间的整数 |
VARCHAR(M)(变长字符串) | M为0~65535之间的整数 | |
TINYBLOB | 允许长度0~255字节 | |
BLOB | 允许长度0~65535字节 | |
MEDIUMBLOB | 允许长度0~167772150字节 | |
LONGBLOB | 允许长度0~4294967295字节 | |
TINYTEXT | 允许长度0~255字节 | |
TEXT | 允许长度0~65535字节 | |
MEDIUMTEXT | 允许长度0~167772150字节 | |
LONGTEXT | 允许长度0~4294967295字节 | |
VARBINARY(M) | 允许长度0~M个字节的变长字节字符串 | |
BINARY(M) | 允许长度0~M个字节的定长字节字符串 |
’超级多有没有,这谁能顶得住啊!还好实际用的不是很多,你只需要把上面常用的掌握了就好,当然下面能记住就很棒了
(1)什么是SQL
Structed Query Language
结构化查询语言,简称SQL,程序员或者DBA(数据库管理员)使用SQL和DBSM进行交互,操纵数据库中的资源。
(2)SQL语句分类
1.DDL(Data Definition Language)数据定义语言 用来定义数据库对象:数据库,表,列等。关键字:create, drop,alter等
2.DML(Data Manipulation Language)数据操作语言 用来对数据库中表的数据进行增删改。关键字:insert, delete, update等
3.DQL(Data Query Language)数据查询语言 用来查询数据库中表的记录(数据)。关键字:select, where等
4.DCL(Data Control Language)数据控制语言(了解) 用来定义数据库的访问权限和安全级别,及创建用户。关键字:GRANT, REVOKE等
(3)SQL通用语法
1.SQL语句可以单行或多行书写。
2.可使用空格和缩进来增强语句的可读性。
3.MySQL数据库的SQL语句不区分大小写
4.3种注释 单行注释: – 注释内容 或 # 注释内容(mysql特有) 多行注释: /* 注释 */
create,alter,drop
(定义 修改 删除 表[数据库])1.直接创建数据库 CREATE DATABASE 数据库名;
2.判断是否存在并创建数据库 CREATE DATABASE IF NOT EXISTS 数据库名;
3.创建数据库并指定字符集(编码表) CREATE DATABASE 数据库名 CHARACTER SET 字符集;
4.创建数据库,指定字符集并指定排序规则
Create database 数据库名 character set 字符集 collate 排序规则
5.具体操作:
•直接创建数据库db1
CREATE DATABASE db1;
1.查看所有的数据库 SHOW databases;
2.查看某个数据库的定义信息 SHOW CREATE DATABASE 数据库名;
修改数据库字符集格式
ALTER DATABASE 数据库名 DEFAULT CHARACTER SET 字符集;
具体操作:
•将db3数据库的字符集改成utf8
ALTER DATABASE db3 DEFAULT CHARACTER SET utf8;
DROP DATABASE 数据库名;
具体操作:
•删除db2数据库
DROP DATABASE db2;
1.查看正在使用的数据库 SELECT DATABASE();
2.使用/切换数据库 USE 数据库名;
具体操作:
•查看正在使用的数据库
SELECT DATABASE();
•使用db1数据库
USE db1;
前提先使用某个数据库
CREATE TABLE 表名 (字段名1 字段类型1, 字段名2 字段类型2…);
建议写成如下格式:
CREATE TABLE 表名 (
字段名1 字段类型1,
字段名2 字段类型2
);
关键字说明:
CREATE – 表示创建
TABLE – 表示创建一张表
具体操作:
创建student表包含id,name,birthday字段
CREATE TABLE student (
id INT,
name VARCHAR(20),
birthday DATE
);
注意书写格式,逗号,不是;结束无符号
1.查看某个数据库中的所有表 SHOW TABLES;
2.查看表结构 DESC 表名;
3.查看创建表的SQL语句 SHOW CREATE TABLE 表名;
具体操作:
•查看mysql数据库中的所有表
SHOW TABLES;
•查看student表的结构
DESC student;
•查看student的创建表SQL语句
SHOW CREATE TABLE student;
3)快速创建一个表结构相同的表
CREATE TABLE 新表名 LIKE 旧表名;
具体操作:
•创建s1表,s1表结构和student表结构相同
CREATE TABLE s1 LIKE student;
直接删除表 DROP TABLE 表名;
具体操作:
•直接删除表s1表
DROP TABLE s1;
修改表结构使用不是很频繁,只需要了解,等需要使用的时候再回来查即可
1.添加表列 ALTER TABLE 表名 ADD 列名 类型;
具体操作:
–为学生表添加一个新的字段remark,类型为varchar(20)
ALTER TABLE student ADD remark VARCHAR(20);
2.修改列类型 ALTER TABLE 表名 MODIFY 列名 新的类型; 具体操作:
–将student表中的remark字段的改成varchar(100)
ALTER TABLE student MODIFY remark VARCHAR(100);
3.修改列名 ALTER TABLE 表名 CHANGE 旧列名 新列名 类型; 具体操作:
–将student表中的remark字段名改成intro,类型varchar(30)
ALTER TABLE student CHANGE remark intro varchar(30);
4.删除列 ALTER TABLE 表名 DROP 列名; 具体操作:
–删除student表中的字段intro
ALTER TABLE student DROP int
5.修改表名 RENAME TABLE 表名 TO 新表名; 具体操作:
–将学生表student改名成student2
RENAME TABLE student TO student2;
6.修改字符集 ALTER TABLE 表名 character set 字符集; 具体操作:
–将sutden2表的编码修改成gbk
ALTER TABLE student2 character set gbk;
update,insert,delete
(对表中数据 增删改)•所有的字段名都写出来 INSERT INTO 表名 (字段名 1, 字段名2, 字段名3) VALUES (值1, 值2, 值3…);
•不写字段名 INSERT INTO 表名 VALUES (值1, 值2, 值3);
•所有的字段名都写出来 INSERT INTO 表名 (字段名 1, 字段名2, 字段名3) VALUES (值1, 值2, 值3…);
•不写字段名 INSERT INTO 表名 VALUES (值1, 值2, 值3);
INSERT INTO 表名 (字段名1, 字段名2, …) VALUES (值1, 值2, …); 没有添加数据的字段会使用NULL
1.关键字说明
INSERT INTO 表名 – 表示往哪张表中添加数据
(字段名1, 字段名2, …) – 要给哪些字段设置值
VALUES (值1, 值2, …); – 设置具体的值
2.注意
–值与字段必须对应,个数相同,类型相同
–值的数据大小必须在字段的长度范围内 varchar()
–除了数值类型外,其它的字段类型的值必须使用引号引起。(建议单引号)
–如果要插入空值,可以不写字段,或者插入null
3.具体操作:
–插入部分数据,往学生表中添加 id, name, age, sex数据
INSERT INTO student (id, NAME, age, sex) VALUES (1, ‘张三’, 20, ‘男’);
–向表中插入所有字段
•所有的字段名都写出来
INSERT INTO student (NAME, id, age, sex, address) VALUES (‘李四’, 2, 23, ‘女’, ‘广州’);
•不写字段名
INSERT INTO student VALUES (3, ‘王五’, 18, ‘男’, ‘北京’);
什么是蠕虫复制:在已有的数据基础之上,将原来的数据进行复制,插入到对应的表中 语法格式:INSERT INTO 表名1 SELECT * FROM 表名2; 作用:将表名2中的数据复制到表名1中
具体操作:
•创建student表,student结构和student2表结构一样
CREATE TABLE student LIKE student2;
•将student2表中的数据添加到student表中
INSERT INTO student SELECT * FROM student2;
注意:如果只想复制student表中name,age字段数据到student2表中使用如下格式 INSERT INTO student2(NAME, age) SELECT NAME, age FROM student;
1.不带条件修改数据 UPDATE 表名 SET 字段名=值;
2.带条件修改数据 UPDATE 表名 SET 字段名=值 WHERE 字段名=值;
3.关键字说明
UPDATE: 修改数据
SET: 修改哪些字段
WHERE: 指定条件
4.具体操作:
–不带条件修改数据,将所有的性别改成女
UPDATE student SET sex=‘女’;
–带条件修改数据,将id号为2的学生性别改成男
UPDATE student SET sex=‘男’ WHERE id=2;
–一次修改多个列,把id为3的学生,年龄改成26岁,address改成北京
UPDATE student SET age=26, address=‘北京’ WHERE id=3;
update student set studentname='张三'
update student set studentname='李四',age=20
update student set studentname='小毛',age=30 where id=1
update student set studentname='小邓',age=29 where id=2
update student set age=33 where studentname='小邓'
update student set studentname='王五' where id >2
update student set birthday='2000-11-11' where studentname='王五' and age=20
update student set sex='女' where studentname='王五' or age=28
update student set age=40 where id=1 or id=3 or id=5
update student set age=50 where id in(1,3,5)
update student set age=30 where studentname='赵六'
update student set age=age+5 where studentname='小毛'
update student set sex='男' where age>=20 and age<=30
update student set sex='女' where age between 20 and 30
1.不带条件删除数据 DELETE FROM 表名;
2.带条件删除数据 DELETE FROM 表名 WHERE 字段名=值;
3.具体操作:
–带条件删除数据,删除id为3的记录
DELETE FROM student WHERE id=3;
–不带条件删除数据,删除表中的所有数据
DELETE FROM student;
delete from student where id=1
delete from student where id !=1
delete from student where id in (1,3,5)
delete from student where id not in (1,3,5)
delete from student where sex is null
delete from student where sex is not null
select
(实际使用最多,查询)查询不会对数据库中的数据进行修改.只是一种显示数据的方式
1.使用*表示所有列 SELECT * FROM 表名; 具体操作:
SELECT * FROM student;
2.写出查询每列的名称 SELECT 字段名1, 字段名2, 字段名3, … FROM 表名; 具体操作:
SELECT id, NAME ,age, sex, address FROM student;
查询指定列的数据,多个列之间以逗号分隔 SELECT 字段名1, 字段名2… FROM 表名;
具体操作: 查询student表中的name 和 age 列
SELECT NAME, age FROM student;
1.查询时给列、表指定别名需要使用AS关键字
2.使用别名的好处是方便观看和处理查询到的数据 SELECT 字段名1 AS 别名, 字段名2 AS 别名… FROM 表名; SELECT 字段名1 AS 别名, 字段名2 AS 别名… FROM 表名 AS 表别名; 注意:
查询给表取别名目前还看不到效果,需要到多表查询的时候才能体现出好处 AS关键字可以省略
3.具体操作:
–查询sudent表中name 和 age 列,name列的别名为”姓名”,age列的别名为”年龄”
SELECT NAME AS ‘姓名’, age AS ‘年龄’ FROM student;
–查询sudent表中name和age列,student表别名为s
SELECT NAME, age FROM student AS s;
查询给表取别名目前还看不到效果,需要到多表查询的时候才能体现出好处
1.查询指定列并且结果不出现重复数据 SELECT DISTINCT 字段名 FROM 表名;
2.具体操作:
–查询name,age列并且结果不出现重复
SELECT DISTINCT NAME, age FROM student;
1.某列数据和固定值运算 SELECT 列名1 + 固定值 FROM 表名;
2.某列数据和其他列数据参与运算 SELECT 列名1 + 列名2 FROM 表名;
注意: 参与运算的必须是数值类型
3.需求:
–添加数学,英语成绩列,给每条记录添加对应的数学和英语成绩
–查询的时候将数学和英语的成绩相加
4.实现:
•修改student表结构,添加数学和英语成绩列
ALTER TABLE student ADD math INT;
ALTER TABLE student ADD english INT;
• 给每条记录添加对应的数学和英语成绩
•查询math + english的和
SELECT math + english FROM student;
结果确实将每条记录的math和english相加,但是效果不好看
•查询math + english的和使用别名”总成绩”
SELECT math + english ‘总成绩’ FROM student;
•查询所有列与math + english的和并使用别名”总成绩”
SELECT *, math + english ‘总成绩’ FROM student;
•查询姓名、年龄,将每个人的年龄增加10岁
SELECT name, age + 10 FROM student;
emloyee表
comm_pct 字段表示 佣金比率
佣金 = 年薪*佣金比率
select name,salary,salary*12 '年薪',salary*12*comm_pct+salary*12 '年收入' from employee
grant,revoke
(创建撤销用户分配权限,了解)前面我们的查询都是将所有数据都查询出来,但是有时候我们只想获取到满足条件的数据 语法格式:SELECT 字段名 FROM 表名 WHERE 条件; 流程:取出表中的每条数据,满足条件的记录就返回,不满足条件的记录不返回
CREATE TABLE student3 (
id int,
name varchar(20),
age int,
sex varchar(5),
address varchar(100),
math int,
english int
);
INSERT INTO student3(id,NAME,age,sex,address,math,english) VALUES (1,'马云',55,'男','杭州',66,78),(2,'马化腾',45,'女','深圳',98,87),(3,'马景涛',55,'男','香港',56,77),(4,'柳岩',20,'女','湖南',76,65),(5,'柳青',20,'男','湖南',86,NULL),(6,'刘德华',57,'男','香港',99,99),(7,'马德',22,'女','香港',99,99),(8,'德玛西亚',18,'男','南京',56,65);
大于 <小于 <=小于等于 >=大于等于 =等于 <>、!=不等于
具体操作:
1.查询math分数大于80分的学生
SELECT * FROM student3 WHERE math>80;
SELECT * FROM student3 WHERE english<=80;
3.查询age等于20岁的学生
SELECT * FROM student3 WHERE age=20;
SELECT * FROM student3 WHERE age!=20;
SELECT * FROM student3 WHERE age<>20;
and(&&) 多个条件同时满足 or(||) 多个条件其中一个满足 not(!) 不满足
具体操作:
5.查询age大于35且性别为男的学生(两个条件同时满足)
SELECT * FROM student3 WHERE age>35 AND sex='男';
6.查询age大于35或性别为男的学生(两个条件其中一个满足)
SELECT * FROM student333 WHERE age>35 OR sex='男';
SELECT * FROM student3 WHERE id=1 OR id=3 OR id=5;
in关键字 语法格式:SELECT 字段名 FROM 表名 WHERE 字段 in (数据1, 数据2…); in里面的每个数据都会作为一次条件,只要满足条件的就会显示
具体操作:
8.查询id是1或3或5的学生
SELECT * FROM student3 WHERE id IN (1,3,5);
SELECT * FROM student3 WHERE id NOT IN (1,3,5);
BETWEEN 值1 AND 值2 表示从值1到值2范围,包头又包尾 比如:age BETWEEN 80 AND 100 相当于: age>=80 && age<=100
具体操作:
10.查询english成绩大于等于75,且小于等于90的学生
SELECT * FROM student3 WHERE english>=75 AND english<=90;
SELECT * FROM student3 WHERE english BETWEEN 75 AND 90;
LIKE表示模糊查询 SELECT * FROM 表名 WHERE 字段名 like ‘通配符字符串’;
满足通配符字符串`规则的数据就会显示出来 MySQL通配符有两个:
%: 表示0个或多个字符(任意个字符)
_: 表示一个字符
具体操作:
11.查询姓马的学生
SELECT * FROM student3 WHERE NAME LIKE '马%';
SELECT * FROM student3 WHERE NAME LIKE '%德%';
SELECT * FROM student3 WHERE NAME LIKE '马__';
ORDER BY
通过ORDER BY子句,可以将查询出的结果进行排序(排序只是显示方式,不会影响数据库中数据的顺序) SELECT 字段名 FROM 表名 WHERE 字段=值 ORDER BY 字段名 [ASC|DESC]; ASC: 升序, 默认是升序, DESC: 降序
[]里代表可写可不写,不写默认升序哈
Order by 后可以跟 列名 、 列别名、数字
单列排序就是使用一个字段排序
具体操作:
14.查询所有数据,使用年龄降序排序
SELECT * FROM student3 ORDER BY age DESC;
select id,name,age a from student3 order by a desc
select id,name,age from student3 order by 3
select id,name,age from student3 order by 1
select * from student3 order by 3 desc
组合排序就是先按第一个字段进行排序,如果第一个字段相同,才按第二个字段进行排序,依次类推。 上面的例子中,年龄是有相同的。当年龄相同再使用math进行排序 SELECT 字段名 FROM 表名 WHERE 字段=值 ORDER BY 字段名1 [ASC|DESC], 字段名2 [ASC|DESC];
具体操作:
15.查询所有数据,在年龄降序排序的基础上,如果年龄相同再以数学成绩降序排序
SELECT * FROM student3 ORDER BY age DESC, math DESC;
count
个数
sum
总数
avg
平均数
max
最大值
min
最小值
聚合函数,忽略null值
之前我们做的查询都是横向查询,它们都是根据条件一行一行的进行判断,而使用聚合函数查询是纵向查询,它是对一列的值进行计算,然后返回一个结果值。另外聚合函数会忽略空值
五个聚合函数: count: 统计指定列记录数,记录为NULL的不统计 sum: 计算指定列的数值和,如果不是数值类型,那么计算结果为0 max: 计算指定列的最大值 min: 计算指定列的最小值 avg: 计算指定列的平均值,如果不是数值类型,那么计算结果为0
聚合函数的使用:写在 SQL语句SELECT后 字段名的地方 SELECT 字段名… FROM 表名; SELECT COUNT(age) FROM 表名;
具体操作:
SELECT COUNT(*) FROM student3;
SELECT COUNT(*) FROM student3 WHERE age>40;
SELECT SUM(math) FROM student3;
18.查询数学成绩平均分
SELECT AVG(math) FROM student3;
SELECT MAX(math) FROM student3;
SELECT MIN(math) FROM student3;
各个数据库,单行函数基本都不相同。
Mysql数据库的单行函数格式非常多。
ifnull(expr1,expr2)
判断expr1是否为null
不为null 返回expr1
为null 返回expr2
select name,salary,salary*12 '年薪' , salary*12*comm_pct+salary*12 from employee
select name,salary,salary*12 '年薪' , salary*12*ifnull(comm_pct,0)+salary*12 from employee
select avg(ifnull(english,0)) from student3
sysdate()
select sysdate() from dual
select sysdate()
Now()
Curdate()
Curtime()
分组查询是指使用 GROUP BY语句对查询信息进行分组,相同数据作为一组 SELECT 字段1,字段2… FROM 表名 GROUP BY 分组字段 [HAVING 条件];
GROUP BY怎么分组的?将分组字段结果中相同内容作为一组 SELECT * FROM student3 GROUP BY sex;
这句话会将sex相同的数据作为一组
GROUP BY将分组字段结果中相同内容作为一组,并且返回每组的第一条数据,所以单独分组没什么用处。分组的目的就是为了统计,一般分组会跟聚合函数一起使用。
分组后聚合函数的作用?不是操作所有数据,而是操作一组数据。
SELECT SUM(math), sex FROM student3 GROUP BY sex;
效果如下:
实际上是将每组的math进行求和,返回每组统计的结果
注意事项:当我们使用某个字段分组,在查询的时候也需要将这个字段查询出来,否则看不到数据属于哪组的
1.查询的时候没有查询出分组字段
2.查询的时候查询出分组字段
具体步骤:
3.按性别分组
SELECT sex FROM student3 GROUP BY sex;
4.查询男女各多少人
1.查询所有数据,按性别分组。 2.统计每组人数
SELECT sex, COUNT(*) FROM student3 GROUP BY sex;
5.查询年龄大于25岁的人,按性别分组,统计每组的人数
1.先过滤掉年龄小于25岁的人。2.再分组。3.最后统计每组的人数
SELECT sex, COUNT(*) FROM student3 WHERE age > 25 GROUP BY sex;
运算顺序,先where 在group by 再 count 喔!
6.查询年龄大于25岁的人,按性别分组,统计每组的人数,并只显示性别人数大于2的数据
有很多人可能会将SQL语句写出这样: SELECT sex, COUNT() FROM student3 WHERE age > 25 GROUP BY sex WHERE COUNT() >2;
注意: 并只显示性别人数>2的数据属于分组后的条件,对于分组后的条件需要使用having子句
SELECT sex, COUNT(*) FROM student3 WHERE age > 25 GROUP BY sex HAVING COUNT(*) >2;
只有分组后人数大于2的‘男’这组数据显示出来
having与where的区别(咳咳,敲黑板)
having是在分组后对数据进行过滤,where是在分组前对数据进行过滤
having后面可以使用聚合函数,where后面不可以使用聚合函数
LIMIT是限制的意思,所以LIMIT的作用就是限制查询记录的条数。
SELECT *|字段列表 [as 别名] FROM 表名 [WHERE子句] [GROUP BY子句][HAVING子句][ORDER BY子句][LIMIT子句];
思考:limit子句为什么排在最后?
因为前面所有的限制条件都处理完了,只剩下显示多少条记录的问题了!
LIMIT语法格式: LIMIT offset,length;
或者limit length; offset是指偏移量,可以认为是跳过的记录数量,默认为0 —》》从哪开始 length是指需要显示的总记录数 —》》显示几条
具体步骤:
准备数据:
INSERT INTO student3(id,NAME,age,sex,address,math,english) VALUES
(9,'唐僧',25,'男','长安',87,78),
(10,'孙悟空',18,'男','花果山',100,66),
(11,'猪八戒',22,'男','高老庄',58,78),
(12,'沙僧',50,'男','流沙河',77,88),
(13,'白骨精',22,'女','白虎岭',66,66),
(14,'蜘蛛精',23,'女','盘丝洞',88,88);
1.查询学生表中数据,从第三条开始显示,显示6条
我们可以认为跳过前面2条,取6条数据
SELECT * FROM student3 LIMIT 2,6;
LIMIT的使用场景:分页 比如我们登录京东,淘宝,返回的商品信息可能有几万条,不是一次全部显示出来。是一页显示固定的条数。 假设我们一每页显示5条记录的方式来分页,SQL语句如下:
– 每页显示5条
– 第一页: LIMIT 0,5; 跳过0条,显示5条
– 第二页: LIMIT 5,5; 跳过5条,显示5条
– 第三页: LIMIT 10,5; 跳过10条,显示5条
SELECT * FROM student3 LIMIT 0,5;
SELECT * FROM student3 LIMIT 5,5;
SELECT * FROM student3 LIMIT 10,5;
注意:
如果第一个参数是0可以简写: SELECT * FROM student3 LIMIT 0,5; SELECT * FROM student3 LIMIT 5;
LIMIT 10,5; – 不够5条,有多少显示多少
top
SQLserver不支持limit关键字,要实现相应的功能,需使用top关键字。
查询前10行数据:
select top 10 * from student3 order by id;
在服务器进行数据传输、数据存储和数据交换,就有可能产生数据故障。比如发生意外停机或存储介质损坏。这时,如果没有采取数据备份和数据恢复手段与措施,就会导致数据的丢失,造成的损失是无法弥补与估量的。
备份格式: mysqldump -u用户名 -p密码 数据库 > 文件的路径
还原格式: SOURCE 导入文件的路径;
注意:还原的时候需要先登录MySQL,并选中对应的数据库
数据库中的所有表和数据都会导出成SQL语句
•还原数据库中的数据,先把备份的数据库里面的表删了(别删错了)
drop table 表名
–登录MySQL
mysql -uroot -proot
–选中数据库
use 数据库;
select database();
–使用SOURCE命令还原数据
source F:\code\bak.sql
图形更简单了在此就不细说,选中相应的数据库,右键找到“导出/备份”,指定保存路径即可
还原的话,先给库中数据删了(表不是库)
在数据库列表区域,右键找到运行sql文件或者执行sql脚本之类的话,因为每个叫法不一,找到后选择之前备份的文件,导入即可。
对表中的数据进行进一步的限制,保证数据的正确性、有效性和完整性。 约束种类:
•PRIMARY KEY: 主键约束
•UNIQUE: 唯一性约束
•NOT NULL: 非空约束
•FOREIGN KEY: 外键约束
Check 检查约束(用户自定义约束) ,比如:age字段的值必须大于0的整数MySQL不支持
用来唯一标识一条记录,每个表都应该有一个主键,并且每个表只能有一个主键。 有些记录的 name,age,score 字段的值都一样时,那么就没法区分这些数据,造成数据库的记录不唯一,这样就不方便管理数据
哪个字段应该作为表的主键? 通常不用业务字段作为主键,单独给每张表设计一个id的字段,把id作为主键。主键是给数据库和程序使用的,不是给最终的客户使用的。所以主键有没有含义没有关系,只要不重复,非空就行。
主键:PRIMARY KEY 主键的特点:
•主键必须包含唯一的值
•主键列不能包含NULL值
创建主键方式:
在创建表的时候给字段添加主键 字段名 字段类型 PRIMARY KEY
具体操作:
•创建表学生表st5, 包含字段(id, name, age)将id做为主键
CREATE TABLE st5 (
id INT PRIMARY KEY, -- id是主键
NAME VARCHAR(20),
age INT
);
INSERT INTO st5 (id, NAME) VALUES (1, '唐伯虎');
INSERT INTO st5 (id, NAME) VALUES (2, '周文宾');
INSERT INTO st5 (id, NAME) VALUES (3, '祝枝山');
INSERT INTO st5 (id, NAME) VALUES (4, '文征明');
•插入重复的主键值
-- 主键是唯一的不能重复:Duplicate entry '1' for key 'PRIMARY'
INSERT INTO st5 (id, NAME) VALUES (1, '文征明2');
•插入NULL的主键值
– 主键是不能为空的:Column ‘id’ cannot be null
INSERT INTO st5 (id, NAME) VALUES (NULL, ‘文征明3’);
创建主键的方式
create table student(
id int primary key,
name varchar(200),
age int
)
---------------------------------------------------------
create table student2(
id int,
name varchar(100),
age int,
primary key(id)
)
-------------------------------------------------------
create table student3(
id int,
name varchar(100),
age int
)
alter table student3 add constraint student3_pk primary key(id)
student3_pk 是创建主键时起的名字,可以省略
ALTER TABLE 表名 DROP PRIMARY KEY;
具体操作:
•删除st5表的主键
ALTER TABLE st5 DROP PRIMARY KEY;
主键如果让我们自己添加很有可能重复,我们通常希望在每次插入新记录时,数据库自动生成主键字段的值 AUTO_INCREMENT 表示自动增长(字段类型必须是整数类型)
具体操作:
•创建学生表st6, 包含字段(id, name, age)将id做为主键并自动增长
CREATE TABLE st6 (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
age INT
);
•插入数据
-- 主键默认从1开始自动增长
INSERT INTO st6 (NAME, age) VALUES ('唐僧', 22);
INSERT INTO st6 (NAME, age) VALUES ('孙悟空', 26);
INSERT INTO st6 (NAME, age) VALUES ('猪八戒', 25);
INSERT INTO st6 (NAME, age) VALUES ('沙僧', 20);
扩展 默认地AUTOINCREMENT 的开始值是1,如果希望修改起始值,请使用下列SQL语法 ALTER TABLE 表名 AUTO_INCREMENT=起始值;
起始值要大于等于1
DELETE和TRUNCATE的区别
DELETE 删除表中的数据,但不重置AUTO_INCREMENT的值。
TRUNCATE 摧毁表,重建表,AUTO_INCREMENT重置为1
在这张表中这个字段的值不能重复
字段名 字段类型 UNIQUE
具体步骤:
•创建学生表st7, 包含字段(id, name),name这一列设置唯一约束,不能出现同名的学生
CREATE TABLE st7 (
id INT,
NAME VARCHAR(20) UNIQUE
);
•添加一个学生
INSERT INTO st7 VALUES (1, '貂蝉');
INSERT INTO st7 VALUES (2, '西施');
INSERT INTO st7 VALUES (3, '王昭君');
INSERT INTO st7 VALUES (4, '杨玉环');
-- 插入相同的名字出现name重复: Duplicate entry '貂蝉' for key 'name'
INSERT INTO st7 VALUES (5, '貂蝉');
-- 出现多个null的时候会怎样?因为null是没有值,所以不存在重复的问题
INSERT INTO st3 VALUES (5, NULL);
INSERT INTO st3 VALUES (6, NULL);
添加唯一约束方式:
create table student2(
id int primary key,
name varchar(200),
email varchar(200) unique
)
--------------------------------------
create table student3(
id int primary key,
name varchar(200),
email varchar(200),
unique(email)
)
-------------------------------------------
create table student4(
id int primary key,
name varchar(200),
email varchar(200)
)
alter table student4 add constraint stu_uni unique(email)
这个字段必须设置值,不能是NULL
字段名 字段类型 NOT NULL
具体操作:
•创建表学生表st8, 包含字段(id,name,gender)其中name不能为NULL
CREATE TABLE st8 (
id INT,
NAME VARCHAR(20) NOT NULL,
gender Varchar(2)
);
•添加一条完整的记录
INSERT INTO st8 VALUES (1, '郭富城', '男');
INSERT INTO st8 VALUES (2, '黎明', '男');
INSERT INTO st8 VALUES (3, '张学友', '男');
INSERT INTO st8 VALUES (4, '刘德华', '男');
-- 姓名不赋值出现姓名不能为null: Column 'name' cannot be null
INSERT INTO st8 VALUES (5, NULL, '男');
往表中添加数据时,如果不指定这个字段的数据,就使用默认值
默认值格式 字段名 字段类型 DEFAULT 默认值
具体步骤:
•创建一个学生表 st9,包含字段(id,name,address), 地址默认值是广州
CREATE TABLE st9 (
id INT,
NAME VARCHAR(20),
address VARCHAR(50) DEFAULT '广州'
);
•添加一条记录,使用默认地址
INSERT INTO st9 (id, NAME) VALUES (1, '刘德华');
INSERT INTO st9 VALUES (2, '张学友', '香港');
疑问:如果一个字段设置了非空与唯一约束,该字段与主键的区别
•一张表中只有一个字段可以设置为主键
•一张表中可以多个字段非空与唯一约束
•主键可以自动增长,非空与唯一约束的字段不能自动增长
添加非空约束的方式
create table student2(
id int primary key auto_increment,
name varchar(200) not null,
age int
)
--------------------------------------------------------------------------------
create table student3(
id int primary key auto_increment,
name varchar(200),
age int
)
alter table student3 modify name varchar(200) not null
创建一个员工表包含如下列(id, name, age, depname, deplocation),id主键并自动增长,添加5条数据
CREATE TABLE emp (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(30),
age INT,
dep_name VARCHAR(30),
dep_location VARCHAR(30)
);
-- 添加数据
INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('张三', 20, '研发部', '广州');
INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('李四', 21, '研发部', '广州');
INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('王五', 20, '研发部', '广州');
INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('老王', 20, '销售部', '深圳');
INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('大王', 22, '销售部', '深圳');
INSERT INTO emp (NAME, age, dep_name, dep_location) VALUES ('小王', 18, '销售部', '深圳');
缺点:表中出现了很多重复的数据(数据冗余),如果要修改研发部的地址需要修改3个地方。
解决方案:将一张表分成2张表(员工表和部门表)
-- 创建部门表
CREATE TABLE department (
id INT PRIMARY KEY AUTO_INCREMENT,
dep_name VARCHAR(20),
dep_location VARCHAR(20)
);
-- 创建员工表
CREATE TABLE employee (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
age INT,
dep_id INT
);
-- 添加2个部门
INSERT INTO department (dep_name, dep_location) VALUES ('研发部', '广州'), ('销售部', '深圳');
-- 添加员工,dep_id表示员工所在的部门
INSERT INTO employee (NAME, age, dep_id) VALUES
('张三', 20, 1),
('李四', 21, 1),
('王五', 20, 1),
('老王', 20, 2),
('大王', 22, 2),
('小王', 18, 2);
问题: 当我们在employee的depid里面输入不存在的部门,数据依然可以添加.但是并没有对应的部门,不能出现这种情况。employee的depid中的内容只能是department表中存在的id
目标:需要约束dep_id只能是department表中已经存在id 解决方式:使用外键约束
一张表中的某个字段引用另一个表的主键 主表: 约束别人 副表/从表: 使用别人的数据,被别人约束
新建表时增加外键: [CONSTRAINT] [外键约束名称] FOREIGN KEY(外键字段名) REFERENCES 主表名(主键字段名) 关键字解释: CONSTRAINT – 约束关键字 FOREIGN KEY(外键字段名) –- 某个字段作为外键 REFERENCES – 主表名(主键字段名) 表示参照主表中的某个字段
具体操作:
•副表/从表: 被别人约束,表结构添加外键约束
CREATE TABLE employee (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
age INT,
dep_id INT,
-- 添加一个外键
-- 外键取名公司要求,一般fk结尾
CONSTRAINT emp_depid_ref_dep_id_fk FOREIGN KEY(dep_id) REFERENCES department(id)
);
create table emp(
id int primary key auto_increment,
name varchar(200),
salary double,
dept_id int
)
create table dept(
id int primary key auto_increment,
name varchar(200),
address varchar(200)
)
alter table emp add constraint emp_fk foreign key(dept_id) references dept(id)
外键名 emp_fk 可以省略
•正常添加数据
INSERT INTO employee (NAME, age, dep_id) VALUES
('张三', 20, 1),
('李四', 21, 1),
('王五', 20, 1),
('老王', 20, 2),
('大王', 22, 2),
('小王', 18, 2);
•部门错误的数据会添加失败
INSERT INTO employee (NAME, age, dep_id) VALUES ('二王', 20, 5);
要把部门表中的id值2,改成5,能不能直接修改呢?
UPDATE department SET id=5 WHERE id=2;
不能直接修改:Cannot delete or update a parent row: a foreign key constraint fails (错误信息)
如果副表(员工表)中有引用的数据,不能直接修改主表(部门表)主键
要删除部门id等于1的部门, 能不能直接删除呢?
DELETE FROM department WHERE id=1;
不能直接删除:Cannot delete or update a parent row: a foreign key constraint fails
如果副表(员工表)中有引用的数据,不能直接删除主表(部门表)数据
什么是级联操作: 在修改和删除主表的主键时,同时更新或删除副表的外键值,称为级联操作 ON UPDATE CASCADE – 级联更新,主键发生更新时,外键也会更新 ON DELETE CASCADE – 级联删除,主键发生删除时,外键也会删除
具体操作:
•删除employee表
•重新创建employee表,添加级联更新和级联删除
CREATE TABLE employee (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(30),
age INT,
dep_id INT,
-- 添加外键约束,并且添加级联更新和级联删除
CONSTRAINT employee_dep_fk FOREIGN KEY (dep_id) REFERENCES department(id) ON UPDATE CASCADE ON DELETE CASCADE
);
•再次添加数据到员工表和部门表
INSERT INTO employee (NAME, age, dep_id) VALUES ('张三', 20, 1);
INSERT INTO employee (NAME, age, dep_id) VALUES ('李四', 21, 1);
INSERT INTO employee (NAME, age, dep_id) VALUES ('王五', 20, 1);
INSERT INTO employee (NAME, age, dep_id) VALUES ('老王', 20, 2);
INSERT INTO employee (NAME, age, dep_id) VALUES ('大王', 22, 2);
INSERT INTO employee (NAME, age, dep_id) VALUES ('小王', 18, 2);
•把部门表中id等于1的部门改成id等于10
UPDATE department SET id=10 WHERE id=1;
DELETE FROM department WHERE id=2;
现实生活中,实体与实体之间肯定是有关系的,比如:老公和老婆,部门和员工,老师和学生等。那么我们在设计表的时候,就应该体现出表与表之间的这种关系!分成三种:
1.一对一
2.一对多 多对一
3.多对多
一对多(1:n) 例如:班级和学生,部门和员工,客户和订单,分类和商品 一对多建表原则: 在从表(多方)创建一个字段,字段作为外键指向主表(一方)的主键
多对多(m:n) 例如:老师和学生,学生和课程,用户和角色 多对多关系建表原则: 需要创建第三张表,中间表中至少两个字段,这两个字段分别作为外键指向各自一方的主键。
一对一(1:1) 在实际的开发中应用不多.因为一对一可以创建成一张表。 两种建表原则:
•外键唯一:主表的主键和从表的外键(唯一),形成主外键关系
外键是主键:主表的主键和从表的主键,形成主外键关系
一个旅游线路分类中有多个旅游线路,根据需求来设计数据库表之间的关系
具体操作:
•创建旅游线路分类表
CREATE TABLE tab_category (
cid INT PRIMARY KEY AUTO_INCREMENT, -- 旅游线路分类主键
cname VARCHAR(100) NOT NULL UNIQUE -- 旅游线路分类名称
);
•添加旅游线路分类数据
INSERT INTO tab_category (cname) VALUES ('周边游'), ('出境游'), ('国内游'), ('港澳游');
•创建旅游线路表
CREATE TABLE tab_route (
rid INT PRIMARY KEY AUTO_INCREMENT, -- 旅游线路主键
rname VARCHAR(100) NOT NULL UNIQUE, -- 旅游线路名称
price DOUBLE NOT NULL, -- 价格
routeIntroduce VARCHAR(200), -- 线路介绍
rflag CHAR(1) NOT NULL, -- 是否上架
rdate VARCHAR(19) NOT NULL, -- 上架时间
isThemeTour CHAR(1) NOT NULL, -- 是否主题旅游
acount INT DEFAULT 0, -- 收藏数量
cid INT NOT NULL, -- 所属分类
rimage VARCHAR(200) NOT NULL, -- 缩略图地址
CONSTRAINT ro_cid_ref_cate_id FOREIGN KEY(cid) REFERENCES tab_category(cid)
);
•添加旅游线路数据
INSERT INTO tab_route VALUES
(NULL, '【厦门+鼓浪屿+南普陀寺+曾厝垵 高铁3天 惠贵团】尝味友鸭面线 住1晚鼓浪屿', 1499, '春节国内游优惠:即日起至2018年1月31号,5-9人同时报名立减¥100/人,10人及以上同时报名立减¥150/人。仅限2月10-22日春节期间出发享优惠,自由行及特价产品不参与!', 1, '2018-01-27', 0, 100, 3, 'c:\1.png'),
(NULL, '【浪漫桂林 阳朔西街高铁3天纯玩 高级团】城徽象鼻山 兴坪漓江 西山公园', 699, '春节国内游优惠:即日起至2018年1月31号,5-9人同时报名立减¥100/人,10人及以上同时报名立减¥150/人。仅限2月10-22日春节期间出发享优惠,自由行及特价产品不参与!', 1, '2018-01-27', 0, 66, 3, 'c:\2.png'),
(NULL, '【爆款¥1699秒杀】泰国 曼谷 芭堤雅 金沙岛 杜拉拉水上市场 双飞六天【含送签费 泰风情 广州往返 特价团】', 1699, '1月15日至2月11日官网特卖!①出境全线正价线路(特价线除外)满2人立减¥60!满4人立减¥200!满5人立减¥500!', 1, '2018-01-27', 0, 15, 2, 'c:\123.png'),
(NULL, '【经典·狮航 ¥2399秒杀】巴厘岛双飞五天 抵玩【广州往返 特价团】', 2399, '官网特卖!2-3月出发,前10名网付立享¥2399/人!', 1, '2018-01-27', 0, 22, 2, 'c:\3.png'),
(NULL, '香港迪士尼乐园自由行2天【永东跨境巴士广东至迪士尼去程交通+迪士尼一日门票+香港如心海景酒店暨会议中心标准房1晚住宿】', 799, '永东巴士提供广东省内多个上车地点,购买后需自行致电永东巴士客服电话4008861668预约车位', 1, '2018-01-27', 0, 38, 4, 'c:\4.png');
对于多对多的关系我们需要增加一张中间表来维护他们之间的关系
具体操作:
•创建用户表
CREATE TABLE tab_user (
uid INT PRIMARY KEY AUTO_INCREMENT, -- 用户id
username VARCHAR(100) NOT NULL UNIQUE, -- 用户名
PASSWORD VARCHAR(30) NOT NULL, -- 密码
NAME VARCHAR(100), -- 真实姓名
birthday DATE, -- 生日
sex CHAR(1), -- 性别
telephone VARCHAR(11), -- 手机号
email VARCHAR(100), -- 邮箱
STATUS CHAR(1) NOT NULL, -- 是否激活状态
CODE VARCHAR(32) NOT NULL UNIQUE -- 激活码
);
•添加用户数据
INSERT INTO tab_user VALUES
(NULL, 'cz110', 123456, '老王', '1977-07-07', '男', '13888888888', '[email protected]', '是', '1386'),
(NULL, 'cz119', 654321, '小王', '1999-09-09', '男', '13999999999', '[email protected]', '是', '9898');
•创建收藏表
CREATE TABLE tab_favorite (
rid INT NOT NULL, -- 旅游线路id
DATE DATE NOT NULL, -- 收藏时间
uid INT NOT NULL -- 用户id
);
•增加收藏表数据
INSERT INTO tab_favorite VALUES
(NULL, 1, '2018-01-01', 1), -- 老王选择厦门
(NULL, 1, '2018-01-01', 2), -- 老王选择桂林
(NULL, 1, '2018-01-01', 3), -- 老王选择泰国
(NULL, 2, '2018-01-01', 2), -- 小王选择桂林
(NULL, 2, '2018-01-01', 3), -- 小王选择泰国
(NULL, 2, '2018-01-01', 5); -- 小王选择迪士尼
同时查询多张表获取到需要的数据 比如:我们想查询到开发部有多少人,需要将部门表和员工表同时进行查询
多表查询的分类:
准备数据:
-- 创建部门表
CREATE TABLE dept (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20)
);
INSERT INTO dept (NAME) VALUES ('开发部'),('市场部'),('财务部');
-- 创建员工表
CREATE TABLE emp (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10),
gender CHAR(1), -- 性别
salary DOUBLE, -- 工资
join_date DATE, -- 入职日期
dept_id INT
);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('孙悟空','男',7200,'2013-02-24',1);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('猪八戒','男',3600,'2010-12-02',2);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('唐僧','男',9000,'2008-08-08',2);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('白骨精','女',5000,'2015-10-07',3);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('蜘蛛精','女',4500,'2011-03-14',1);
多表查询时左表的每条数据和右表的每条数据组合,这种效果成为笛卡尔积
需求:查询每个部门有哪些人
具体操作:
SELECT * FROM dept, emp;
以上数据其实是左表的每条数据和右表的每条数据组合。左表有3条,右表有5条,最终组合后3*5=15条数据。
左表的每条数据和右表的每条数据组合,这种效果称为笛卡尔乘积(咳咳!敲黑板面试会有问)
我们发现不是所有的数据组合都是有用的,只有员工表.dept_id = 部门表.id 的数据才是有用的。所以需要通过条件过滤掉没用的数据。
SELECT * FROM dept, emp WHERE emp.`dept_id`=dept.`id`;
用左边表的记录去匹配右边表的记录,如果符合条件的则显示
隐式内连接:看不到JOIN关键字,条件使用WHERE指定 SELECT 字段名 FROM 左表, 右表 WHERE 条件;
select * from emp,dept where emp.dept_id = dept.id
显示内连接:使用INNER JOIN … ON语句, 可以省略INNER SELECT 字段名 FROM 左表 INNER JOIN 右表 ON 条件;
具体操作:
•查询唐僧的信息,显示员工id,姓名,性别,工资和所在的部门名称,我们发现需要联合2张表同时才能查询出需要的数据,我们使用内连接
1.确定查询哪些表
SELECT * FROM dept INNER JOIN emp;
1.确定表连接条件,员工表.dept_id = 部门表.id 的数据才是有效的
SELECT * FROM dept INNER JOIN emp ON emp.`dept_id`=dept.`id`;
1.确定表连接条件,我们查询的是唐僧的信息,员工表.name=‘唐僧’
SELECT * FROM dept INNER JOIN emp ON emp.`dept_id`=dept.`id` AND emp.`NAME`='唐僧';
1.确定查询字段,查询唐僧的信息,显示员工id,姓名,性别,工资和所在的部门名称
SELECT emp.`id`, emp.`NAME`, emp.`gender`, emp.`salary`, dept.`NAME` FROM dept INNER JOIN emp ON emp.`dept_id`=dept.`id` AND emp.`NAME`='唐僧';
1.我们发现写表名有点长,可以给表取别名,显示的字段名也使用别名
SELECT e.`id` 员工编号, e.`NAME` 员工姓名, e.`gender` 性别, e.`salary` 工资, d.`NAME` 部门名称 FROM dept d INNER JOIN emp e ON e.`dept_id`=d.`id` AND e.`NAME`='唐僧';
总结内连接查询步骤:
1.确定查询哪些表
2.确定表连接条件
3.确定查询字段
查询出工资比白骨精高的员工的姓名和工资
select e1.name,e1.salary from emp e1,emp e2 where e1.salary > e2.salary and e2.name='白骨精'
左外连接:使用LEFT OUTER JOIN … ON,OUTER可以省略 SELECT 字段名 FROM 左表 LEFT OUTER JOIN 右表 ON 条件; 用左边表的记录去匹配右边表的记录,如果符合条件的则显示;否则,显示NULL 可以理解为:在内连接的基础上保证左表的数据全部显示
具体操作:
•在部门表中增加一个销售部
INSERT INTO dept (NAME) VALUES ('销售部');
SELECT * FROM dept INNER JOIN emp ON emp.`dept_id`=dept.`id`;
SELECT * FROM dept LEFT OUTER JOIN emp ON emp.`dept_id`=dept.`id`;
右外连接:使用RIGHT OUTER JOIN … ON,OUTER可以省略 SELECT 字段名 FROM 左表 RIGHT OUTER JOIN 右表 ON 条件; 用右边表的记录去匹配左边表的记录,如果符合条件的则显示;否则,显示NULL 可以理解为:在内连接的基础上保证右表的数据全部显示
具体操作:
•在员工表中增加一个员工 INSERT INTO
emp(NAME,gender,salary,joindate,deptid) VALUES('沙僧','男',6666,'2013-02-24',NULL);
SELECT * FROM dept INNER JOIN emp ON emp.dept_id=dept.id;
SELECT * FROM dept RIGHT OUTER JOIN emp ON emp.dept_id=dept.id;
一条SELECT语句结果作为另一条SELECT语法一部分 SELECT 查询字段 FROM 表 WHERE 查询条件; SELECT * FROM employee WHERE salary=(SELECT MAX(salary) FROM employee);
子查询需要放在()中
主查询 ------> 子查询
外查询 ------> 内查询
子查询结果的三种情况:
1.子查询的结果是一个值的时候
2.子查询结果是单例多行的时候
3.子查询的结果是多行多列
说明: 子查询结果只要是单列,肯定在WHERE后面作为条件 子查询结果只要是多列,肯定在FROM后面作为表
子查询结果只要是单列,肯定在WHERE后面作为条件 SELECT 查询字段 FROM 表 WHERE 字段=(子查询);
1.查询工资最高的员工是谁?
1.查询最高工资是多少
SELECT MAX(salary) FROM emp;
SELECT * FROM emp WHERE salary=(SELECT MAX(salary) FROM emp);
2.查询工资小于平均工资的员工有哪些?
1.查询平均工资是多少
SELECT AVG(salary) FROM emp;
SELECT * FROM emp WHERE salary < (SELECT AVG(salary) FROM emp);
单行子查询使用单行运算符
= > >= < <= != like …
多行子查询要使用多行运算符
in
any
all
子查询结果只要是单列,肯定在WHERE后面作为条件 子查询结果是单例多行,结果集类似于一个数组,父查询使用IN运算符 SELECT 查询字段 FROM 表 WHERE 字段 IN (子查询);
1.查询工资大于5000的员工,来自于哪些部门的名字
1.先查询大于5000的员工所在的部门id
SELECT dept_id FROM emp WHERE salary > 5000;
SELECT dept.name FROM dept WHERE dept.id IN (SELECT dept_id FROM emp WHERE salary > 5000);
2.查询开发部与财务部所有的员工信息
1.先查询开发部与财务部的id
SELECT id FROM dept WHERE NAME IN('开发部','财务部');
SELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE NAME IN('开发部','财务部'));
any 和 all 不是单独使用的运算符,要和 比较运算符一起使用
select name,salary from emp where salary >any(select salary from emp where name='白骨精')
select name,salary from emp where salary >all(select salary from emp where name='白骨精')
子查询结果只要是多行多列,肯定在FROM后面作为表 SELECT 查询字段 FROM (子查询) 表别名 WHERE 条件; 子查询作为表需要取别名,否则这张表无法访问表中的字段
•查询出2011年以后入职的员工信息,包括部门名称
1.在员工表中查询2011-1-1以后入职的员工
SELECT * FROM emp WHERE join_date > '2011-1-1';
1.查询所有的部门信息,与上面的虚拟表中的信息组合,找出所有部门id等于的dept_id
SELECT * FROM dept d, (SELECT * FROM emp WHERE join_date > '2011-1-1') e WHERE e.dept_id = d.id;
id | name | age |
---|---|---|
1 | aaa | 20 |
2 | aaa | 20 |
3 | aaa | 20 |
4 | bbb | 30 |
5 | bbb | 30 |
6 | ccc | 40 |
写一条删除语句,删除 name和age重复的数据,留下id最小的那个
delete from ttt where id not in(select min(id) from ttt group by name,age) --其他数据库都可以,但mysql报错
delete from ttt where id not in(select min(id) from (select * from ttt) t group by name,age)
•子查询结果只要是单列,肯定在WHERE后面作为条件 SELECT 查询字段 FROM 表 WHERE 字段=(子查询);
•子查询结果只要是多列,肯定在FROM后面作为表 SELECT 查询字段 FROM (子查询) 表别名 WHERE 条件;
感谢各位的观看和支持,东西是不难,就是要多敲,看会是一回事,敲是一回事。
大家共同学习,共同进步,有总结的不足的多多指教,谢谢支持!
如需练习这里还有些单表和多表查询的文章点这里
单表-多表练习