MySQL_数据类型_约束_SQL查询
文章目录
1. 数据类型
既然是数据就必然存在类型之分,mysql数据库对于不同的数据也使用不同的类型进行表示:
- 数值
- 字符串
- 日期时间
1.1. 数值类型
mysql数据库数值类型和Java数值类型对照表
Mysql | Java |
---|---|
tinyint | byte |
smallint | short |
int | int |
bigint | long |
float | float |
double | double |
decimal(m,d) | java.lang.BigDecimal |
Decimal类型中
m
表示数值长度,d
表示小数点后位数(精度)[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uTrNQKEe-1628585723558)(assets/image-20210804094535059.png)]
常用的数值类型:
tinyint
一般用于表示状态字段,例如:订单状态(0-未支付,1-已支付,2-已出库,3-配送中)int
:用于表示常见的整数值,例如:年龄,库存double
:表示常见浮点数据,例如:体重,分数decimal
:用于表示对精度要求高的数值类型,例如:金额
1.2. 字符串类型
Mysql中对于字符串数据表示包含了很多可以选择的类型:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O1xettcb-1628585723559)(assets/image-20210804095337363.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DIBBzXyW-1628585723561)(assets/image-20210804095438410.png)]
以上
char
和varchar
中的M
实际表示的是字符数,Mysql中字符数据占据的存储空间按照如下:
- 字符集如果是
GBK
则一个字符占据2个字节,使用char或varchar存储中文时最大范围是(65536/2)- 字符集如果是
UTF8
则一个字符占据是3个字节,使用char或varchar存储中文时最大范围是(65536/3)
常见字符串类型:
varchar
:可变长字符串char
:定长字符串text
:表示大文本类型enum
:枚举类型
常见面试题:
char
类型和varchar
类型区别?
char
类型是一个定长字符串类型,无论实际为列指定的值大小多少,都会占满申请的空间,不足的内存空间使用空格填充,一般用于长度固定的数据列(例如:性别,手机号,身份证号),不存在大小改变问题,因此效率较高。
varchar
类型是一个可变长字符串类型,在声明时,数据列不会占据存储空间,只在具体赋值时,根据数据值的实际大小占据空间,在内存空间方面能够合理分配,但是如果涉及到值的长度更改,则需要重新分配,因此效率相对char
较低,一般用于长度不定的数据列(例如:姓名,个人简介等)。
enum
枚举类型使用:可以使用枚举类型对可选的数据值进行列举,表示列中存储的数据只能是枚举中的类型,也可以使用序号来表示改列值:
create table t4(a enum('男','女','male','famale')); --使用方式1:直接从枚举中选择值 insert into t4 values('女'); --使用方式2:使用枚举字段序号表示枚举值 insert into t4 values(2); insert into t4 values('2');
在Mysql中字符串类型和数值类型存在隐式转换机制:
create table t5 values(a int,b varchar(5)); --向表中插入数据 insert into t5(a,b) values('123','123'); insert into t5(a,b) values(456,456);
注意事项:对于以上隐式转换机制,只适用于数值数据(数值类型,字符串类型数值)。
1.3. 日期时间类型
Mysql对于日期时间也提供一些常见的数据类型来表示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ePWPJtnc-1628585723563)(assets/image-20210804104326607.png)]
常用的日期时间类型:
date
:用于表示日期(年-月-日)datetime
:用于表示日期时间(年-月-日 时-分-秒)timstamp
:用于表示时间戳(在创建表时可以指定默认值,自动生成,也可以在更新数据时自动更新)
常见日期类型的使用:
create table t6(a date);
insert into t6(a) values('2021-08-08');
insert into t6(a) values('20210808');
insert into t6(a) values('2021/08/08');
-- now()表示当前系统时间(内置函数)
insert into t6(a) values(now());
create table t7(a datetime);
insert into t7(a) values('2021-08-08 12:13:34');
insert into t7(a) values(now());
create table t8(id int,a timestamp default CURRENT_TIMESTAMP);
-- 若未指定timestamp的列值,此时数据库服务器会自动生成系统时间
insert into t8(id) values(2);
注意事项:
- 在使用
timestamp
作为列类型时,一张表中只能为一个timestamp
列指定default CURRENT_TIMESTAMP
1.4. 数据类型总结
Mysql中常见的数据类型主要包含:
- 数值类型:
- int
- double
- decimal
- 字符串类型
- char
- varchar
- text
- 日期时间类型
- datetime
- timestamp
- date
2. 维护数据完整性-约束
Mysql中对数据完整性的保障策略主要包含以下:
- 约束(constraint)
- 数据库可编程性(触发器)
约束是其中最为简单也是最为常用的一种方式,数据库中的约束主要包含以下:
primary key
unique
not null
default
check
(Mysql8.0实现)foreign key
2.1. 主键约束(Primary Key)
通常在创建表时,为了保证每条数据的唯一性,一般都会为每条数据指定一个标志列,该标志列存在以下特征:
- 唯一
- 非空
使用方式:
- 创建表时直接在字段后定义
create table student(
id int primary key, -- 设置主键
...
)
- 建表时,在所有字段末尾设置
create table student(
id int,
sname varchar(16),
...
primary key(id) -- 设置主键列
)
- 表已经创建完成,通过DDL语句修改指定列为主键列
alter table student add constraint pk_sno primary key(id)
auto_increment
:用于设置键列(主键)的自动递增,即该列的值无需再添加数据时手动指定,可以由系统自动生成。主键的使用事项:
- 主键列一般用于标志列(不能重复,不能为空)
- 尽量避免使用联合主键(设置多个列为主键)
- 任何表都应该存在一个主键
- 针对主键列的查询操作效率最高的(唯一索引)
2.2. 唯一约束(Unique)
设置当前列的值在表中不能出现重复的,例如:手机号,账号,qq号,邮箱地址,使用方式:
在建表时使用unique
关键字约束字段即可
phone varchar(16) unique
2.3. 非空约束(Not Null)
设置当前列必须存在一个具体值,不能为null
,除非由设置过列的缺省值(default),使用方式:
在建表时使用not null
关键字约束
username varchar(16) not null
2.4. 缺省值约束(Default)
为当前列设置一个缺省值(默认值),即添加数据时若未指定具体列值,则使用缺省值代替,使用方式:
在建表时使用default 默认值
指定
password varchar(32) default '123456'
2.5. 检查约束(Check)
检查约束用于限定列中数据的范围和内容,例如限制性别列只能是男
或女
;但是该约束的生效是在mysql8.0.5以上版本,以下的版本还未被实现(不生效)
sex char(2) check(sex in('男','女'))
针对版本问题,我们实际可以使用enum
代替
sex enum('男','女')
约束综合使用:
create table student(
sno int,
sname varchar(16) not null,
pwd varchar(32) not null default '123456',
phone char(11) unique,
sex enum('男','女')),
primary key (sno)
);
2.6. 外键约束(Foreign Key)
为了维护表和表之间的数据完整性,通常会使用一种约束:外键约束,对数据列进行限定;
外键约束指的是将一个表(从表)的某一个列于另一个表(主表)的主键列关联,这样一来,从表中的数据列值只能从主表列中筛选,外键创建方式分为两种:
-
在创建表时直接指定
create table student ( sno int primary key auto_increment, sname varchar(16) not null, pwd varchar(32) default '123456', cno int, foreign key(cno) references classes(cno) -- 设置外键 )
-
表已创建完成,后续通过
DDL
修改alter table student add constraint fk_cno foreign key(cno) references classes(cno);
外键约束注意事项:
- 外键列必须关联其他表的
主键列
- 被关联的表叫主表,外键列所在表叫从表
- 在进行数据删除时,需要先删除从表数据再删除主表数据
关于pk_sno
和fk_cno
:
指的是主键外键的别名,类似变量名,可以通过该名称对主外键进行删除操作:
alter table student drop foreign key fk_cno;
3. 运算符
3.1. 算术运算
运算符 | 操作方式 | 说明 |
---|---|---|
+ | a + b | 实现两数相加 |
- | a - b | 两数相减 |
- | -a | 一元减号,取负值 |
* | a * b | 两数相乘 |
/ | a / b | 两数相除 |
% | a % b | 两数取余 |
3.2. 关系运算
运算符 | 操作方式 | 说明 |
---|---|---|
= | a=b | 如果两操作数相等则为true |
!=,<> | a != b,a<>b | 如果两操作数不相等则为true |
> | a > b | 如果a大于b,为true |
>= | a >= b | 如果a大于等于b,为true |
< | a < b | 如果a小于b,为true |
<= | a <= b | 如果a小于等于b,为true |
in | a in(b1,b2,b3…) | 判断a是否是b1,b2,b3…中的一个 |
between…and | a between b1 and b2 | 判断a是否在b1,b2之间 |
like | a like b | 如果a与b匹配,则为true |
not like | a not like b | 如果a与b不匹配,则为true |
is null | a is null | 如果操作数为null,则为true |
is not null | a is not null | 如果操作数不为null,则为true |
3.3. 逻辑运算
运算符 | 操作房四海 | 说明 |
---|---|---|
and,&& | a and b,a && b | 逻辑与,两操作数都为true则为true |
or,|| | a or b,a||b | 逻辑或,两操作数任意一个为true,则为true |
not,! | not a,!a | 逻辑非,如果操作数为false,则结果为true |
4. SQL查询
SQL语句中对于程序员来说最为重要的当属DML
,而DML语句中最常用的语句一般为查询语句select
;对于增删改操作千篇一律,但是查询语句千变万化。
查询语句的语法规范:
select 查询列 from 查询目标表
where 查询条件
group by 分组依据 having 分组条件
order by 排序列
limit 起始查询位置,结果集条数
对于查询语句的编写可以先从以下几个目标展开:
- 查询表是哪一张(哪几张)
- 查询列有哪些
- 查询条件
4.1. 单表查询
4.1.1 基础查询
-- 查询所有数据
select * from student;
-- 查询指定列
select sno,sname,phone from student;
-- 查询所有学生姓名(去除重复)
select distinct sname from student;
-- 查询学生姓名,手机号(拼接前缀)
select sname,concat('+86-',phone) from student;
/* 聚合函数(分组函数)*/
-- 统计数据的总行数
select count(*) from student;
-- 查询最高的学分
select max(score) from student;
-- 查询最低的学分
select min(score) from student;
-- 查询平均的学分
select avg(score) from student;
-- 对学分求和
select sum(score) from student;
4.1.2. 条件查询
-- 查询所有学分在60分以上的学生信息
select * from student where score >= 60;
-- 查询区间值(查询分数在70~90之间的学生)
select * from student where score>=70 and score <=90;
select * from student where score between 70 and 90;
-- 查询james,lily,lucy三名学生的成绩和姓名
select score,sname from student where sname='james' || sname='lily' || sname='lucy';
select score,sname from student where sname='james' or sname='lily' or sname='lucy';
select score,sname from student where sname in('james','lily','lucy');
-- 查询所有学分不等80 的学生信息
select * from student where score != 80;
select * from student where score <> 80;
/*模糊查询*/
-- 查询所有名字以"l"开头的学生信息
select * from student where sname like 'l%';
-- 查询所有名字以"j"开头5个子符的学生
select * from student where sname like 'j____';
-- 查询所有名字中包含’e‘的学生信息
select * from student where sname like '%e%';
-- 查询任意列中包含指定查询目标字符串(将部分列拼接成一个字符串)
select concat(sno,sname,phone,sex,score) from student where concat(sno,sname,phone,sex,score) like '%89%' ;
-- 查询名字不是以"j"开头的学生信息
select * from student where sname not like 'j%';
-- 查询所有没有参加社团的学生
select * from student where gid is null;
-- 查询所有参加过社团的学生
select * from student where gid is not null;
模糊查询问题:
%
是一个占位符,表示任意个字符_
是一个占位符,只表示一个字符
4.1.3. 分组,排序,分页
/* 分组 */
-- 查询每个班级的平均分和班级号
select cno,avg(score) '平均分' from student group by cno;
-- 查询每个班级的总人数
select cno,count(sno) from student group by cno;
-- 查询出总人数超过4个人的班级和总人数
select cno,count(sno) from student group by cno having count(sno) > 4;
/* 排序 */
-- 查询所有学生成绩,并排序显示(默认从低到高 asc)
select * from student order by score;
-- 查询所有学生成绩,并降序显示
select * from student order by score desc;
-- 查询每个班的平均分并降序显示
select cno,avg(score) from student group by cno order by avg(score) desc;
/* 分页(对查询数据行限制)*/
-- 查询前5条数据
select * from student limit 5;
-- 查询分数排名前三的学生信息
select * from student order by score desc limit 3;
-- 查询第二页数据,每页显示3条,limit后面的参数:1-查询起始索引位置,2-结果集数目
select * from student limit 3,3;
注意事项:
group by...having
:查询列必须是分组列或者分组函数,having
表示分组条件,分组条件也应该分组列或分组函数order by asc|desc
:默认排序规则使用升序asc
,order by
一般出现在查询语句的末尾(在limit
之前)limit
:对结果集限制,可以使用1个或者两个参数,如果1个则指的结果集的前n条;如果是两个则,第一个表示查询的起始位置,第二个表示条数限制。