文章目录
1、约束条件1.1、主键(primary key)1.2、not null1.3、unique1.4、check1.5、外键
2、关系数据库中表与表的三种关系2.1、一对一2.2、多对一或者一对多2.3、多对多
3、单表查询3.1、准备数据表及数据3.2、查询语法3.3、简单查询3.4、where约束3.5、having过滤3.6、group by分组查询3.7、order by查询排序3.8、使用聚合函数查询3.9、where的补充(使用正则表达式查询)3.10、limit限制查询的记录数3.11、关键字的执行优先级
1、约束条件
在项目开发,我们要对表的数据进行管理
(比如说从业务逻辑的角度,保证数据的正确性
), 比如有一个字段叫 email
, 要求是唯一的。为了达到这个效果,mysql提供一种机制来保证这些数据的正确性,就是表的约束
表的约束有
5种
: 主键
(primary key
)、
not null
(非空
)、unique
(唯一约束
), 外键约束
, check约束
[在mysql中,支持check的语法,但是本身并不生效
]
1.1、主键(primary key)
用于唯一的标示表行的数据
,当定义主键约束后,该列不能重复
, 一般来说,mysql中的每张表都会有一个primary key
, 用于唯一标识一条记录
. 而且这个primary 所在的列是整数类型
特点
:
1、主键的约束效果是
not null
+unique
2、innodb表有且只有一个主键,但是该主键可以是联合主键
mysql
> create table t8
(id int primary key
, name varchar
(10));
Query OK
, 0 rows affected
(1.43 sec
)
mysql
> desc t8
;
+-------+-------------+------+-----+---------+-------+
| Field
| Type
| Null
| Key
| Default
| Extra
|
+-------+-------------+------+-----+---------+-------+
| id | int | NO
| PRI
| NULL
| |
| name
| varchar
(10) | YES
| | NULL
| |
+-------+-------------+------+-----+---------+-------+
2 rows
in set (0.20 sec
)
1.2、not null
如果在列上定义了
not null
,那么当插入数据时,必须为列提供数据
mysql
> create table t9
(id int primary key
,name varchar
(10) not null
);
Query OK
, 0 rows affected
(1.83 sec
)
mysql
> desc t9
;
+-------+-------------+------+-----+---------+-------+
| Field
| Type
| Null
| Key
| Default
| Extra
|
+-------+-------------+------+-----+---------+-------+
| id | int | NO
| PRI
| NULL
| |
| name
| varchar
(10) | NO
| | NULL
| |
+-------+-------------+------+-----+---------+-------+
2 rows
in set (0.00 sec
)
mysql
> insert into t9 values
(1,null
);
ERROR
1048 (23000): Column
'name' cannot be null
mysql
> create table t9
(x
int not null default
111);
Query OK
, 0 rows affected
(1.18 sec
)
mysql
> insert into t9 values
();
Query OK
, 1 row affected
(0.17 sec
)
mysql
> desc t9
;
+-------+------+------+-----+---------+-------+
| Field
| Type
| Null
| Key
| Default
| Extra
|
+-------+------+------+-----+---------+-------+
| x
| int | NO
| | 111 | |
+-------+------+------+-----+---------+-------+
1 row
in set (0.04 sec
)
1.3、unique
当定义了唯一约束后,该列值是不能重复的
mysql
> create table t10
(id int primary key
,email varchar
(20) unique
);
Query OK
, 0 rows affected
(1.34 sec
)
mysql
> insert into t10 values
(1,'123@qq.com');
Query OK
, 1 row affected
(0.17 sec
)
mysql
> insert into t10 values
(2,'123@qq.com');
ERROR
1062 (23000): Duplicate entry
'123@qq.com' for key
't10.email'
mysql
> create table server
(
-> id int,
-> name varchar
(10),
-> ip varchar
(15),
-> port
int,
-> unique
(ip
,port
),
-> unique
(name
)
-> );
Query OK
, 0 rows affected
(1.27 sec
)
mysql
> insert into server values
(1,"web1","10.10.0.11",8080);
Query OK
, 1 row affected
(0.16 sec
)
mysql
> insert into server values
(2,"web2","10.10.0.11",8081);
Query OK
, 1 row affected
(0.11 sec
)
mysql
> insert into server values
(3,"web3","10.10.0.11",8081);
ERROR
1062 (23000): Duplicate entry
'10.10.0.11-8081' for key
'server.ip'
补充:
not null 和 unique的化学反应
=> 会被识别成表的主键
mysql
> create table test1
(id int,name varchar
(10) not null unique
);
Query OK
, 0 rows affected
(1.48 sec
)
mysql
> create table test2
(id int,name varchar
(10) unique
);
Query OK
, 0 rows affected
(1.78 sec
)
mysql
> desc test1
;
+-------+-------------+------+-----+---------+-------+
| Field
| Type
| Null
| Key
| Default
| Extra
|
+-------+-------------+------+-----+---------+-------+
| id | int | YES
| | NULL
| |
| name
| varchar
(10) | NO
| PRI
| NULL
| |
+-------+-------------+------+-----+---------+-------+
2 rows
in set (0.00 sec
)
mysql
> desc test2
;
+-------+-------------+------+-----+---------+-------+
| Field
| Type
| Null
| Key
| Default
| Extra
|
+-------+-------------+------+-----+---------+-------+
| id | int | YES
| | NULL
| |
| name
| varchar
(10) | YES
| UNI
| NULL
| |
+-------+-------------+------+-----+---------+-------+
2 rows
in set (0.00 sec
)
1.4、check
check只是做语法的校验,而没有真正的生效
mysql
> create table t11
(id int primary key
,sal
float check
(sal
>100 and sal
<900));
Query OK
, 0 rows affected
(0.71 sec
)
1.5、外键
用于定义主表和从表之间的关系
: 外键约束要定义在从表上,主表则必须具有主键约束或是unique约束
,当定义外键约束后,要求外键列数据必须在主表的主键列存在或是为null
foreign key
(字段名
) references 主表
(列
)
mysql
> create table
class(
id int primary key
,
name varchar
(12) unique
);
Query OK
, 0 rows affected
(0.63 sec
)
mysql
> insert into
class values(1,'班级1');
Query OK
, 1 row affected
(0.18 sec
)
mysql
> insert into
class values(2,'班级2');
Query OK
, 1 row affected
(0.13 sec
)
mysql
> create table student
(
id int primary key
,
name varchar
(12),
class_id
int,
foreign key student
(class_id
) references
class(id) on update cascade on delete cascade
);
Query OK
, 0 rows affected
(1.10 sec
)
mysql
> insert into student values
(1,'zhangsan',1);
Query OK
, 1 row affected
(0.19 sec
)
mysql
> insert into student values
(2,'lisi',5);
ERROR
1452 (23000): Cannot add
or update a child row
: a foreign key constraint fails
(`db01`
.`student`
, CONSTRAINT `student_ibfk_1` FOREIGN KEY
(`class_id`
) REFERENCES `
class`
(`
id`
) ON DELETE CASCADE ON UPDATE CASCADE
)
2、关系数据库中表与表的三种关系
表
1 foreign key 表
2
则表
1的多条记录对应表
2的一条记录,即多对一
利用foreign key的原理我们可以制作两张表的多对多,一对一关系
多对多
:
表
1的多条记录可以对应表
2的一条记录
表
2的多条记录也可以对应表
1的一条记录
一对一
:
表
1的一条记录唯一对应表
2的一条记录,反之亦然
分析时,我们先从按照上面的基本原理去套,然后再翻译成真实的意义,就很好理解了
2.1、一对一
一对一关系
: 表
1的一条记录唯一对应表
2的一条记录
,例如用户基本信息和用户详细信息
mysql
> create table user
(
id int primary key
,
name varchar
(20)
);
Query OK
, 0 rows affected
(0.69 sec
)
mysql
> insert into user values
(1,'zhangsan');
Query OK
, 1 row affected
(0.19 sec
)
mysql
> insert into user values
(2,'lisi');
Query OK
, 1 row affected
(0.21 sec
)
mysql
> create table detail
(
id int primary key
,
phone char
(11),
addr varchar
(50),
u_id
int,
foreign key detail
(u_id
) references user
(id) on update cascade on delete cascade
);
Query OK
, 0 rows affected
(0.92 sec
)
mysql
> insert into detail values
(1,110,'zhangsan的地址',1);
Query OK
, 1 row affected
(0.09 sec
)
mysql
> insert into detail values
(2,120,'lisi的地址',2);
Query OK
, 1 row affected
(0.24 sec
)
2.2、多对一或者一对多
多对一关系
: 左边表的多条记录对应右边表的唯一一条记录
说明
:
1、先确立关系
2、找到多的一方,把关联字段写在多的一方
需要注意的
:
1.先建被关联的表,保证被关联表的字段必须唯一
2.在创建关联表,关联字段一定保证是要有重复的
案例参考【外键】章节
2.3、多对多
多对一关系
: 多条记录对应多条记录,需要建立中间表,例如书与作者
书和作者
(创建book和author两张表
)
要把book_id和author_id设置成联合唯一
联合唯一
: unique
(book_id,author_id
)
多对多
: 一个作者可以写多本书,一本书也可以有多个作者,双向的一对多,即多对多
mysql
> create table book
(
id int primary key auto_increment
,
name varchar
(10),
price
float(3,2)
);
Query OK
, 0 rows affected
, 1 warning
(1.02 sec
)
mysql
> create table author
(
id int primary key auto_increment
,
name char
(5)
);
Query OK
, 0 rows affected
(0.97 sec
)
mysql
> create table author2book
(
id int primary key auto_increment
,
book_id
int not null
,
author_id
int not null
,
unique
(book_id
,author_id
),
foreign key
(book_id
) references book
(id) on delete cascade on update cascade
,
foreign key
(author_id
) references author
(id) on delete cascade on update cascade
);
Query OK
, 0 rows affected
(1.52 sec
)
mysql
> insert into book
(name
,price
) values
('三国演义',9.9), ('西游记',9.5),('红楼梦',5),('水浒传',7.3);
Query OK
, 4 rows affected
(0.30 sec
)
mysql
> insert into author
(name
) values
('allen'),('lily'),('tom'),('tank'),('lucy');
Query OK
, 5 rows affected
(0.20 sec
)
mysql
> insert into author2book
(book_id
,author_id
) values
(1,1),(1,4),(2,1),(2,5),(3,2),(3,3),(3,4),(4,5);
Query OK
, 8 rows affected
(0.88 sec
)
mysql
> select
* from author2book
;
+----+---------+-----------+
| id | book_id
| author_id
|
+----+---------+-----------+
| 1 | 1 | 1 |
| 2 | 1 | 4 |
| 3 | 2 | 1 |
| 4 | 2 | 5 |
| 5 | 3 | 2 |
| 6 | 3 | 3 |
| 7 | 3 | 4 |
| 8 | 4 | 5 |
+----+---------+-----------+
8 rows
in set (0.00 sec
)
3、单表查询
3.1、准备数据表及数据
create table employee
(
id int not null unique auto_increment
,
name varchar
(20) not null
,
sex enum
('male','female') not null default
'male',
age
int(3) unsigned
not null default
28,
hire_date date
not null
,
post varchar
(50),
post_comment varchar
(100),
salary double
(15,2),
office
int,
depart_id
int
);
mysql
> desc employee
;
+--------------+-----------------------+------+-----+---------+----------------+
| Field
| Type
| Null
| Key
| Default
| Extra
|
+--------------+-----------------------+------+-----+---------+----------------+
| id | int | NO
| PRI
| NULL
| auto_increment
|
| name
| varchar
(20) | NO
| | NULL
| |
| sex
| enum
('male','female') | NO
| | male
| |
| age
| int unsigned
| NO
| | 28 | |
| hire_date
| date
| NO
| | NULL
| |
| post
| varchar
(50) | YES
| | NULL
| |
| post_comment
| varchar
(100) | YES
| | NULL
| |
| salary
| double
(15,2) | YES
| | NULL
| |
| office
| int | YES
| | NULL
| |
| depart_id
| int | YES
| | NULL
| |
+--------------+-----------------------+------+-----+---------+----------------+
10 rows
in set (0.07 sec
)
mysql
> insert into employee
(name
,sex
,age
,hire_date
,post
,salary
,office
,depart_id
) values
('allen','male',18,'20170301','teacher',7300.33,401,1),
('luly','male',78,'20150302','teacher',1000000.31,401,1),
('tom','male',81,'20130305','teacher',8300,401,1),
('jack','male',73,'20140701','teacher',3500,401,1),
('lilei','male',28,'20121101','teacher',2100,401,1),
('hanmeimei','female',18,'20110211','teacher',9000,401,1),
('zhangsan','male',18,'19000301','teacher',30000,401,1),
('lisi','male',48,'20101111','teacher',10000,401,1),
('wangwu','female',48,'20150311','sale',3000.13,402,2),
('张三','female',38,'20101101','sale',2000.35,402,2),
('李四','female',18,'20110312','sale',1000.37,402,2),
('王五','female',18,'20160513','sale',3000.29,402,2),
('赵六','female',28,'20170127','sale',4000.33,402,2),
('用户1','male',28,'20160311','operation',10000.13,403,3),
('用户2','male',18,'19970312','operation',20000,403,3),
('用户3','female',18,'20130311','operation',19000,403,3),
('用户4','male',18,'20150411','operation',18000,403,3),
('用户5','female',18,'20140512','operation',17000,403,3);
Query OK
, 18 rows affected
(0.34 sec
)
注意
:
select
* from t1 where 条件 group by 分组字段
1、分组只能查询分组字段,要想查看其余的利用聚合函数
2、聚合函数的分类
: count
,min,max,avg
,group_concat
,sum等
3、模糊匹配
: 用like关键字
select
* from t1 where name like
'%al%';
select
* from t1 where name like
'd__l';
4、拷贝表
:
create table t2 select
* from t1
;
create table t2 select
* from t1 where
1=2 ;
3.2、查询语法
SELECT 字段
1,字段
2... FROM 表名
WHERE 条件
GROUP BY field
HAVING 筛选
ORDER BY field
LIMIT 限制条数
3.3、简单查询
SELECT
id,name
,sex
,age
,hire_date
,post
,post_comment
,salary
,office
,depart_id
FROM employee
;
SELECT
* FROM employee
;
SELECT name
,salary FROM employee
;
SELECT DISTINCT post FROM employee
;
SELECT name
, salary
*12 FROM employee
;
SELECT name
, salary
*12 AS Annual_salary FROM employee
;
SELECT name
, salary
*12 Annual_salary FROM employee
;
CONCAT
() 函数用于连接字符串
SELECT CONCAT
('姓名: ',name
,' 年薪: ', salary
*12) AS Annual_salary
FROM employee
;
CONCAT_WS
() 第一个参数为分隔符
SELECT CONCAT_WS
(':',name
,salary
*12) AS Annual_salary
FROM employee
;
3.4、where约束
where字句中可以使用
:
1、比较运算符
: > < >= <= <> !=
2、between
80 and 100 值在
10到
20之间
3、
in(80,90,100) 值是
80或
90或
100
4、like
'al%'
可以是
%或_,
%表示任意多字符
_表示一个字符
like
'al__n'
5、逻辑运算符
: 在多个条件直接可以使用逻辑运算符
and or not
SELECT name FROM employee WHERE post
='sale';
SELECT name
,salary FROM employee WHERE post
='teacher' AND salary
>10000;
SELECT name
,salary FROM employee WHERE salary BETWEEN
10000 AND
20000;
SELECT name
,salary FROM employee WHERE salary NOT BETWEEN
10000 AND
20000;
SELECT name
,post_comment FROM employee WHERE post_comment IS NULL
;
SELECT name
,post_comment FROM employee WHERE post_comment IS NOT NULL
;
SELECT name
,post_comment FROM employee WHERE post_comment
=''; 注意
''是空字符串,不是null
ps
:
执行
update employee
set post_comment
='' where
id=2;
再用上条查看,就会有结果了
SELECT name
,salary FROM employee WHERE salary
=3000 OR salary
=3500 OR salary
=4000 OR salary
=9000 ;
SELECT name
,salary FROM employee WHERE salary IN
(3000,3500,4000,9000) ;
SELECT name
,salary FROM employee WHERE salary NOT IN
(3000,3500,4000,9000) ;
通配符’
%’
SELECT
* FROM employee WHERE name LIKE
'al%';
通配符’_’
SELECT
* FROM employee WHERE name LIKE
'al__';
3.5、having过滤
having和where语法上是一样的
select
* from employee where
id>15;
select
* from employee having
id>15;
where和having的区别
1、Where 是一个约束声明,使用Where约束来自数据库的数据,Where是在结果返回之前起作用的
(先找到表,按照where的约束条件,从表
(文件
)中取出数据
),Where中不能使用聚合函数
2、Having是一个过滤声明,是在查询返回结果集以后对查询结果进行的过滤操作
(先找到表,按照where的约束条件,从表
(文件
)中取出数据,然后group by分组,如果没有group by则所有记录整体为一组,然后执行聚合函数,然后使用having对聚合的结果进行过滤
),在Having中可以使用聚合函数。
3、where的优先级比having的优先级高
4、having可以放到group by之后,而where只能放到group by 之前。
3.6、group by分组查询
大前提
: 可以按照任意字段分组
,但分完组后,只能查看分组的那个字段,要想取的组内的其他字段信息,需要借助函数
单独使用GROUP BY关键字分组
select post
from employee group by post
;
注意
: 我们按照post字段分组,那么select查询的字段只能是post,想要获取组内的其他相关信息,需要借助函数
GROUP BY关键字和group_concat
()函数一起使用
select post
,group_concat
(name
) from employee group by post
;
select post
,group_concat
(name
) as emp_members FROM employee group by post
;
GROUP BY与聚合函数一起使用
select post
,count
(id) as count
from employee group by post
;
强调
:
一般相同的多的话就可以分成一组
(一定是有重复的字段
)
3.7、order by查询排序
按单列排序
SELECT
* FROM employee ORDER BY salary
;
SELECT
* FROM employee ORDER BY salary ASC
;
SELECT
* FROM employee ORDER BY salary DESC
;
按多列排序
: 先按照age排序,如果年纪相同,则按照薪资排序
SELECT
* from employee ORDER BY age
,salary DESC
;
1、select
* from employee order by salary
;
2、select
* from employee order by salary asc
;
3、select
* from employee order by salary desc
;
4、select
* from employee order by age asc
, salary desc
;
3.8、使用聚合函数查询
先
from找到表
再用where的条件约束去表中取出记录
然后进行分组group by,没有分组则默认一组
然后进行聚合
最后select出结果
示例
:
select count
(*) from employee
;
select count
(*) from employee where depart_id
=1;
select
max(salary
) from employee
;
select
min(salary
) from employee
;
select avg
(salary
) from employee
;
select
sum(salary
) from employee
;
select
sum(salary
) form employee WHERE depart_id
=3;
3.9、where的补充(使用正则表达式查询)
1、select
* from employee where name regexp
'^all';
2、select
* from employee where name regexp
'en$';
3、select
* from employee where name regexp
'n{1,2}';
小结
: 对字符串匹配的方式
where name
= 'allen';
where name like
'zhangs%';
where name regexp
'si$';
3.10、limit限制查询的记录数
1、select
* from employee limit
3;
2、像这样表示的
: 指的是从哪开始,往后取几条
(这样的操作一般用来分页
)
select
* from employee limit
0,3;
select
* from employee limit
3,4;
select
* from employee limit
6,3;
select
* from employee limit
9,3;
3、select
* from employee order by
id desc limit
3;
分页显示,每页
5条
select
* from employee limit
0,5;
select
* from employee limit
5,5;
select
* from employee limit
10,5;
3.11、关键字的执行优先级
关键字的执行优先级
:
from
where
group by
having
select
distinct
order by
limit
具体
:
1、找到表
: from
2、拿着where指定的约束条件,去文件
/表中取出一条条记录
3、将取出的一条条记录进行分组group by,如果没有group by,则整体作为一组
4、如果有聚合函数,则将组进行聚合
5、将
4的结果过滤
: having
6、查出结果
: select
7、去重
8、将
6的结果按条件排序
: order by
9、将
7的结果限制显示条数