MySQL笔记_MySQL的再探
连接查询
-
多张表联合查询,连接方式: 1. 内连接:等值连接、非等值连接、自连接。2. 外连接:左(外)连接、右(外)连接、全连接。
-
笛卡尔积:若两张表进行连接查询 无过滤条件 则 条数 为 两表条数乘积
-
找出 员工的部门名称
mysql> select e.ename,d.dname from emp e ,dept d;
-- 上条 更好 且 需要起 别名 易于 分别 且效率更高 可读性好
mysql> select ename,dname from emp,dept;
+--------+------------+
| ename | dname |
+--------+------------+
| SMITH | ACCOUNTING |
| SMITH | RESEARCH |
| SMITH | SALES |
| SMITH | OPERATIONS |
| TURNER | SALES |
| TURNER | OPERATIONS |
| ADAMS | ACCOUNTING |
| ADAMS | RESEARCH |
| ADAMS | SALES |
| ADAMS | OPERATIONS |
...
| MILLER | SALES |
| MILLER | OPERATIONS |
+--------+------------+
56 rows in set (0.01 sec) -- 56 = 14 * 4
ps:避免 笛卡尔积
现象,同时不会减少记录的匹配次数,因而可以用来where
,having
加条件。
mysql> select e.ename,d.dname
-> from emp e , dept d
-> where
-> e.deptno = d.deptno;//92语法 不用
+--------+------------+
| ename | dname |
+--------+------------+
| CLARK | ACCOUNTING |
| KING | ACCOUNTING |
| MILLER | ACCOUNTING |
| SMITH | RESEARCH |
| JONES | RESEARCH |
| SCOTT | RESEARCH |
| ADAMS | RESEARCH |
| FORD | RESEARCH |
| ALLEN | SALES |
| WARD | SALES |
| MARTIN | SALES |
| BLAKE | SALES |
| TURNER | SALES |
| JAMES | SALES |
+--------+------------+
14 rows in set (0.01 sec)
内连接
-
内连接 --> 等值连接
条件是 等量关系 则可以分离条件
select e.ename, d.dname
from emp e
(inner)join dept d --inner 可以省略 带上更清晰
on e.deptno = d.deptno;
+--------+------------+
| ename | dname |
+--------+------------+
| CLARK | ACCOUNTING |
| KING | ACCOUNTING |
| MILLER | ACCOUNTING |
| SMITH | RESEARCH |
| JONES | RESEARCH |
| SCOTT | RESEARCH |
| ADAMS | RESEARCH |
| FORD | RESEARCH |
| ALLEN | SALES |
| WARD | SALES |
| MARTIN | SALES |
| BLAKE | SALES |
| TURNER | SALES |
| JAMES | SALES |
+--------+------------+
14 rows in set (0.00 sec)
语法
select
e.ename,d.dname
from
emp e
join
dept d
on
连接条件
where
过滤条件
- 内连接 --> 非等值 连接
select e.ename,e.sal,s.grade
from emp e
join salgrade s
on e.sal between s.losal and s.hisal;
+--------+---------+-------+
| ename | sal | grade |
+--------+---------+-------+
| SMITH | 800.00 | 1 |
| ALLEN | 1600.00 | 3 |
| WARD | 1250.00 | 2 |
| JONES | 2975.00 | 4 |
| MARTIN | 1250.00 | 2 |
| BLAKE | 2850.00 | 4 |
| CLARK | 2450.00 | 4 |
| SCOTT | 3000.00 | 4 |
| KING | 5000.00 | 5 |
| TURNER | 1500.00 | 3 |
| ADAMS | 1100.00 | 1 |
| JAMES | 950.00 | 1 |
| FORD | 3000.00 | 4 |
| MILLER | 1300.00 | 2 |
+--------+---------+-------+
14 rows in set (0.00 sec)
- 内连接–>自连接
eg
. 找到每个员工 的上级领导(13条记录 忽略NULL)
select a.ename,b.ename
from emp a
join emp b
on a.mgr = b.empno;
+--------+-------+
| ename | ename |
+--------+-------+
| SMITH | FORD |
| ALLEN | BLAKE |
| WARD | BLAKE |
| JONES | KING |
| MARTIN | BLAKE |
| BLAKE | KING |
| CLARK | KING |
| SCOTT | JONES |
| TURNER | BLAKE |
| ADAMS | SCOTT |
| JAMES | BLAKE |
| FORD | JONES |
| MILLER | CLARK |
+--------+-------+
13 rows in set (0.00 sec)
-- 将两张表看作一张表进行自连接 关键要找到合适的关系
-- 上表King无 上级
外连接
区别:与内链接 -能够匹配记录可以查询出来 就是内链接 且 无主辅之分
外连接:分主次 若副表 无主表数据 模拟NULL与之匹配
左连接 右连接 指的是主表的位置 可以相互替换 不忽略匹配不上的情况。
mysql> select a.ename,b.ename
-> from emp a
-> left(outer) join emp b
-> on a.mgr = b.empno;
-- or
mysql> select a.ename,b.ename
-> from emp b
-> right(outer) join emp a
-> on a.mgr = b.empno;
+--------+-------+
| ename | ename |
+--------+-------+
| SMITH | FORD |
| ALLEN | BLAKE |
| WARD | BLAKE |
| JONES | KING |
| MARTIN | BLAKE |
| BLAKE | KING |
| CLARK | KING |
| SCOTT | JONES |
| KING | NULL |
| TURNER | BLAKE |
| ADAMS | SCOTT |
| JAMES | BLAKE |
| FORD | JONES |
| MILLER | CLARK |
+--------+-------+
14 rows in set (0.00 sec)
-- 主表数据 无条件 全部查询出来
左右连接
eg
: 找出哪个部门没有员工
mysql> select e.*[可以省略],d.*
-> from emp e
-> right join dept d
-> on e.deptno = d.deptno
-> where e.empno is NULL;
+-------+-------+------+------+----------+------+------+--
|EMPNO|ENAME|JOB|MGR| HIREDATE|SAL|COMM|DEPTNO|DEPTNO|
+-------+-------+------+------+----------+------+------+--
|NULL|NULL|NULL|NULL|NULL|NULL|NULL|NULL|40|OPERATIONS|
+-------+-------+------+------+----------+------+------+--
1 row in set (0.00 sec)
mysql> select d.*
-> from emp e
-> right join dept d
-> on e.deptno = d.deptno
-> where e.empno is NULL;
+--------+------------+--------+
| DEPTNO | DNAME | LOC |
+--------+------------+--------+
| 40 | OPERATIONS | BOSTON |
+--------+------------+--------+
1 row in set (0.00 sec)
-
三张表 的 连接
eg
:找出 每一个员工的 部门名称 和 薪资等级-- 找出 每一个员工的 部门名称 和 薪资等级 ... -- A -- join B -- join C -- A 先 和B连接 结果在和 C连接 select e.ename,d.dname,s.grade,e1.ename as authorname from emp e join dept d on e.deptno = d.deptno join salgrade s on e.sal between s.losal and s.hisal left join emp e1 on e.mgr = e1.empno; +--------+------------+-------+ | ename | dname | grade | +--------+------------+-------+ | SMITH | RESEARCH | 1 | | ALLEN | SALES | 3 | | WARD | SALES | 2 | | JONES | RESEARCH | 4 | | MARTIN | SALES | 2 | | BLAKE | SALES | 4 | | CLARK | ACCOUNTING | 4 | | SCOTT | RESEARCH | 4 | | KING | ACCOUNTING | 5 | | TURNER | SALES | 3 | | ADAMS | RESEARCH | 1 | | JAMES | SALES | 1 | | FORD | RESEARCH | 4 | | MILLER | ACCOUNTING | 2 | +--------+------------+-------+ -- ----------------------------------------加领导名 +--------+------------+-------+------------+ | ename | dname | grade | authorname | +--------+------------+-------+------------+ | SMITH | RESEARCH | 1 | FORD | | ALLEN | SALES | 3 | BLAKE | | WARD | SALES | 2 | BLAKE | | JONES | RESEARCH | 4 | KING | | MARTIN | SALES | 2 | BLAKE | | BLAKE | SALES | 4 | KING | | CLARK | ACCOUNTING | 4 | KING | | SCOTT | RESEARCH | 4 | JONES | | KING | ACCOUNTING | 5 | NULL | | TURNER | SALES | 3 | BLAKE | | ADAMS | RESEARCH | 1 | SCOTT | | JAMES | SALES | 1 | BLAKE | | FORD | RESEARCH | 4 | JONES | | MILLER | ACCOUNTING | 2 | CLARK | +--------+------------+-------+------------+ 14 rows in set (0.00 sec)
-
from 后 嵌套子查询
eg
:找出每个部门 的 平均薪水的 薪资等级1. 找出每个部门的 平均薪水 (按照部门标号 分组 求 平均薪资) select deptno,avg(sal) from emp group by deptno; +--------+-------------+ | deptno | avg(sal) | +--------+-------------+ | 10 | 2916.666667 | | 20 | 2175.000000 | | 30 | 1566.666667 | +--------+-------------+ mysql> select t.*,s.grade -> from (select deptno,avg(sal) as avgsal from emp group by deptno) t -> join salgrade s -> on t.avgsal between s.losal and hisal; +--------+-------------+-------+ | deptno | avgsal | grade | +--------+-------------+-------+ | 30 | 1566.666667 | 3 | | 10 | 2916.666667 | 4 | | 20 | 2175.000000 | 4 | +--------+-------------+-------+
-
找出每个部门 平均的薪水等级
mysql> select e.deptno,avg(s.grade) > from emp e > join salgrade s > on e.sal between s.losal and s.hisal > group by e.deptno;
-
在 select 后 嵌套 子查询
select e.ename,(select d.dname from dept d where e.deptno = d.deptno) as dname from emp e; +--------+------------+ | ename | dname | +--------+------------+ | SMITH | RESEARCH | | ALLEN | SALES | | WARD | SALES | | JONES | RESEARCH | | MARTIN | SALES | | BLAKE | SALES | | CLARK | ACCOUNTING | | SCOTT | RESEARCH | | KING | ACCOUNTING | | TURNER | SALES | | ADAMS | RESEARCH | | JAMES | SALES | | FORD | RESEARCH | | MILLER | ACCOUNTING | +--------+------------+ 14 rows in set (0.00 sec)
union 联合查询
-
union 可以将 查询结果集 相加
-- 找出 工作岗位是 salesman 和 manager 的员工 -- 第一种 or mysql> select ename,job -> from emp -> where job = 'MANAGER' or job = 'SALESMAN'; -- 第二种 in mysql> select ename,job -> from emp -> where job in('MANAGER','SALESMAN'); -- 第三种 union mysql> select ename,job from emp where job = 'MANAGER' -> union -> select ename,job from emp where job = 'SALESMAN'; +--------+----------+ | ename | job | +--------+----------+ | JONES | MANAGER | | BLAKE | MANAGER | | CLARK | MANAGER | | ALLEN | SALESMAN | | WARD | SALESMAN | | MARTIN | SALESMAN | | TURNER | SALESMAN | +--------+----------+ 7 rows in set (0.00 sec)
-
limit 限制查询
往往用于分页或排序查询来限制结果的显示方式
其中:
MySQL特有limit 查询 ,Oracle 有类似机制
rownum
limit 只取结果集中的 部分数据
limit 命令格式 :limit startIndex,length
ps
:起始值 startIndex(从零开始,可以不写) 长度length
- limit 最后执行
- 找出收入倒序排列的前5位
mysql> select ename,sal from emp order by sal desc limit 0,5;
+-------+---------+
| ename | sal |
+-------+---------+
| KING | 5000.00 |
| SCOTT | 3000.00 |
| FORD | 3000.00 |
| JONES | 2975.00 |
| BLAKE | 2850.00 |
+-------+---------+
5 rows in set (0.01 sec)
eg
:找出4-9名工资排名
mysql> select ename,sal
-> from emp
-> order by sal desc
-> limit 3,6;
+--------+---------+
| ename | sal |
+--------+---------+
| JONES | 2975.00 |
| BLAKE | 2850.00 |
| CLARK | 2450.00 |
| ALLEN | 1600.00 |
| TURNER | 1500.00 |
| MILLER | 1300.00 |
+--------+---------+
6 rows in set (0.00 sec)
-- 通用 翻页 每页显示 pageSize条记录
-- 第 pageNo 页 (PageNo - 1) *pageNo = pageSize
MySQL 常见 数据类型
与 Java 数据类型 对应理解记忆, 分别有 int、 bigint 、long;float 、double; char、varchar(
类似Java StringBuilder构造的字符串
)、date(from java.sql.Date);BLOB
二进制大对象(存储图片、视频 等流媒体信息) Binary Large Object;CLOB
字符大对象 存储较大文本 可以存储 4G 字符串 Character Large Object。eg. id(int) name(varchar) playtime(date/char) seal(BLOB) - IO流 history(CLOB)
char 与 varchar 的区别
char 效率高 不用判断 长度, char(6) 少补 多错 varchar(6) 智能分配
char 字段数据长度 是定长的 eg. 性别、生日
varchareg.
简介 姓名
DQL 语句
- 建表语句
-- 语法
> create table 表名(
字段名:数据类型,
字段名:数据类型,
字段名:数据类型,
字段名:数据类型,
...
);
-- 一般 数据库 创建表格时 建议 以 t_/tbl_
-- t_movie 命名
eg.
建立一个 拥有 “学号 姓名 性别 班级编号 生日” 的学生表格
-- 学号 姓名 性别 班级编号 生日
create table t_stu(
no bigint,
name varchar(255),
sex char(1),
classno varchar(255),
birth char(10)
);
Query OK, 0 rows affected (0.01 sec)
mysql> desc t_stu;
+---------+--------------+------+-----+-------+
| Field | Type| NULL | Key | Default | Extra |
+---------+--------------+------+-----+-------+
| no | bigint(20) | YES | | NULL | |
| name | varchar(255) | YES | | NULL| |
| sex | char(1) | YES | | NULL | |
| classno | varchar(255) | YES | | NULL| |
| birth | char(10) | YES | | NULL | |
+---------+--------------+------+-----+-------+
5 rows in set (0.00 sec)
- 插入数据 insert
-- 语法:
insert into 表名(
字段名,
字段名,
字段名,
)
values
(
val1,
val2,
val3,
) ;
-- ps :值和字段的数量要相同 且 数据类型要对应
-
插入方式,所有字段都赋值,或只给单个字段赋值。
insert into t_stu( no,name,sex,classno,birth )values( 1,'Zhangsan','f','gaosan1ban','1980-10-23' ); -- 插入 一个字段 其他值 自动 赋值NULL 且 顺序可变 insert into t_student(name)values('Zhangsan'); Query OK, 1 row affected (0.01 sec)
- 删表
drop table if exists t_stu;
create table t_student(
no bigint,
name varchar(255),
sex char(1) default 1,//指定默认值
classno varchar(255),
birth char(10)
)
- 更新表
当 insert 执行 一次 表中新产生一行 忽略NULL 且 不能再用insert 插入 只能用 update 更新
若按顺序 插入 前方 字段 默认 按 插入 顺序 和 数量 执行
ps.如果没有条件 则 全表更新
-- 语法格式:
update 表名 set
字段1=值1,
字段2=值2,
where conditon ;
-- 更新示例
-- 插入单行数据
insert into t_student values(
10,
'Zhangsan',
'gaoshan',
);
-- 插入多行数据
insert into t_student values(
20,
'Lisi',
'gaoshan',
),(
30,
'Wangwu',
'gaoshan',
);
update dept1 set loc = 'SHANGHAI',dname = 'RENSHIBU' where deptno = 10;
mysql> update dept1 set loc = 'x',dname = 'y';
Query OK, 3 rows affected (0.00 sec)
Rows matched: 3 Changed: 3 Warnings: 0
mysql> select * from dept1;
+--------+-------+------+
| DEPTNO | DNAME | LOC |
+--------+-------+------+
| 10 | y | x |
| 20 | y | x |
| 30 | y | x |
+--------+-------+------+
4 rows in set (0.00 sec)
-
表的复制
create table 表名 as dql 语句;
create table emp1 as select ename,sal from emp;
-- 将 查询结果 赋作 新表
create table emp1 as select* from emp;
-- 将 查询结果 插入 一张表
- 删除数据 不删除表格
- 语法格式
-- 删除 可以 回滚 rollback
mysql>delete from table0 where conditions
/*if no condition delete all data*/
-- 截断 不可回滚
mysql> truncate table emp1;
Query OK, 0 rows affected (0.01 sec)
- DDL 对表结构 修改 可以借助工具 且 很少发生
CRUD ---> R --> create retrieve update delete
约束(Constraint)
非空约束(not NULL) 确保数据 合法、有效、完整性
唯一性约束(unique) 用户名 方便管理 不能重复
主键约束(primary key) : 不能为NULL 且不能 重复(PK)
外键约束(foriegn key)(FK)
检查约束(check) : Oracle 支持 check 约束 mysql 不支持该约束
- 非空约束 not NULL
drop table if exists t_user;
create table t_user(
id int,
username varchar(255) not NULL,
password varchar(255) not NULL,
);
insert into t_user(id,password) values(1,'123');
1364 ---> 缺 默认值
- 唯一性约束 unique
唯一 约 束 修饰 的 字段具有唯一性 不能重复 但 可以为NULL
drop table if exists t_user;
create table t_user(
id int,
username varchar(255) unique -- 列级约束
);
insert into t_user values(1,'Zhangsan');
insert into t_user values(2,'Zhangsan');
同时加 unique
drop table if exists t_user;
create table t_user(
id int,
usercode varchar(255),
username varchar(255),
unique(usercode,username) -- 加一个约束 表级约束
);
insert into t_user values(1,'111','Zhangsan');
insert into t_user values(2,'111','Lisi');
insert into t_user values(3,'222','Zhangsan');
select * from t_user;
mysql> select * from t_user;
+------+----------+----------+
| id | usercode | username |
+------+----------+----------+
| 1 | 111 | Zhangsan |
| 2 | 111 | Lisi |
| 3 | 222 | Zhangsan |
+------+----------+----------+
3 rows in set (0.00 sec)
------------------分别加约束----------------------
drop table if exists t_user;
create table t_user(
id int,
usercode varchar(255) unique,
username varchar(255) unique
);
insert into t_user values(1,'111','Zhangsan');
insert into t_user values(2,'111','Lisi');
- 主键约束
drop table if exists t_user;
create table t_user(
id int primary key,
username varchar(255)
-- primary key(id)
);
写在最后
MySQL的探索还在路上,加油!!