1.数据的存储方式有哪些
特定的文件 / 内存 / 第三方云服务器 / 数据库服务器
2.什么是数据库
按照一定的形式来组织存放数据,目的是为了更快的操作数据——增删改查
(1)数据库的发展历史
网状数据库 – 层次型数据库 – 关系型数据库 - 非关系型数据库(NoSQL)
常见的关系型数据库
SQLite --微型数据库,常用于移动设备
MySQL --开源中小型数据库,可以用于各种操作系统
PostgreSQL --开源中小型数据库
SQL Server --Microsoft开发的中型数据库,只用于Windows操作系统
Oracle --Oracle公司开发的中大型数据库,可用于各种操作系统
DB2 --IBM公司开发的中大型数据库, 常与IBM服务器搭配
MySQL简介
http://www.mysql.com/downloads/
(2)关系型数据库的逻辑结构
Server - Database - Table - Row - Column
服务器 数据库 数据表 行 列
3.mysql数据库
Oracal:mysql
马丁:MariaDB
Xampp
服务器套装,包含多个服务器软件,例如mysql,Apache…
(1)部署结构
服务器端:负责存储维护数据 —— 银行的数据库服务器
启动文件 C:/xampp/mysql/bin/mysqld.exe
占用3306端口
客户端:负责连接服务器端,对数据进行操作 —— ATM机
客户端工具 C:/xampp/mysql/bin/mysql.exe
(2)使用客户端连接服务器端
mysql.exe -h127.0.0.1 -P3306 -uroot -p
-h host IP地址/域名 127.0.0.1/localhost
-P port 端口
-u user 用户名 root 管理员账户
-p password 密码 xampp下root的密码是空
mysql -uroot 简写形式
连接的命令结尾不能加分号
(3)常用管理命令(连接成功后)
quit; 退出服务器的连接
show databases; 显示当前所有的数据库
use 数据库名称; 进入到指定的数据库
show tables; 显示当前数据库中所有的数据表
desc 数据表名称; 描述数据表中都有哪些列
所有的管理命令都以英文的分号结尾
练习:分别进入到数据库test和phpmyadmin
练习:查看数据库mysql和information_schema中分别有多少个表
练习:分别查看以下数据表中都有哪些列
pma__recent
pma__history
pma__favorite
4.SQL命令
结构化查询语言:用于操作关系型数据库服务器,主要是对数据进行增删改查
SQL命令的执行方式
(1)交互模式
客户端输入一行,点击回车服务器端执行一行,适用于临时性的查看数据
(2)脚本模式
客户端把要执行的命令写在一个脚本文件中,一次性的提交给服务器执行,适用于批量的操作数据
再连接之前的命令行
mysql -uroot<拖拽脚本文件 回车
练习:编写脚本文件02.sql,打开脚本,显示当前数据库服务器下所有的数据库,进入到数据库phpmyadmin,显示当前数据库下所有的数据表,描述数据表pma__history有哪些列;提交给服务器执行
(3)SQL命令的语法规范
一条SQL命令可以跨越多行,以英文的分号作为结束
SQL命令不区分大小写,习惯上关键字大写,非关键字小写
假设某一条SQL命令出现语法错误,则此条命令及后边所有的命令不再被服务器执行
分为单行注释(#...)和多行注释(/*…*/)
5.常用的SQL命令
(1)丢弃数据库,如果存在的话
drop database if exists jd;
(2)创建新的数据库
create database jd;
(3)进入数据库
use jd;
(4)创建保存数据的表
create table student(
id int,
name varchar(8),
sex varchar(1),
score int
);
(5)插入数据
insert into student values(‘1’, ’tao’, ’b’, ’100’);
(6)查询数据
select * from student;
练习:编写脚本文件04_tedu.sql,打开文件,丢弃数据库tedu如果存在,再创建一个新的数据库tedu,进入创建的数据库
练习:在04_tedu.sql下,创建保存员工数据的表emp,包含有编号eid,姓名ename,地址addr,手机号码phone
练习:在04_tedu.sql下,往员工表emp下插入若干条数据,查询结果。
int存手机号存不下
(2)练习:编写脚本文件xz.sql,先丢弃再创建数据库xz,进入数据库,创建保存用户数据的表user,包含编号uid,用户名uname,密码upwd,邮箱email,手机号码phone,是否在线isOnline,真实姓名userName,注册时间regTime;插入若干条数据,查询结果
#客户端连接服务器端使用的编码是UTF8
set names utf8;
#丢弃数据库,如果存在
drop database if exists xz;
#创建新的数据库,设置存储的编码为utf8
create database xz charset=utf8;
#进入创建的数据库
use xz;
#创建数据表
create table user(
uid int,
uname varchar(16),
upwd varchar(32),
email varchar(32),
phone varchar(11),
isOnline varchar(1), #y/n
userName varchar(8),
regTime varchar(10) #2020-12-31
);
#插入数据
insert into user values('1','tao','123456','tao@tedu.cn','13132338889','y','涛哥','2020-12-31');
insert into user values('2','hua','444555','hua@126.com','15587332345','n','华哥','2015-1-1');
insert into user values('3','dong','666666','dong@qq.com','18334321345','n','东哥','2018-8-5');
#修改数据
update user set upwd='999999',phone='19913888898' where uid='1';
#删除数据
delete from user where uid='2';
#查询数据
select * from user;
1.SQL命令
(1)修改数据
update user set upwd='99999',phone='19912345678' where uid='1';
(2)删除数据
delete from user where uid='2';
2.计算机存储字符
(1)如何存储英文字符
ASCII 总共有128个,对英文字母及其符号进行了编码
Latin-1 总共有256个,对欧洲字符进行了编码,兼容ASCII
(2)如何存储中文字符
GB2312 对常用的6千多汉字进行了编码,兼容ASCII
GBK 对2万多的汉字进行了编码,兼容GB2312
BIG5 台湾繁字体编码,兼容ASCII
Unicode 对世界上主流国家常用的语言进行了编码,兼容ASCII,具体包含有utf-8、utf-16、utf-32
(3)mysql中文乱码产生的原因
mysql默认使用Latin-1,没有对汉字进行编码
(4)解决mysql中文乱码
脚本文件另存为的编码为utf8
客户端连接服务器端的编码为utf8
服务器端创建数据库存储的编码为utf8
练习:编写脚本文件01_sina.sql,先丢弃再创建数据库sina,设置编码为utf-8,进入数据库sina,创建保存新闻数据的表news,包含有编号nid,标题title,详情detail,发表时间ctime,来源origin;插入若干条数据,修改1条,删除1条。 在交互模式下写查询。
#设置客户端连接服务器端的编码
set names utf8;
#丢弃数据库,如果存在
drop database if exists sina;
#创建新的数据库,设置存储的编码
create database sina charset=utf8;
#进入数据库
use sina;
#创建保存数据的表
create table news(
nid int,
title varchar(32),
detail varchar(5000),
ctime varchar(10),
origin varchar(16)
);
#插入数据
insert into news values('1','震惊!涛哥居然对那条狗做出这样的事','详情1','2021-4-2','达内日报');
insert into news values('2','H&M、Nike等品牌永久退出中国','详情2','2021-4-3','京华时报');
insert into news values('3','白宫遭遇恐怖袭击,拜登不治身亡','详情3','2021-4-5','纽约时报');
#修改数据
update news set ctime='2019-1-1' where nid='1';
#删除数据
delete from news where nid='2';
3.列类型
在创建数据表的时候,指定的列能存储的数据类型
create table t1(
id 列类型
);
(1)数值型 —— 可以不加引号
tinyint 微整型,占1个字节,范围-128~127
smallint 小整型,占2个字节,范围-32768~32767
int 整型,占4个字节,范围-2147483648~2147483647
bigint 大整型,占8个字节
float 单精度浮点型,占4个字节,范围比int大的多,存储的数字越大精度越低,以牺牲小数点后的若干位为代价。最大3.4e+38
double 双精度浮点型,占8个字节,范围比bigint大的多
decimal(M,D) 定点小数,小数点位置不会发生变化,M代表总的有效位数,D代表小数点后的有效位数
boolean 布尔型,只有两个值,分别是true和false,代表真和假,用于存储只有两个值的数据,例如是否在线、性别、是否在售… 在使用的过程中会自动转为tinyint,true转为1,false转为0,也可以直接使用1和0
true和false是关键字,使用的时候不能加引号 |
(2)日期时间型 —— 必须加引号
date 日期型 2020-12-25
time 时间型 15:20:30
datetime 日期时间型 2020-12-25 15:20:30
(3)字符串型 —— 必须加引号
varchar(M) 变长字符串,几乎不会产生空间浪费,数据操作速度相对慢,M最大值是65535,用于存储变化长度的数据,例如用户名、邮箱、标题、文章详情…
char(M) 定长字符串,可能会产生空间浪费,数据操作速度相对快,M的最大值是255,用于存储固定长度的数据,例如手机号码、身份证号码
text(M) 大型变长字符串,M最大值是2G
varchar(5) | char(5) | |
a | a\0 | a\0\0\0\0 |
ab | ab\0 | ab\0\0\0 |
一二三 | 一二三\0 | 一二三\0\0 |
99999.99 decimal(7,2)
TB GB MB KB Byte Bit(位)
1024
1Byte=8Bit
1 2 3 4 5 6 7 8 9 10
1 10 11 100 101 …
浮点型
123456.789e-1
12345.6789
1234.56789e+1
123.456789e+2
选择合理的列类型:
create table t2(
id int,
age tinyint,
phone char(11),
sex Boolean,
price decimal(6,2), #9999.99
detail varchar(5000),
ctime date,
headpic varchar(32) #tao.jpg 01.zip 1.mp4
);
练习:编写脚本文件02_xuezi.sql,先丢弃再创建数据库xuezi,设置编码为utf8,进入数据库,创建保存商品数据的表laptop,包含编号lid,标题title,价格price,库存量stockCount,上架时间shelfTime,是否为首页推荐isIndex;插入若干条数据。
#设置客户端连接服务器端的编码
set names utf8;
#丢弃数据库,如果存在
drop database if exists xuezi;
#创建数据库,设置存储的编码
create database xuezi charset=utf8;
#进入数据库
use xuezi;
#创建数据表
create table laptop(
lid int primary key,
title varchar(64) not null,
price decimal(7,2), #99999.99
stockCount smallint,
shelfTime date,
isIndex boolean
);
#插入数据
insert into laptop values(4,'小米Air',4199,800,'2021-3-1',true);
insert into laptop values(2,'Apple pro',null,'355',null,false);
insert into laptop values('1','联想小新','4766','500','2019-5-1','1');
insert into laptop values('3','燃7000','5166','100','2020-10-1','200');
4.列约束
Mysql可以对要插入的数据进行特定的验证,只有符合格式才允许插入,例如编号不允许重复,一个人的性别只能是男或者女,一个人成绩范围0~100之间
create table t1(
lid int 列约束
);
(1)主键约束 —— primary key
声明了主键约束的列上不允许插入重复的值,一个表中只有能有一个主键约束,通常是在编号列,会加快数据的查找速度
null 表示空,在插入数据的时候,表示暂时无法确定的值,例如无法确定一个人的有效,无法确定一个商品的价格… null是关键字,不能加引号 |
主键约束的列上不允许插入null
(2)非空约束 —— not null
声明了非空约束的列上不允许插入null
练习:给标题列添加非空约束,并插入数据测试
(2)练习:编写脚本文件xz.sql,先丢弃再创建数据库xz,创建保存笔记本分类的表family,包含有分类编号fid,分类名称fname,插入以下数据
10 联想 20 戴尔 30 小米
创建保存笔记本数据的表laptop,包含编号lid,标题title,价格price,规格spec,详情detail,上架时间shelfTime,是否在售isOnsale,所属分类编号familyId(保存分类表的编号),插入若干条数据。
#设置客户端连接服务器端的编码
set names utf8;
#丢弃数据库,如果存在
drop database if exists xz;
#创建数据库,设置存储的编码
create database xz charset=utf8;
#进入数据库
use xz;
#创建保存笔记本分类的表
create table family(
fid int primary key,
fname varchar(16) default '未知'
);
#插入数据
insert into family values(50,'苹果');
insert into family values
(10,'联想'),
(20,'戴尔');
insert into family values(60,'神州');
insert into family values(30,'小米');
insert into family values(40,'华硕');
insert into family values(70,default);
insert into family(fid) values(80);
#创建保存笔记本数据的表
create table laptop(
lid int primary key auto_increment,
title varchar(128) unique,
price decimal(7,2) default 3000, #99999.99
spec varchar(256),
detail varchar(5000),
shelfTime date,
isOnsale boolean,
familyId int,
#将familyId这一列作为外键列,取值会到family表的fid中去找
foreign key(familyId) references family(fid)
);
#插入数据
insert into laptop values(1,'小米Air',4299,'流光银|溢彩金','详情1','2020-12-31',1,30);
insert into laptop values(2,'外星人',12999,'游戏版','详情2','2021-1-1',1,20);
insert into laptop values(3,'ThinkPadE470',3000,'开发版','详情3','2017-5-1',0,10);
insert into laptop values(4,null,4399,'流光银|溢彩金','详情4','2021-2-1',1,30);
insert into laptop values(5,null,4799,'流光银1|溢彩金1','详情5','2021-4-1',1,30);
insert into laptop values(6,'灵越',default,default,'详情6',default,1,20);
insert into laptop(lid,title) values(7,'AppleAir');
insert into laptop(lid,title) values(null,'AppleAir1');
insert into laptop(lid,title) values(null,'AppleAir2');
1.列约束
(1)唯一约束 —— unique
声明了唯一约束的列上不允许插入重复的值,允许插入null,甚至多个null
两个无法确定的值(null)是不一定相同的,所以允许多个 |
练习:给family表的fname添加唯一约束和非空约束,并插入数据测试。
(2)默认值约束 —— default
可以使用关键字default来设置默认值,具体应用方式有两种
insert into laptop values(6,’灵越’, default ….)
insert into laptop(lid,title) values(7,’AppleAir’);
练习:删除family表的fname中当前约束,添加默认值约束,设置默认值为’未知’,插入数据测试。
(3)检查约束 —— check
也称为自定义约束,用户自己添加的约束
create table student(
score tinyint check(score>=0 and score<=100)
);
mysql不支持检查约束,会极大的影响数据的插入速度。将来可以通过js完成
(4)外键约束
声明了外键约束的列,取值会另一个表的主键列去找,允许插入null;外键列和对应的主键列两者的列类型要保持一致。
foreign key(外键列) references 另一个表(主键列)
外键约束是为了让两个表之间建立关联 |
2.自增列
auto_increment 自动增长,如果设置了自增列,在插入数据的时候,只需要设置为null,就会获取当前的最大值然后加1插入
注意事项
自增列只能添加在整数形式的主键列上
自增列允许手动赋值
练习:编写脚本文件tedu.sql,先丢弃再创建数据库tedu,进入数据库,创建保存部门数据的表dept,包含部门编号did(主键,自增列),部门名称dname(唯一约束),插入以下数据
1 研发部 2 市场部 3 运营部 4 测试部
创建保存员工数据的表emp,包含编号eid(主键约束,自增列),员工姓名ename(非空约束),性别sex(默认值为1 ),生日birthday,工资salary,所属部门编号deptId(外键约束,对应dept的did列),插入若干条数据
#设置客户端连接服务器端的编码
set names utf8;
#丢弃数据库,如果存在
drop database if exists tedu;
#创建数据库,设置存储的编码
create database tedu charset=utf8;
#进入数据库
use tedu;
#创建部门表
create table dept(
did int primary key auto_increment,
dname varchar(16) unique
);
#插入数据
insert into dept values(null,'研发部');
insert into dept values(null,'市场部');
insert into dept values(null,'运营部');
insert into dept values(null,'测试部');
#创建员工表
create table emp(
eid int primary key auto_increment,
ename varchar(16) not null,
sex boolean default 1,
birthday date,
salary decimal(7,2), #99999.99
deptId int,
foreign key(deptId) references dept(did)
);
#插入数据
INSERT INTO emp VALUES(NULL,'Tom',default,'1990-5-5',6000,2);
INSERT INTO emp VALUES(NULL,'Jerry',0,'1991-8-20',7000,1);
INSERT INTO emp VALUES(NULL,'David',1,'1995-10-20',3000,3);
INSERT INTO emp VALUES(NULL,'Maria',0,'1992-3-20',5000,1);
INSERT INTO emp VALUES(NULL,'Leo',1,'1993-12-3',8000,2);
INSERT INTO emp VALUES(NULL,'Black',1,'1991-1-3',4000,1);
INSERT INTO emp VALUES(NULL,'Peter',1,'1990-12-3',10000,1);
INSERT INTO emp VALUES(NULL,'Franc',1,'1994-12-3',6000,3);
INSERT INTO emp VALUES(NULL,'Tacy',1,'1991-12-3',9000,1);
INSERT INTO emp VALUES(NULL,'Lucy',0,'1995-12-3',10000,2);
INSERT INTO emp VALUES(NULL,'Jone',1,'1993-12-3',8000,3);
INSERT INTO emp VALUES(NULL,'Lily',0,'1992-12-3',12000,1);
INSERT INTO emp VALUES(NULL,'Dong',0,'1989-12-3',8000,1);
INSERT INTO emp VALUES(NULL,'King',1,'1988-12-3',10000,1);
INSERT INTO emp VALUES(NULL,'Tao',1,'1993-12-3',22000,NULL);
3.简单查询
(1)查询特定的列
示例: 查询出所有员工的编号和姓名
select eid,ename from emp;
练习:查询出所有员工的姓名,性别,生日,工资
select ename,sex,birthday,salary from emp;
(2)查询所有的列
select eid,ename,sex,birthday,salary,deptId from emp;
select * from emp;
(3)给列起别名
示例:查询出所有员工的编号和姓名,使用汉字别名
select eid as 编号,ename as 姓名 from emp;
练习:查询出所有员工的姓名,性别,生日,使用汉字别名
Select ename as 姓名,sex 性别,birthday 生日 from emp;
练习:查询出所有员工的姓名,工资,所属部门编号,使用一个字母作为别名
Select ename a,salary b,deptId c from emp;
使用别名目的是为了简化列名称,便于后期使用 As关键字可以省略 |
(4)显示不同的记录
示例:查询出都有哪些性别的员工
Select distinct sex from emp;
练习:查询出员工都分布在哪些部门
Select distinct deptId from emp;
(5)查询时执行计算
示例:计算2+3*4.5+6*5.8
select 2+3*4.5+6*5.8;
练习:查询出所有员工的姓名及其年薪
Select ename,salary*12 from emp;
练习:假设每个员工的工资加2000,年终奖20000,查询出所有员工的姓名及其年薪,使用一个字母作为别名
Select ename a,(salary+2000)*12+20000 b from emp;
(6)查询的结果集排序
示例:查询出所有部门,结果按照部门编号从小到大排列
Select * from dept order by did asc; #ascendant 升序的
示例:查询出所有部门,结果按照部门编号从大到小排列
Select * from dept order by did desc; #descendant 降序的
练习:查询出所有的员工,结果按照工资的降序排列
Select * from emp order by salary desc;
练习:查询出所有的员工,结果按照年龄从大到小排列(生日从小到大)
Select * from emp order by birthday;
不加排序条件,默认是按照从小到大排列 |
练习:查询出所有的员工,结果按照姓名的升序排列
Select * from emp order by ename;
按照字符串排序,按照字符的Unicode码排序 |
练习:查询出所有的员工,结果按照工资降序排列,如果工资相同按照姓名升序排列
Select * from emp order by salary desc,ename;
练习:查询出所有的员工,要求女员工显示在前,男员工在后;如果性别相同按照年龄从大到小排列
Select * from emp order by sex,birthday;
(7)条件查询
示例:查询出7号员工的所有列
Select * from emp where eid=7;
示例:查询出姓名为King的员工所有列
Select * from emp where ename='king';
练习:查询出2号部门下的员工有哪些
select * from emp where deptId=2;
练习:查询出不在2号部门的员工有哪些
select * from emp where deptId!=2;
> < >= <= = !=(不等于) |
练习:查询出工资在8000以上的员工有哪些
select * from emp where salary>8000;
练习:查询出没有明确部门的员工有哪些
select * from emp where deptId is null;
练习:查询出有明确部门的员工有哪些
select * from emp where deptId is not null;
练习:查询出7000以下的男员工有哪些
select * from emp where salary<7000 and sex=1;
练习:查询出工资在5000~8000之间的员工有哪些
select * from emp where salary>=5000 and salary<=8000;
select * from emp where salary between 5000 and 8000;
练习:查询出工资在5000以下或者8000以上的员工有哪些
select * from emp where salary<5000 or salary>8000;
select * from emp where salary not between 5000 and 8000;
练习:查询出1993年出生的员工有哪些
select * from emp where birthday>='1993-1-1' and birthday<='1993-12-31';
select * from emp where birthday between '1993-1-1' and '1993-12-31';
练习:查询出2号部门或者3号部门的员工有哪些
select * from emp where deptId=2 or deptId=3;
select * from emp where deptId in(2,3);
练习:查询出不在2号部门并且不在3号部门的员工有哪些
select * from emp where deptId not in(2,3);
select * from emp where deptId!=2 and deptId!=3;
and / or between .. and .. / not between .. and .. in( ) / not in( ) is null / is not null |
(8)模糊条件查询
示例:查询出姓名中含有字母e的员工有哪些
select * from emp where ename like '%e%';
练习:查询出姓名中以e结尾的员工有哪些
select * from emp where ename like '%e';
练习:查询出姓名中倒数第2个字符是e的员工有哪些
select * from emp where ename like '%e_';
% 匹配任意个字符 >=0 _ 匹配任意1个字符 =1 以上两个匹配的符合必须结合like使用 |
练习:删除代码,保留注释,重新编码SQL命令
查询出工资在8000以上的男员工的姓名,性别,生日,工资;结果按照工资的降序排列。
查看学子商城数据库的设计
select ename,sex,birthday,salary from emp where salary>8000 and sex=1 order by salary desc;
2021-04-07 9:34:30
2021年04月07日
2021/04/07
04/07/2021
距离2021年高考还有x天x
精确度 毫秒
存储的是距离计算机元年(1970-1-1 0:0:0 0)的毫秒数
2021-1-1 0:0:0 51*365*24*60*60*1000 = 1,608,336,000,000
时间戳
1.简单查询——分页查询
查询的结果集中有太多的数据,一次显示不完可以做成分页显示
需要有两个已知的条件:当前的页码、每页显示的数据量
开始查询的值 = (当前的页码-1)*每页的数据量 |
select * from emp limit 开始查询的值,每页的数据量;
练习:假设每页显示5条数据,分别查询出前3页的数据
第1页 select * from emp limit 0,5;
第2页 select * from emp limit 5,5;
第3页 select * from emp limit 10,5;
limit后的两个值必须是数值型,不能加引号 |
2.复杂查询
(1)聚合查询/分组查询
示例:查询出所有员工的数量
select count(*) from emp;
练习:使用编号列查询所有男员工的数量
select count(eid) from emp where sex=1; #推荐使用主键列
练习:使用所属部门编号列查询出所有男员工的数量
select count(deptId) from emp where sex=1;
函数(function):是一个独立的功能体,需要提供若干个数据,返回结果 聚合函数 count() / sum() / avg() / max() / min() 数量 总和 平均 最大 最小 |
练习:查询出所有女员工的工资总和
select sum(salary) from emp where sex=0;
练习:查询出1号部门的平均工资
select avg(salary) from emp where deptId=1;
练习:查询出年龄最大的员工的生日是多少
select min(birthday) from emp;
练习:查询出工资最高的员工工资是多少
select max(salary) from emp;
通常分组查询只是查询分组条件和聚合函数 |
示例:查询出男女员工的数量和平均工资
select count(eid),avg(salary),sex from emp group by sex;
练习:查询出各个部门的最高工资、最低工资、平均工资
select max(salary),min(salary),avg(salary),deptId from emp group by deptId;
示例:获取日期1995-5-20中的年份
select year('1995-5-20');
练习:查询出1993年出生的员工有哪些
select * from emp where year(birthday)=1993;
练习:查询出所有员工出生的年份
select year(birthday) from emp;
year() 获取日期中的年份 |
(2)子查询
是多个SQL命令的组合,把一个命令的结果作为另一个的条件。
示例:查询出工资最高的员工的所有列
步骤1:查询出工资的最高值 —— 22000
select max(salary) from emp;
步骤2:通过工资最高值查询出员工
select * from emp where salary=22000;
综合:
select * from emp where salary=(select max(salary) from emp);
练习:查询出高于平均工资的男员工有哪些
步骤1:查询出平均工资的值 —— 8533.33
select avg(salary) from emp;
步骤2:查询出高于平均工资的男员工
select * from emp where salary>8533.33 and sex=1;
综合:
select * from emp where salary>(select avg(salary) from emp) and sex=1;
练习:查询出研发部的员工有哪些
步骤1:查询出研发部的部门编号 —— 1
select did from dept where dname='研发部';
步骤2:通过部门编号查询出员工
select * from emp where deptId=1;
综合:
select * from emp where deptId=(select did from dept where dname='研发部');
练习:查询出和tom同一年出生的员工有哪些
步骤1:查询出tom出生的年份 1990
select year(birthday) from emp where ename='tom';
步骤2:查询出和tom同一年出生的员工
select * from emp where year(birthday)=1990 and ename!='tom';
综合:
select * from emp where year(birthday)=(select year(birthday) from emp where ename='tom') and ename!='tom';
(3)多表查询
要查询的列分布在多个表中,前提在创建表的时候已经建立了关联
示例:查询出所有员工的姓名及其部门名称
select emp.ename,dept.dname from emp,dept where emp.deptId=dept.did;
内连接
select ename,dname from emp inner join dept on deptId=did;
和之前的查询结果一样
左外连接
select ename,dname from emp left outer join dept on deptId=did;
显示左侧表中所有的记录,先写哪个表哪个就是左,outer可以省略
右外连接
select ename,dname from emp right outer join dept on deptId=did;
显示右侧表中所有的记录,后写哪个表哪个就是右,outer可以省略
全连接
full join .. on ..
联合
union all 相同的记录不合并
union 相同的记录合并
解决方法:将左外连接和右外连接的结果联合起来,合并相同的记录。
(select ename,dname from emp left outer join dept on deptId=did)
union
(select ename,dname from emp right outer join dept on deptId=did);