MySQL基础
- 一、MySQL
- 1. 常见命令
- 2. 语法规范
- 二、查询:DQL语言
- 1. 基础查询
- 2. 条件查询
- 3. 排序查询
- 4. 常见函数
- 01 单行函数
- 02 分组函数
- 5. 分组查询
- 6. 连接查询
- 01 sql92标准
- 02 sql99标准
- 7. 子查询
- 8. 分页查询
- 9. 联合查询
- 三、操纵:DML语言
- 1. 插入
- 2. 修改
- 01 修改单表记录
- 02 修改多表记录
- 3. 删除
- 四、定义:DDL语言
- 1. 库的管理
- 2. 表的管理
- 3. 数据类型
- 01 整型
- 02 浮点型
- 03 字符型
- 04 日期型
- 4. 常见约束
- 01 创建表时添加约束
- 02 修改表时添加约束
- 03 修改表时删除约束
- 5. 标识列
一、MySQL
1. 常见命令
1.登陆与退出: mysql [-h 主机名 -P 端口号] -u root -p密码
2.查看当前所有的数据库:show databases;
3.打开指定的库:use 库名;
4.查看当前库的左右表:show tables;
5.查看其他库的所有表:show tables from 库名;
6.创建表:create table 表名(
列名 列类型,
列名 列类型,
)
7.查看表结构:desc 表名;
8.查看服务器版本:select version();
2. 语法规范
- 不区分大小写,建议关键字大写,表名、列名小写
- 每条命令最好用分号结尾
- 每条命令根据需要可以进行缩进和换行
- 注释:
#单行注释
-- 单行注释
/*注释文字*/
二、查询:DQL语言
1. 基础查询
/* 语法:select 查询列表 from 表名;
* 特点:
* 1.查询列表可以是:表中的字段、常量值、表达式、函数
* 2.查询的结果是一个虚拟的表格
*/
# 查询表中的单个字段
select last_name from employees ;
# 查询表中的多个字段
select last_name,salary,email from employees ;
# 查询表中的所有字段
select * from employees ;
# 查询常量值
select 100 ;
select 'john' ;
# 查询表达式
select 100*98 ;
# 查询函数
select version();
# 起别名
select 100*98 as 结果;
select last_name as 姓, first_name as 名 from employees;
select last_name 姓, first_name 名 from employees;
select salary as `out put` from employees ;
# 去重
select distinct department_id from employees ;
# +号的作用
select 100 + 90; # 两个操作数都是数值型,则作加法运算
select '123' + 90; # 其中一方为字符型时,视图将字符型数值转换为数值型
# 若转换成功,则继续做加法运算;否则将字符型转为0
select null + 123; # 只要一方为null,则结果就为null
# 拼接
select concat('a','b','c') as 结果;
2. 条件查询
/* 语法:select
* 查询列表
* from
* 表名
* where
* 筛选条件;
* 分类:
* 1.按条件表达式筛选:> < = != <> >= <=
* 2.按逻辑表达式筛选:&& || ! and or not
* 3.模糊查询:like、between and、in、is null
*/
# 按条件表达式筛选
select * from employees e where salary > 12000;
select last_name,department_id from employees where department_id <> 90;
# 按逻辑表达式筛选
select last_name,salary ,commission_pct
from employees e
where salary >= 10000 and salary <= 20000;
# 模糊查询
/*like:
* 1.一般和通配符搭配使用:
* % 任意多个字符,包含0个字符
* _ 任意单个字符
*/
# 查询员工名中包含字符a的员工信息
select * from employees where last_name like '%a%';
# 查询员工名中第二个字符为_的员工名
select last_name from employees e where last_name like '_\_%';# like '_$_%' escape '$';
/*between and:
* 使用between and 可以提高语句的简洁度
* 区间简洁包含
* 临界值顺序不可颠倒
*/
select * from employees e where employee_id between 100 and 120;
/*in:
* 含义:用于判断某字段中的值是否属于in列表中的某一项
* 特点:括号内容不支持使用通配符
*/
select last_name, job_id from employees e where job_id in('IT_PROT','AD_VP','AD_PRES');
/*is null:
* =或<>不能判断null值
*/
select last_name, commission_pct from employees where commission_pct is null;
# 安全等于<=>
select last_name, commission_pct from employees where commission_pct <=> null;
select last_name, commission_pct from employees where salary <=> 12000;
3. 排序查询
/* 语法:
* select 查询列表
* from 表
* [where 筛选条件]
* order by 排序列表 [asc|desc]
* 注意:
* 1.asc代表升序,desc代表降序,默认为升序
* 2.order by 后支持单个、多个字段、表达式、函数、别名
* 3.order by 子句一般是放在查询语句的最后边,limit 子句除外*/
select * from employees e order by salary desc;
select * from employees e order by salary asc;
# 添加筛选条件
select *
from employees e
where department_id >= 90
order by hiredate asc;
# 按表达式进行排序
select *, salary * 12 *(1+ifnull(commission_pct,0)) 年薪
from employees e
order by salary * 12 *(1+ifnull(commission_pct,0)) desc;
# 按别名排序
select *, salary * 12 *(1+ifnull(commission_pct,0)) 年薪
from employees e
order by 年薪 desc;
# 按姓名的长度显示员工的姓名和工资[按函数排序]
select length(last_name) 字节长度, last_name, salary
from employees e
order by length(last_name) desc ;
# 查询员工信息,要求先按工资排序,再按员工编号排序[按多个字段排序]
select * from employees e
order by salary asc, employee_id desc;
4. 常见函数
01 单行函数
/*语法:
* select 函数名(实参列表) [from 表];
* 分类:
* 1.单行函数:concat, length, ifnull
* 2.分组函数*/
# 字符函数
# length:获取参数值的字节数
select length('join');
# concat: 拼接字符串
select concat(last_name,'_',first_name) 姓名 from employees e ;
# upper/lower
select upper('join');
# substr/substring
select substr('abcdefg',4) out_put; # defg
select substr('abcdefg',1,3) out_put; # abc
# instr: 返回子串第一次出现的索引,若找不到返回0
select instr('abcdefg','cde') as out_put;
# trim
select length(trim(' abc '))as out_put;
select length(trim('a'from'aaaaaaaaabcaaadaaaaaaaaa')) as out_put;
# lpad:用指定的字符实现左填充指定长度
select lpad('张智森',10,'*') as out_put ; # *******张智森
select rpad('abg',5,'b') as out_put ; # abgbb
# replace: 替换
select replace('abbcdded','b','z');
# 数学函数
# round 四舍五入
select round(1.65); #2
select round(-1.65); #-2
select round(1.567,2); #1.57
# ceil:向上取整,返回大于等于该参数的最小整数
select ceil(1.00) ;
select ceil(-1.02); #-1
# floor:向下取整
# truncate:截断
select truncate(1.65435,1); #1.6
# mod:取余
select mod(-10,-3); #-1
select mod(10,-3); #1
select mod(-10,3); #-1
# rand:获取随机数,返回0-1之间的小数
# 日期函数
# now:返回当前系统日期+时间
select now();
# curdate:返回当前系统日期,不包含时间
select curdate();
# curtime:返回当前系统时间,不包含日期
select curtime();
# 可以获取指定的部分,年/月/日/小时/分钟/秒
select year(now());
select month(now());
select monthname(now());
# str_to_date:将日期格式的字符转换成指定格式的日期
select str_to_date('3-16-2003','%c-%d-%Y');
select * from employees e where hiredate ='1992-4-3';
# date_format:将日期转换为字符
select date_format(now(),'%y年%m月%d日');
# datadiff:计算两个日期之间相差的天数
select datadiff('2003-3-16','2002-8-27');
# 其他函数
select version();
select database();
select user();
# 流程控制函数
# if函数:if else的效果
select if(10 > 5, '大', '小');
select last_name,commission_pct,
if(commission_pct is null,'没奖金,垃圾','有奖金,牛逼') 备注 from employees e ;
# case函数:switch case 的效果
select salary 原始工资,department_id,
case department_id
when 30 then salary * 1.1
when 40 then salary * 1.2
when 50 then salary * 1.3
else salary
end as 新工资
from employees e ;
# case函数:类似于多重if
select salary,
case
when salary > 20000 then 'A'
when salary > 15000 then 'B'
when salary > 10000 then 'C'
else 'D'
end as 工资级别
from employees e ;
02 分组函数
# 分组函数
-- 功能:用作统计使用,有称为聚合函数或统计函数或组函数
-- 分类:sum 求和、avg 平均值、max 最大值、min 最小值、count 计算个数
-- 特点:
-- 1.sum、avg 一般用于处理数值型
-- max、min、count 可以处理任何类型
-- 2.以上分组函数都忽略null值
-- 3.可以和distinct 搭配实现去重运算
-- 4. count函数
-- 5.和分组函数一同查询的字段要求是group by 后的字段
# 1.简单的使用
select sum(salary) from employees e ;
select avg(salary) from employees e ;
select count(salary) from employees e ;
select max(salary) from employees e ;
select sum(salary) 和,round( avg(salary),2) 平均
from employees e ;
# 2.和distinct搭配
select sum(distinct salary),sum(salary) from employees e ;
select count(distinct salary),count(salary) from employees e ;
# 3.count函数详细介绍
select count(salary) from employees e ;
select count(*) from employees e ; # 只要一行内存在一个不为null则统计上,即行数
select count(1) from employees e ; # 与上一个作用一样,都是统计行数
5. 分组查询
# 进阶5:分组查询
/*语法:
select 分组函数,列(要求出现在group by的后面)
from 表
[where 筛选条件]
group by 分组的列表
[order by 子句]
注意:查询列表必须特殊,要求是分组函数和group by 后出现的字段
* 分组查询中的筛选条件可以分为两类*/
# 简单分组
# 案例1:查询每个工种的最高工资
select max(salary),job_id
from employees e
group by job_id;
# 案例2:查询每个位置上的部门个数
select count(*),location_id
from departments d
group by location_id ;
# 添加分组前的筛选条件
# 案例1:查询邮箱中包含a字符的,每个部门的平均工资
select avg(salary),department_id
from employees e
where email like '%a%'
group by department_id ;
# 案例2:查询有奖金的,每个领导手下员工的最高工资
select max(salary),manager_id
from employees e
where commission_pct is not null
group by manager_id ;
# 添加分组后的筛选条件
# 案例1:查询哪个部门的员工个数大于2
select count(*),department_id
from employees e
group by department_id
having count(*)>2;
# 案例2:查询每个工种有奖金的员工的最高工资>12000的工种编号和最高工资
select max(salary),job_id
from employees e
where commission_pct is not null
group by job_id
having max(salary) > 12000;
# 按表达式或函数分组
# 案例:按员工姓名的长度分组,查询每一组的员工个数,筛选员工个数>5的有哪些
select count(*),length(last_name) len_name
from employees e
group by len_name
having count(*) > 5;
# group by 和having 语句都支持别名
# 按多个字段分组
# 案例:查询每个部门每个工种的员工的平均工资
select avg(salary),department_id,job_id
from employees e
group by job_id ,department_id ;
# 添加排序
# 案例:查询每个部门每个工种的员工的平均工资,并按平均工资的高低显示
select avg(salary),department_id,job_id
from employees e
group by job_id ,department_id
order by avg(salary) desc;
6. 连接查询
又称多表查询,当查询的字段来自于多个表时,就会用到连接查询
01 sql92标准
# 1.等值连接
/*
1.多表等值连接的结果为多表的交集部分
2.n表连接,至少需要n-1个连接条件
3.可以搭配使用
*/
# 案例1:查询女生名和对应的男生名
select name, boyname
from boys, beauty
where beauty.boyfriend_id= boys.id;
# 案例2:查询员工名和对应的部门名
select last_name, department_name
from employees,departments
where employees.department_id = departments.department_id ;
# 2.为表起别名: 注意为表起了别名,则查询的字段就不能使用原来的别名去限定
# 案例:查询员工名、工种号、工种名
select last_name, e.job_id, job_title
from employees e,jobs j
where e.job_id = j.job_id;
# 3.两个表的顺序可以调换
select last_name, e.job_id, job_title
from jobs j,employees e
where e.job_id = j.job_id;
# 4.可以加筛选
# 案:1:查询有奖金的员工名、部门名
select last_name, department_name
from employees e , departments d
where e.department_id = d.department_id
and e.commission_pct is not null;
# 案例2:查询城市名中第二个字符为o的部门名和城市名
select department_name ,city
from departments d ,locations l
where d.location_id = l.location_id
and city like '_o%';
# 5.可以加分组
# 案例1:查询每个城市的部门个数
select count(*) 个数, city
from departments d , locations l
group by city;
# 案例2:查询有奖金的每个部门名和部门领导编号和该部门的最低工资
select department_name ,d.manager_id, min(salary)
from departments d ,employees e
where d.department_id = e.department_id
and commission_pct is not null
group by department_name, d.manager_id ;
# 6.可以加排序
# 案例:查询每个工种名和与员工个数,并按照员工个数降序
select job_title ,count(*) 个数
from employees e , jobs j
where e.job_id = j.job_id
group by job_title
order by count(*) desc ;
# 7.可以实现三表连接
# 查询员工名、部门名和所在城市
select last_name ,department_name ,city
from employees e ,departments d ,locations l
where d.location_id = l.location_id
and e.department_id =d.department_id ;
# 非等值连接
# 案例:查询员工工资和工资级别
select salary, grade_level
from employees e ,job_grades jg
where salary between jg.lowest_sal and jg.highest_sal ;
# 自连接
# 案例:查询员工名和上级名称
select e1.employee_id, e1.last_name, e2.employee_id , e2.last_name
from employees e1, employees e2
where e1.manager_id = e2.employee_id ;
02 sql99标准
select 查询列表
from 表1 别名 [连接类型]
join 表2 别名
on 连接条件
[where 筛选条件]
[group by 分组]
[having 筛选条件]
[order by 排序条件]
# 一、内连接
#1.等值连接
# 案例1:查询员工名、部门名
select last_name, department_name
from employees e
inner join departments d
on e.department_id = d.department_id ;
# 案例2:查询名字中包含e的员工和工种名(添加筛选)
select last_name, job_title
from employees e
inner join jobs j
on e.job_id = j.job_id
where e.last_name like "%e%";
# 案例3:查询部门个数>3的城市名和部门个数(添加分组+筛选)
select city, count(*) 部门个数
from departments d
inner join locations l
on d.location_id = l.location_id
group by city
having count(*)>3;
# 案例4:查询每个部门员工个数大于3的部门名和员工个数,并按降序(添加排序)
select count(*) 员工个数, department_name
from departments d
inner join employees e
on d.department_id = e.department_id
group by department_name
having count(*)>3
order by count(*) desc;
# 案例5:查询员工名、部门名、工种名,并按部门名降序
select last_name, department_name, job_title
from jobs j
inner join employees e on e.job_id = j.job_id
inner join departments d on e.department_id = d.department_id
order by department_name desc;
# 2.非等值连接
# 查询员工的工资级别
select salary, grade_level
from employees e
join job_grades jg
on e.salary between jg.lowest_sal and jg.highest_sal ;
# 3.自连接
# 查询员工的名字、上级的名字
select e.last_name, m.last_name
from employees e
join employees m
on e.manager_id = m.employee_id ;
上述案例中inner都可以省略,inner join 的效果与sql92中的等值连接一样。
# 二、外连接
/* 用于查询查询一个表中有,另一个表中没有的情况
* 1.外连接的查询结果为主表中的所有记录,
* 若从表中有和它匹配的,则显示匹配的值
* 若从表中没有和它匹配的,则显示null
* 外连接查询结果=内连接结果+主表中有而从表中没有的记录
* 2.左外连接:left join 左边的是主表
* 右外连接:right join 右边的是主表
* 3.左外和右外交换两个表的顺序,可以实现同样的效果 */
# 左外连接
select b.name
from beauty b
left outer join boys bo
on b.boyfriend_id = bo.boyName
where bo.id is null;
# 右外连接
select b.name
from boys bo
right outer join beauty b
on b.boyfriend_id = bo.boyName
where bo.id is null;
# 案例:查询哪个部门没有员工
select d.*, e.employee_id
from departments d
left outer join employees e
on d.department_id = e.department_id
where e.department_id is null;
# 交叉连接
select b.*, bo.*
from beauty b
cross join boys bo;
# 即笛卡尔成乘机
7. 子查询
含义:出现在其他语句中的select语句,称为子查询或内查询;外部的查询语句,称为主查询或外查询
分类:
按子查询出现的位置:
select 后面:仅支持标量子查询
from 后面:支持表子查询
where或having 后面:标量子查询、列子查询、行子查询
exists后面:表子查询(相关子查询)
按结果集的行列数不同:标量子查询(结果集只有一行一列),列子查询(结果集只有一行多列),行子查询(结果集可以有一行多列)、表子查询(结果集一般为多行多列)
# 一、where或having 后面
-- 1.标量子查询(单行子查询)
# 案例1:谁的工资比Abel高?
select *
from employees e
where salary>(
select salary
from employees
where last_name = 'Abel'
);
select job_id, salary
from employees e
where employee_id = 141;
# 案例2:查询最近工资大于50号部门最低工资的部门id和其最低工资
select min(salary), department_id
from employees e
group by department_id
having min(salary) > (
select min(salary)
from employees
where department_id = 50
);
-- 2.列子查询(多行单列)
# 案例1:返回location_id是1400或1700的部门中的所有员工姓名
select distinct last_name
from employees e
where department_id in (
select department_id
from departments
where location_id in (1400,1700)
)
# 案例2:返回其他部门中比job_id为“IT_PROG”部门任一工资低的员工的员工号、姓名、job_id和salary
select last_name ,employee_id ,job_id ,salary
from employees e
where salary < any(
select distinct salary
from employees
where job_id = 'IT_PROG'
)and job_id <> 'IT_PROG';
# 案例3:返回其他部门中比job_id为“IT_PROG”部门所有工资低的员工的员工号、姓名、job_id和salary
select last_name ,employee_id ,job_id ,salary
from employees e
where salary < all(
select distinct salary
from employees
where job_id = 'IT_PROG'
)and job_id <> 'IT_PROG';
-- 3.行子查询(多行多列)
# 案例:查询员工编号最小并且工资最高的员工信息
select *
from employees e
where (employee_id ,salary)=(
select min(employee_id),max(salary)
from employees
);
# 二、select 后面<仅仅支持标量查询>
# 案例1:查询每个部门的员工个数
select d.*,(
select count(*)
from employees e
where e.department_id = d.department_id
)个数
from departments d ;
# 三、from 后边
/*将子表查询充当一张表,要求必须起别名*/
# 案例:查询每个部门的平均工资的工资等级
select *,jg.grade_level
from (
select avg(salary) ag,department_id
from employees e
group by department_id
)ag_dep
inner join job_grades jg
on ag_dep.ag between lowest_sal and highest_sal;
# exists后面(相关子查询)
# 案例:查询有员工名的部门名
select department_name
from departments d
where exists(
select *
from employees e
where e.department_id = d.department_id
);
8. 分页查询
当要显示的数据一页中显示不全,需要分页提交sql请求
语法:select 查询列表
from 表
[join type] join 表2
on 连接条件
where 筛选条件
group by 分组字段
having 分组后的筛选
order by 排序的字段
limit offset,size; //offset:要现现显示条目的起始索引,size:要显示的条目个数
# 案例1:查询前五条员工信息
select * from employees e limit 0,5;
select * from employees e limit 5; # 默认起始值为0
# 案例2:查询第11条至第25条
select * from employees e limit 10,15;
# 案例3:有奖金的员工信息,并且工资较高的前10名的显示
select * from employees e
where commission_pct is not null
order by salary desc
limit 10;
9. 联合查询
将多条查询语句的结果合并成一个结果
语法:查询语句1
union
查询语句2
union
……
# 引入案例:查询部门编号>90,或者邮箱包含a的员工信息
select * from employees e where email like '%a%' or department_id > 90;
select * from employees e where email like '%a%'
union
select * from employees e where department_id > 90;
要查询的结果来自于多个表,且多个表没有直接的连接关系,但查询的信息一致时:
- 要求多条查询语句的查询列数是一致的
- 要求多条查询语句的查询每一列的类型和顺序一致
- union关键字默认去重,如果用union all 可以包含重复项
三、操纵:DML语言
1. 插入
语法:
insert into 表名(列名,…)
values(值,…);
# 方法一:
# 1.插入的值的类型要与列的类型一致或兼容
insert into beauty (id,name,sex,borndate,phone,photo,boyfriend_id)
values(13,'孟凡','女','2003-3-16','1898888888',null,2);
# 2.不可以插入null的列必须插入值。可以为null的列如何插入值?
# 方式一:
insert into beauty (id,name,sex,borndate,phone,photo,boyfriend_id)
values(13,'xxx','女','2003-3-16','1898888888',null,2);
# 方式二:
insert into beauty (id,name,sex,borndate,phone,boyfriend_id)
values(13,'xxx','女','2003-3-16','1898888888',2);
# 3.列的顺序可以调换
# 4.列数和值的个数必须保持一致
# 5.可以省略列名,默认所有列,而且列的顺序和表中的顺序一致
insert into beauty
values(18,'张飞','女',null,'119',null,null);
# 方式二:
insert into beauty
set id = 19, name = '刘涛', phone = '999';
2. 修改
01 修改单表记录
语法:
update 表名
set 列 = 新值,列 = 新值,……
where 筛选条件;
# 案例1:修改beauty表中姓孟的电话改为:
update beauty set phone = '18888199199'
where name like '孟%';
02 修改多表记录
语法:
sql92语法:
update 表1 别名,表2 别名
set 列 = 值,……
where 连接条件
and 筛选条件;
sql99语法:
update 表1,别名
inner/left/right join 表2 别名
on 连接条件
set 列 = 值,……
where 筛选条件;
# 案例:修改张无忌的女朋友的手机号为114
update boys bo
inner join beauty b on bo.id = b.boyfriend_id
set b.photo = '114'
where bo.boyName = '张无忌';
3. 删除
方式一:delete
单表的删除:
delete from 表名 where 筛选条件
多表删除:
sql92:
delete别名
from 表1 别名,表2 别名
where 连接条件
and 筛选条件
sql99:
delete 表1的别名,表2的别名
from 表1 别名
inner/left/right join 表2 别名 on 连接条件
where 筛选条件;
方式二:turncate
turncate table 表名;
-- 方式一:delete
# 1.单表删除
# 案例:删除手机号以9结尾的女神信息
delete from beauty where phone like '%9';
# 2.多表删除
# 案例:删除张无忌的女神的信息以及自己的信息
delete b,bo
from beauty b
inner join boys bo on b.boyfriend_id = bo.id
where bo.boyName = '张无忌';
-- 方式二:turncate 语句(清空数据)
# 案例:将魅力值>100的男神删除
turncate table boys;
四、定义:DDL语言
1. 库的管理
# 1.库的创建
# 案例:创建库Books
create database if not exists books;
# 2.库的修改
# rename database books to 新库名;已废弃
# 更改库的字符集
alter database books character set gbk;
# 3.库的删除
drop database if exists books;
2. 表的管理
# 1.表的创建
/* 语法:
* create table 表名(
* 列名 列的类型 [(长度) 约束],
* 列名 列的类型 [(长度) 约束],
* 列名 列的类型 [(长度) 约束],
* ……
* 列名 列的类型 [(长度) 约束]
* )*/
# 案例:创建Book表
create table if not exists book(
id int, #编号
bName varchar(20),# 图书名
price double,
authorId int,
publishDate datetime
);
# 2.表的修改
# ①修改列名
alter table book change column publishDate pubDate datetime;
# ②修改类型
alter table book modify column pubDate timestamp;
# ③添加新列
alter table book add column annual double;
# ④删除列
alter table book drop column annual;
# ⑤修改表名
alter table book rename to Book;
# 3.表的删除
drop table if exists book;
# 4.表的复制
# 仅仅复制表的结构
create table copy like author;
# 复制表的结构与数据
create table copy
select * from author;
# 只复制部分数据
create table copy3
select id, au_name
from author
where nation='中国';
# 仅仅复制某些字段(部分表的结构)
create table copy4
select id,au_name
from author
where 1=2; # 构建一个不可能满足的条件
3. 数据类型
01 整型
整数类型 | 字节 |
tinyint | 1 |
smallint | 2 |
mediumint | 3 |
int/integer | 4 |
bigint | 8 |
# 一、整型
/*特点:
* 1.若不设置无符号还是有符号,默认是有符号,如果想设置无符号,需要添加unsigned关键字
* 2.如果插入的数值超出了整数的范围,会报out of range异常,并且插入临界值
* 3.如果不设置长度,会有默认长度
* 长度代表了显示的最大宽度,如果不够会用0在左边填充,但必须搭配zerofill使用。
*/
# 1.设置无符号与有符号
create table tab_int(
t1 int,
t2 int unsigned
);
desc tab_int;
insert into tab_int values(-123456);
insert into tab_int values(-123456,12344554);
02 浮点型
# 二、小数
/*
* 1.浮点型
* float(M,D)
* double(M,D)
* 2.定点型
* dec(M,D)
* decimal(M,D)
*
* 特点:
* 1.M: 整数部位+小数部位
* D: 小数部位
* 如果超出范围,则插入临界值
* 2.M,D可以省略,
* 如果是decimal,则M默认为10,D默认为0,
* 如果是float和double,则会根据插入的数值的精度来决定精度
* 3.定点性精度要求较高,货币运算等使用。
*/
drop table if exists tab_float ;
create table tab_float(
f1 float(5,2),
f2 double(5,2),
f3 decimal(5,2)
);
desc tab_float ;
insert into tab_float values(123.45, 123.45, 123.45);
insert into tab_float values(123.456, 123.456, 123.456);
insert into tab_float values(123.4, 123.4, 123.4);
select * from tab_float ;
03 字符型
# 三、字符型
/*
* 较短的文本:
* char(M)
* varchar(M)
* 较长的文本:
* text
* blob
*
* 特点:
* 1.char代表固定长度的字符,varchar代表可变长度的字符
* 2.M代表最大字符长度
*/
# enum 枚举类型:要求插入的值必须属于列表中指定的值之一
create table tab_char(
c1 enum('a','b','c')
);
insert into tab_char values('a');
insert into tab_char values('b');
insert into tab_char values('c');
insert into tab_char values('n');
insert into tab_char values('A');
select * from tab_char;
# set 集合类型:与enum类似,可以保存最多64个成员,与enum的区别是:
# set一次可以选取多个成员,enum 只能选择一个
create table tab_set(
s1 set('a','b','c','d')
);
insert into tab_set values('a');
insert into tab_set values('a','b');
04 日期型
# 四、日期型
/*
* 分类:
* date 只保存日期
* time 只保存时间
* year 只保存年
*
* datetime 保存日期+时间
* timestamp 保存日期+时间
*
* 特点:
* 字节 范围 时区的影响
* datetime 8 1000——9999 不受
* timestamp 4 1970——2038 受
*/
create table tab_date(
t1 datetime,
t2 timestamp
);
insert into tab_date values(now(),now());
select * from tab_date ;
set time_zone='+9:00';
show variables like 'time_zone';
4. 常见约束
# 常见约束
/*
* 含义:一种限制,用于限制表中的数据,为了保证表中的数据的准确性和可靠性
*
* 分类:六大约束
* 1.not null:非空,用于保证该字段的值不能为空
* 2.default: 默认,用于保证该字段的值有默认值
* 3.primary key:主键,用于保证该字段的值具有唯一性,并且非空
* 4.unique:唯一,用于保证该字段的值具有唯一性,可以为空
* 5.check:检查约束(mysql中不支持),
* 6.foreign key:外键,用于限制两个表的关系,用于保证该字段的值必须来自于主表的关联列的值
* 在从表中添加外界约束,用于引用主表中某列的值
*
* 添加约束的时机:
* 1.创建表时
* 2.修改表时
*
* 约束的添加分类:
* 1.列级约束:六大约束语法上都支持,但外键约束无效果
* 2.表级约束:除了非空和默认其他都支持
*/
01 创建表时添加约束
# 1.添加列级约束
/*
* 语法:
* 直接在字段名和类型名后面追加约束类型即可
* 只支持:默认、非空、主键、唯一
*/
use students;
create table stuinfo(
id int primary key,# 主键
stuName varchar(20) not null,# 非空
gender char(1) check(gender='男' or gender='女'),# 检查,但无效果
seat int unique,# 唯一
age int default 18, # 默认
majorId int references major(id) # 外键
);
create table major(
id int primary key ,
majorName varchar(20)
);
show index from stuinfo;
# 2.添加表级约束:
/*
* 语法:
* [constraint 约束名] 约束类型(字段名)
*/
drop table if exists stuinfo ;
create table stuinfo(
id int,
stuname varchar(20),
gender char(1),
seat int,
age int,
majorid int,
constraint pk primary key(id), # 主键
constraint uq unique(seat), # 唯一
constraint ck check(gender = '男' or gender = '女'),
constraint fk_stuinfo_major foreign key(majorid) references major(id) # 外键
);
外键的特点:
- 要求在从表设置外键的关系
- 从表的外键列的类型和主表的关联列的类型要求一致或兼容,名称无要求
- 主表的关联列必须是一个key(一般是主键或唯一)
- 插入数据时,应该先插入主表,再插入从表
删除数据时,先删除从表,再删除主表
02 修改表时添加约束
/*
* 1.添加列级约束
* alter table 表名 modify column 字段名 字段类型 新约束;
* 2.添加表级约束
* alter table 表名 add [constriant 约束名] 约束类型(字段名) [外键的引用];
*/
# 1.添加非空约束
alter table stuinfo modify column stuname varchar(20) not null;
# 2.添加默认约束
alter table stuinfo modify column age int default(18);
# 3.添加主键
alter table stuinfo modify column id int primary key;#列级约束
alter table stuinfo add primary key(id); #表级约束
# 4.添加唯一
alter table stuinfo modify column seat int unique ;
# 5.添加外键
alter table stuinfo add constraint fk_stuinfo_major foreign key(majorid) references major(id);
03 修改表时删除约束
# 1.删除非空约束
alter table stuinfo modify column stuname varchar(20) null;
# 2.删除默认约束
alter table stuinfo modify column age int;
# 3.删除主键
alter table stuinfo drop primary key;
# 4.删除唯一
alter table stuinfo drop index seat;
# 5.删除外键
alter table stuinfo drop foreign key fk_stuinfo_major;
5. 标识列
# 标识列
/*
* 又称为自增长列(可以不用手动的插入值,系统提供默认的序列值)
*
* 特点:
* 1.标识列不一定必须和主键搭配,但必须是一个key
* 2.一个表只可以有一个标识列
* 3.标识列的类型只能是数值型
* 4.标识列可以通过set auto_increment_increment = 3;设置步长
*
*/
# 一、创建表时设置标识列
drop table if exists tab_identity;
create table tab_identity(
id int primary key auto_increment ,
name varchar(20)
);
truncate table tab_identity ; # 删除表
insert into tab_identity values(null,'john');
insert into tab_identity(id, name) values(null,'john');
insert into tab_identity(name) values('john');
select * from tab_identity ;
# 设置步长
set auto_increment_increment = 3;
# 二、修改表时设置标识列
alter table tab_identity modify column id int primary key auto_increment ;
# 三、修改表时删除标识列
alter table tab_identity modify column id int;