-- 添加自增站约束 create table t_user1( id intprimary key auto_increment, name varchar(20) ); -- 从1开始自增长,每次加1 insert into t_user1 values(NULL,'张三'); insert into t_user1(name) values('李四');
指定自增字段初始值
-- 方式一:创建表时指定 create table t_user2( id intprimary key auto_increment, name varchar(20) )auto_increment=100;
-- 方式二:创建表之后指定 create table t_user3( id intprimary key auto_increment, name varchar(20) ); -- 通过修改表结构来指定初始值 alter table t_user3 auto_increment =200;
delete** 和 truncate 在删除后自增列的变化**
delete 数据之后自动增长从断点开始
truncate 数据之后自动增长从默认起始值开始
-- delete删除数据之后,自增长还是在最后一个值基础上加1 deletefrom t_user2; -- 如最后一个id值为100,则删除重新添加数据之后从101开始 insert into t_user2(name) values('李四');
-- truncate删除之后,自增长从1开始 truncate t_user3; insert into t_user3(name) values('李四');
非空约束
使用了非空约束的字段,如果用户在添加数据时没有指定值,数据库系统就会报错
添加
-- 方式一:创建表时指定 字段名 数据类型 not null; create table t_user6( id int, name varchar(20) not null, -- 指定非空约束 address varchar(20) not null ); -- insert into t_user6(id) values(1001); name、address为空报错 -- 控制字符串可以 insert into t_user6(id,name,address) values(1001,'',''); -- 字符串为NULL insert into t_user6(id,name,address) values(1001,'NULL','NULL');
-- 方式二:创建表之后通过修改表结构指定 alter table 表名 modify 字段 类型 not null; create table t_user7( id int, name varchar(20), address varchar(20) ); alter table t_user7 modify name varchar(20) not null;
删除
alter table t_user7 modify name varchar(20);
唯一约束
一个表可以有多个唯一约束,可以包含NULL值
添加
-- 方式一:创建表时指定 <字段名><数据类型>unique create table t_user8( id int, name varchar(20), phone_number varchar(20) unique ); insert into t_user8 values(1001,'张三',138); -- phone_number不能重复 -- insert into t_user8 values(1001,'张三',138); -- 在mysql中NULL和任何值都不相同,甚至和自己都不相同 insert into t_user8 values(1002,'张1',NULL); insert into t_user8 values(1003,'张2',NULL);
-- 方式二:创建表之后通过修改表结构指定 alter table 表名 add constraint 约束名 unique(列); create table t_user9( id int, name varchar(20), phone_number varchar(20) ); alter table t_user9 add constraint unique_pn unique(phone_number);
删除
alter table<表名>drop index <唯一约束名>;
-- 使用第二种创建的约束删除 alter table t_user9 drop index unique_pn; -- 使用第一种创建的约束删除,约束名为约束那一列的列名 alter table t_user8 drop index phone_number;
默认约束
默认值约束用来指定某列的默认值
创建
-- 方式一:创建表时指定 <字段名><数据类型>default<默认值>; create table t_user10( id INT, name varchar(20), address varchar(20) default'北京' ); -- address没给定值,默认为北京 insert into t_user10(id,name) values(1001,'李四');
-- 方式二:创建表之后通过修改表结构指定 alter table 表名 modify 列名 类型 default 默认值; create table t_user11( id INT, name varchar(20), address varchar(20) ); alter table t_user11 modify address varchar(20) default'深圳'; insert into t_user11(id,name) values(1001,'李四');
删除
alter table<表名> modify column<字段名><类型>defaultnull;
alter table t_user11 modify address varchar(20) defaultnull;
零填充约束
插入数据时,当该字段的值的长度小于定义的长度时,会在该值的前面补上相应的0
创建
create table t_user12( id int zerofill, name varchar(20) ); insert into t_user12 values(20,'李四');
-- 添加主表数据 -- 注意必须先给主表添加数据 insert into dept values('1001','研发部'); insert into dept values('1002','销售部'); insert into dept values('1003','财务部'); insert into dept values('1004','人事部');
-- 添加从表数据 -- 注意给从表添加数据时,外键列的值不能随便写,必须依赖主表的主键列 insert into emp values('1','乔峰',20, '1001'); insert into emp values('2','段誉',21, '1001'); insert into emp values('3','虚竹',23, '1001'); insert into emp values('4','阿紫',18, '1002'); insert into emp values('5','扫地僧',35, '1002'); insert into emp values('6','李秋水',33, '1003'); insert into emp values('7','鸠摩智',50, '1003'); insert into emp values('8','天山童姥',60, '1005'); -- 不可以(外键需要添加主键有的)
删除数据
主表的数据被从表依赖时,不能删除,否则可以删除
从表的数据可以随便删除
-- 1001部门号被外键绑定,不能删除 deletefrom dept where deptno ='1001'; -- 1004部门号没有被外键依赖,可以删除 deletefrom dept where deptno ='1004'; -- 从表数据随便删 deletefrom emp where eid ='7';
多对多关系
修改和删除时,中间从表可以随便删除和修改,但是两边的主表受从表依赖的数据不能删除或者修改
-- 创建学生表student(左侧主表) create table if notexists student( sid intprimary key auto_increment, name varchar(20), age int, gender varchar (20) );
-- 建立外键约束(2次) alter table score addforeign key(sid) references student(sid); alter table score addforeign key(cid) references course(cid);
-- 给学生表添加数据 insert into student values(1,'小龙女',18,'女'), (2,'阿紫',19,'女'), (3,'周芷若',20,'男'); -- 给课程表添加数据 insert into course values(1,'语文'),(2,'数学'),(3,'英语'); -- 给中间表添加数据 insert into score values(1,1,58),(1,3,50),(2,1,89),(2,2,64),(3,2,25),(3,3,82);
多表联合查询
交叉连接查询(了解)
一张表的每一行去和另外一张表的任意一行进行匹配
假如A表有m行数据,B表有n行数据,则返回m*n行数据
笛卡尔积会产生很多冗余的数据,后期的其他查询可以在该集合的基础上进行条件筛选
select*from 表1,表2,表3….;
select*from dept3,emp3;
内连接查询
[!NOTE]
查询求多张表的交集,关键字 inner join (inner可以省略)
-- 隐式内连接(SQL92标准) select*from A,B where 条件; -- 显示内连接(SQL99标准) select*from A innerjoin B on 条件;
-- 查询每个部门的所属员工 -- 隐式内连接 select*from dept3,emp3 where dept3.deptno = emp3.dept_id; -- 显示内连接 select*from dept3 join emp3 on dept3.deptno = emp3.dept_id;
-- 查询研发部所属员工 -- 隐式内连接 select*from dept3 a,emp3 b where a.deptno = b.dept_id and a.name ='研发部'; -- 显示内连接 select*from dept3 a join emp3 b on a.deptno = b.dept_id and a.name ='研发部';
-- 查询研发部和销售部的所属员工 -- 隐式内连接 select*from dept3 a,emp3 b where a.deptno = b.dept_id and (a.name ='研发部'or a.name ='销售部'); -- 显示内连接 select*from dept3 a join emp3 b on a.deptno = b.dept_id and (a.name ='研发部'or a.name ='销售部'); select*from dept3 a join emp3 b on a.deptno = b.dept_id and a.name in ('研发部'or'销售部');
-- 查询每个部门的员工数,并升序排序 select a.name,a.deptno,count(1) c from dept3 a join emp3 b on a.deptno = b.dept_id groupby a.deptno,a.name orderby c desc;
-- 查询人数大于等于3的部门,并按照人数降序排序 select a.deptno,a.name,count(1) as total_cnt from dept3 a join emp3 b on a.deptno = b.dept_id groupby a.deptno,a.name having total_cnt >=3 orderby total_cnt desc;
外连接查询
[!NOTE]
关键字 outer join(outer可以省略)
显示符合连接条件的信息,信息内容是左表还是右边或都显示,看是左连接还是右连接或满连接
union操作符用于合并两个或多个select语句的结果集,但是每个select语句必须选择相同数量的列,列也必须具有相似的数据类型,union默认会去除重复的行,如果需要保留重复的行,可以使用union all
-- 左外连接:left outer join select*from A leftouterjoin B on 条件; -- 右外连接:right outer join select*from A rightouterjoin B on 条件; -- 满外连接: full outer join -- oracle里面有full join,可是在mysql对full join支持的不好,使用union来达到目的 select*from A fullouterjoin B on 条件;
-- 左连接 -- 查询哪些部门有员工,哪些部门没有员工 select*from dept3 a leftouterjoin emp3 b on a.deptno = b.dept_id; select*from dept3 a leftjoin emp3 b on a.deptno = b.dept_id;
select*from A leftjoin B on 条件1 leftjoin C on 条件2 leftjoin D on 条件3;
-- 右连接 -- 查询哪些员工有对应的部门,哪些没有 select*from dept3 a rightouterjoin emp3 b on a.deptno = b.dept_id; select*from dept3 a rightjoin emp3 b on a.deptno = b.dept_id;
-- 满外连接 -- 使用union关键字实现左外连接和右外连接的并集 -- select * from dept3 a full join emp3 b on a.deptno = b.dept_id; -- 不能执行 select*from dept3 a leftjoin emp3 b on a.deptno = b.dept_id union select*from dept3 a rightjoin emp3 b on a.deptno = b.dept_id;
基本子查询
select的嵌套
[!IMPORTANT]
子查询返回的数据类型:
单行单列:返回的是一个具体列的内容,可以理解为一个单值数据
单行多列:返回一行数据中多个列的内容
多行单列:返回多行记录之中同一列的内容,相当于给出了一个操作范围
多行多列:查询返回的结果是一张临时表
-- 查询年龄最大的员工信息,显示信息包含员工号、员工名字,员工年龄 -- 1.查询最大年龄 selectmax(age) from emp3; -- 2.每一个员工的年龄和最大年龄进行比较,相等则满足条件 select*from emp3 where age = (selectmax(age) from emp3); -- 单行单列可以作为一个值来用
-- 查询年研发部和销售部的员工信息,包含员工号、员工名字 -- 内连接查询 select*from emp3 a join dept b on a.dept_id = b.deptno and (b.name ='研发部'or b.name ='销售部');
-- 子查询 -- 1.先查询研发部和销售部的部门号:deptno 1001 1002 select dept.deptno from dept where dept.name ='研发部'or dept.name ='销售部'; -- 2.查询哪个员工的部门号是1001 或 1002 select a.dept_id,a.ename from emp3 a where a.dept_id in (select dept.deptno from dept where dept.name ='研发部'or dept.name ='销售部'); -- 多行单列,多个值
-- 查询研发部20岁以下的员工信息,包括员工号、员工名字,部门名 -- 关联查询 select*from emp3 a join dept b on (b.name ='研发部'and a.age <20); -- 子查询 -- 2.1在部门表中查询研发部信息 select*from dept3 where name ='研发部'; -- 一行多列 -- 2.2在员工表中查询年龄小于30岁的员工信息慕容博 select*from emp3 where age <30; -- 2.3将以上两个查询的结果进行关联查询 select* from (select*from dept3 where name ='研发部') t1 join (select*from emp3 where age<30) t2 on t1.deptno = t2.dept_id; -- 多行多列
select 字段列表 from 表1 a , 表1 b where 条件; 或者 select 字段列表 from 表1 a [left] join 表1 b on 条件;
-- 1.查询每个三国人物及他的上级信息,如: 关羽 刘备 select a.ename,b.ename from t_sanguo a, t_sanguo b where a.manager_id = b.eid; select a.ename,b.ename from t_sanguo a join t_sanguo b on a.manager_id = b.eid;
-- 查询所有任务及上级 select a.ename,b.ename from t_sanguo a leftjoin t_sanguo b on a.manager_id = b.eid;
函数
聚合函数
group_concat()函数,数据的某一列合并成一行
-- 将所有员工的名字合并成一行(默认;分隔) select group_concat(emp_name) from emp;
-- 指定分隔符合并 select group_concat(emp_name separator ';') from emp;
-- 指定排序方式和分隔符 select department,group_concat(emp_name separator ';') from emp groupby department;
计算起始日期 d 加上一个时间段后的日期,expr:数字 type 值可以是:microsecond(微秒)、second(秒)、minute(分钟)、hour(小时)、day(天)、week(周)、month(月)、quarter(季)、year(年)、DAY_MINUTE day_minute(天和分钟)、day_hour(天和小时)、ear_month(年和月)
extract(type from d)
从日期 d 中获取指定的值,type指定返回的值 type 可取值为:microsecond(微秒)、second(秒)、minute(分钟)、hour(小时)
row_number() |rank() |dense_rank() over ( partitionby ... orderby ... )
-- 对每个部门的员工按照薪资降序排序,并给出排名 select dname, ename, salary, row_number() over(partitionby dname orderby salary desc) as rn1, rank() over(partitionby dname orderby salary desc) as rn2, dense_rank() over(partitionby dname orderby salary desc) as rn3 from employee;
--求出每个部门薪资排在前三名的员工- 分组求TOPN select * from ( select dname, ename, salary, dense_rank() over(partitionby dname orderby salary desc) as rn from employee )t where t.rn <=3
-- 对所有员工进行全局排序(不分组) -- 不加partition by表示全局排序 select dname, ename, salary, dense_rank() over( orderby salary desc) as rn from employee;
开窗聚合函数
sum()、avg()、max()、min()、count()
select dname, ename, salary, sum(salary) over(partitionby dname orderby hiredate) as pvl from employee;
-- 如果没有order by排序语句默认把分组内的所有 select dname,ename,hiredate,salary, sum(salary) over(partitionby dname) as c1 -- sum(salary) over(partition by dname order by hiredate rows between unbounded preceding and current row) as c1 from employee;
-- 向前三行及本身及向后一行数据相加 select dname, ename, salary, sum(salary) over(partitionby dname orderby hiredate rowsbetween3 preceding and1 following) as c1 from employee;
-- 当前行(包括本身)加到最后一行 select dname, ename, salary, sum(salary) over(partitionby dname orderby hiredate rowsbetweencurrentrowand unbounded following) as c1 from employee;