当前位置: 首页 > article >正文

数据库基础操作 all in one

数据库

  • 1. 概述
  • 2. 详述
  • 3. 创建数据库表
  • 4. 增加数据库记录
  • 5. 修改和删除数据库记录
  • 6. 修改和删除数据库表
  • 7.非外键约束
  • 8.外键约束
  • 9.外键策略
  • 10.杂项-快速拷贝表
  • 11.表的准备
  • 12.单表查询
  • 13.where子句
  • 14. 单行多行函数
  • 15. group by 和 having
  • 小结1-单表查询总结
  • 16. 多表查询-内连接
  • 17.多表查询-外连接
  • 18.多表联查
  • 19.自关联
  • 20.单行子查询
  • 21.多行子查询
  • 22.相关子查询
  • 23.事务

1. 概述

数据库的基础操作主要分为六块。

  • DQL:Query,select
  • DML: Manual,insert update delete
  • DDL:Define,create drop alter
  • DCL: Control,grant revoke commit rollback
  • 函数:字符串函数、数字函数、日期函数
  • 运算符:算术运算符、比较运算符、逻辑运算符、位运算符

2. 详述

SQL语言分为五个部分:
• 数据查询语言(Data Query Language,DQL):DQL主要用于数据的查询,其基本结构是使用SELECT子句,FROM子句和WHERE子句的组合来查询一条或多条数据。
• 数据操作语言(Data Manipulation Language,DML):DML主要用于对数据库中的数据进行增加、修改和删除的操作,其主要包括:
  1) INSERT:增加数据
  2) UPDATE:修改数据
  3) DELETE:删除数据
• 数据定义语言(Data Definition Language,DDL):DDL主要用针对是数据库对象(数据库、表、索引、视图、触发器、存储过程、函数)进行创建、修改和删除操作。其主要包括:
  1) CREATE:创建数据库对象
  2) ALTER:修改数据库对象
  3) DROP:删除数据库对象
• 数据控制语言(Data Control Language,DCL):DCL用来授予或回收访问 数据库的权限,其主要包括:
  1) GRANT:授予用户某种权限
  2) REVOKE:回收授予的某种权限
• 事务控制语言(Transaction Control Language,TCL):TCL用于数据库的事务管理。其主要包括:
  1) START TRANSACTION:开启事务
  2) COMMIT:提交事务
  3) ROLLBACK:回滚事务
  4) SET TRANSACTION:设置事务的属性

3. 创建数据库表

#这是一个单行注释
-- 这也是单行注释
/*
多行
注释
*/

create table t_student(
	snum int(6),
	sname varchar(5),
	sex char(1),
	age int(3),
	enterdate date,
	class varchar(6),
	email varchar(15)
);


desc t_student;

select * from t_student;
show create table t_student;

4. 增加数据库记录

select * from t_student;

insert into t_student values (1, '小明' ,'男', 18, '2023-2-12',3,'3303@qq.com');
insert into t_student values (10001011, '小明' ,'男', 18, '2023-2-12',3,'3303@qq.com');
insert into t_student values (2, '小明' ,'男', 18, '2023/2/12',3,'3303@qq.com');
insert into t_student values (1, '小王' ,"男", 18, '2023.2.12',3,'3303@qq.com');
insert into t_student values (9, '小李' ,'女', 17, now(),3,'3303@qq.com');
insert into t_student (snum,enterdate,sex) values (9, now(),"女");


select * from t_student;

5. 修改和删除数据库记录

select * from t_student;

-- 修改表中数据 都是不区分大小写的,内容插可区分大小写,但查不区分
#全表
update t_student set sex = '女';
update t_student set sex = '男' where snum = 9;
UPDATE T_STUDENT SET SEX = '男' where snum = 1;
update t_student set class = 'PYTH1' where snum = 1;
update t_student set class = "pyth1" where snum=2;
update t_student set sname = 'nope' where class = 'pyth1';
#限制字段

select * from t_student;
delete from t_student where snum = 2;

6. 修改和删除数据库表

select * from t_student;

alter table t_student add score double(5,2);
update t_student set score = 123.5678 where snum = 9;

update t_student set snum = 1 where enterdate = '2023-02-12';


alter table t_student add first_column int(6) first;
alter table t_student add special_column int(6) after sex;

alter table t_student drop first_column;


alter table t_student modify score float(4,1);
alter table t_student change score score1 double (5,1);

drop table t_student;

7.非外键约束

create table t_student_1(
	snum int(6) primary key AUTO_INCREMENT,
	sname varchar(5) not null,
	sex char(1) default '男' check(sex='男' || sex='女'),
	age int(3) check(age>=18 and age<=50),
	enterdate date,
	class varchar(6),
	email varchar(15) unique
	constraint pk_stu primary key (sno),  -- pk_stu 主键约束的名字
	constraint ck_stu_sex check (sex = '男' || sex = '女'),
  constraint ck_stu_age check (age >= 18 and age <= 50),
  constraint uq_stu_email unique (email)

);
-- •	学号是主键 = 不能为空 +  唯一 
-- •	姓名不能为空 
-- •	性别默认值是男 
-- •	Email唯一 
select * from t_student_1;


drop table t_student;
create table t_student(
	sno int(6),
	sname varchar(5),
	sex char(1),
	age int(3),
	enterdate date,
	class varchar(6),
	email varchar(15)
);

alter table t_student add constraint pk_stu primary key (sno) ; -- 主键约束
alter table t_student modify sno int(6) auto_increment; -- 修改自增条件(由于自增必须先设置主键,所以才有了上面第21行)
alter table t_student add constraint ck_stu_sex check (sex = '男' || sex = '女');
alter table t_student add constraint ck_stu_age check (age >= 18 and age <= 50);
alter table t_student add constraint uq_stu_email unique (email);

-- 查看表结构:
desc t_student;
	
insert into t_student values (1,'张三','男',18,'2022-5-8','软件1班','123@126.com');
insert into t_student values (10010010,'李四','男',18,'2022-5-8','软件1班','124@126.com');

select * from t_student;

8.外键约束

create table t_class(
cno int(4) primary key auto_increment,
cname varchar(10) not null,
room char(4)
)

insert into t_class values (null,'java001','r803');
insert into t_class values (null,'java002','r416');
insert into t_class values (null,'大数据001','r103');

insert into t_class values (null,'java001','r803'),(null,'java002','r416'),(null,'大数据001','r103');

select * from t_class;

drop table t_student;

create table t_student(
	snum int(6) primary key auto_increment,
	sname varchar(5) not null,
	class int(4),
	constraint fk_stu_classno foreign key(class) references t_class(cno) -- 法1
);

insert into t_student values (null,'张三','1'),(null,'李晓明','2'),(null,'阳光男孩','3');

select * from t_student;

alter table t_student add constraint fk_stu_classno foreign key(class) references t_class(cno); -- 法2

9.外键策略

-- 先删从表再删主表 不然会删不掉
drop table t_student;
drop table t_class;

create table t_class(
cno int(4) primary key auto_increment,
cname varchar(10) not null,
room char(4)
);

create table t_student(
	snum int(6) primary key auto_increment,
	sname varchar(5) not null,
	class int(4),
	constraint fk_stu_classno foreign key(class) references t_class(cno) -- 法1
);

insert into t_class values (null,'java001','r803'),(null,'java002','r416'),(null,'大数据001','r103');
insert into t_student values (null,'张三','1'),(null,'李晓明','2'),(null,'阳光男孩','3');

select * from t_class;
select * from t_student;

-- 删除有外键约束的父表记录,策略1为no action,不允许.也即只能先将子表相关记录置空,然后再删父表记录,
update t_student set class = null where class = 2;
delete from t_class where cno =2;

-- 策略2为cascade级联操作(全影响),先删外键约束,再新建外键约束
alter table t_student drop foreign key fk_stu_classno;
alter table t_student add constraint fk_stu_classno foreign key(class) references t_class(cno) on update cascade on delete cascade;

update t_class set cno = 5 where cno = 3;
delete from t_class where cno = 5;

-- 策略3为setnull,也即动了以后,别的相关的全变成null。
alter table t_student drop foreign key fk_stu_classno;
alter table t_student add constraint fk_stu_classno foreign key(class) references t_class(cno) on update set null on delete set null;

update t_class set cno = 8 where cno = 1;

-- 注意:可混用。比如
alter table t_student add constraint fk_stu_classno foreign key(class) references t_class(cno) on update cascade on delete set null;

10.杂项-快速拷贝表

-- 结构√数据√
create table t_student2
as
select * from t_student;

select * from t_student2;

-- 结构√数据×
create table t_student3
as
select * from t_student where 1=2;

select * from t_student3;

-- 结构√部分列数据√
create table t_student4
as 
select snum,sname from t_student where snum = 2;
select * from t_student4;


-- 清空数据的两条相似操作:delete和truncate(区别-面试题)
delete from t_student;-- 不填where xxx 意思是 全删。 一条一条删数据。
truncate table t_student; -- 重新创表,效率高 


11.表的准备

create table DEPT(  
  DEPTNO int(2) not null,  
  DNAME  VARCHAR(14),  
  LOC    VARCHAR(13)  
);  

alter table DEPT  
  add constraint PK_DEPT primary key (DEPTNO); 
        
create table EMP  
(  
  EMPNO    int(4) primary key,  
  ENAME    VARCHAR(10),  
  JOB      VARCHAR(9),  
  MGR      int(4),  
  HIREDATE DATE,  
  SAL      double(7,2),  
  COMM     double(7,2),  
  DEPTNO   int(2)  
);  

alter table EMP  
  add constraint FK_DEPTNO foreign key (DEPTNO)  
  references DEPT (DEPTNO);  
        
create table SALGRADE  
(  
  GRADE int primary key,  
  LOSAL double(7,2),  
  HISAL double(7,2)  
);  
create table BONUS  
(  
  ENAME VARCHAR(10),  
  JOB   VARCHAR(9),  
  SAL   double(7,2),  
  COMM  double(7,2)  
);  

insert into DEPT (DEPTNO, DNAME, LOC)  
values (10, 'ACCOUNTING', 'NEW YORK');  
insert into DEPT (DEPTNO, DNAME, LOC)  
values (20, 'RESEARCH', 'DALLAS');  
insert into DEPT (DEPTNO, DNAME, LOC)  
values (30, 'SALES', 'CHICAGO');  
insert into DEPT (DEPTNO, DNAME, LOC)  
values (40, 'OPERATIONS', 'BOSTON');  


insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)  
values (7369, 'SMITH', 'CLERK', 7902, '1980-12-17', 800, null, 20);  
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)  
values (7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20', 1600, 300, 30);  
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)  
values (7521, 'WARD', 'SALESMAN', 7698, '1981-02-22', 1250, 500, 30);  
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)  
values (7566, 'JONES', 'MANAGER', 7839, '1981-04-02', 2975, null, 20);  
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)  
values (7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28', 1250, 1400, 30);  
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)  
values (7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01', 2850, null, 30);  
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)  
values (7782, 'CLARK', 'MANAGER', 7839, '1981-06-09', 2450, null, 10);  
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)  
values (7788, 'SCOTT', 'ANALYST', 7566, '1987-04-19', 3000, null, 20);  
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)  
values (7839, 'KING', 'PRESIDENT', null, '1981-11-17', 5000, null, 10);  
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)  
values (7844, 'TURNER', 'SALESMAN', 7698, '1981-09-08', 1500, 0, 30);  
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)  
values (7876, 'ADAMS', 'CLERK', 7788, '1987-05-23', 1100, null, 20);  
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)  
values (7900, 'JAMES', 'CLERK', 7698, '1981-12-03', 950, null, 30);  
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)  
values (7902, 'FORD', 'ANALYST', 7566, '1981-12-03', 3000, null, 20);  
insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)  
values (7934, 'MILLER', 'CLERK', 7782, '1982-01-23', 1300, null, 10);  


insert into SALGRADE (GRADE, LOSAL, HISAL)  
values (1, 700, 1200);  
insert into SALGRADE (GRADE, LOSAL, HISAL)  
values (2, 1201, 1400);  
insert into SALGRADE (GRADE, LOSAL, HISAL)  
values (3, 1401, 2000);  
insert into SALGRADE (GRADE, LOSAL, HISAL)  
values (4, 2001, 3000);  
insert into SALGRADE (GRADE, LOSAL, HISAL)  
values (5, 3001, 9999);  


select * from DEPT;

select * from emp;

select * from SALGRADE;  

select * from BONUS;  

12.单表查询

-- 对emp表查询:
select * from emp; -- *代表所有数据
-- 显示部分列:
select empno,ename,sal from emp;
-- 显示部分行:where子句
select * from emp where sal > 2000;
-- 显示部分列,部分行:
select empno,ename,job,mgr from emp where sal > 2000;

-- 起别名:
select empno 员工编号,ename 姓名,sal 工资 from emp; -- as 省略,''或者""省略了
-- as alias 别名
select empno as 员工编号,ename as 姓名,sal as 工资 from emp;
select empno as '员工编号',ename as "姓名",sal as 工资 from emp;
-- > 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '编号,ename as "姓 名",sal as 工资 from emp' at line 1
-- 错误原因:在别名中有特殊符号的时候,''或者""不可以省略不写
select empno as 员工 编号,ename as "姓 名",sal as 工资 from emp;

-- 算术运算符:
select empno,ename,sal,sal+1000 as '涨薪后',deptno from emp where sal < 2500;
select empno,ename,sal,comm,sal+comm from emp;  -- ???null和0不一样,null+任何值=null事实上不应该

-- 去重操作:
select job from emp;
select distinct job from emp;
select job,deptno from emp;
select distinct job,deptno from emp; -- 对后面的所有列组合 去重 ,而不是单独的某一列去重

-- 排序:
select * from emp order by sal; -- 默认情况下是按照升序排列的
select * from emp order by sal asc; -- asc 升序,可以默认不写
select * from emp order by sal desc; -- desc 降序
select * from emp order by sal asc ,deptno desc; -- 在工资升序的情况下,deptno按照降序排列

13.where子句

-- 查看emp表:
select * from emp;

-- where子句:将过滤条件放在where子句的后面,可以筛选/过滤出我们想要的符合条件的数据:
-- where 子句 + 关系运算符
select * from emp where deptno = 10;
select * from emp where deptno > 10;
select * from emp where deptno >= 10;
select * from emp where deptno < 10;
select * from emp where deptno <= 10;
select * from emp where deptno <> 10; -- 跟下面的不等于一样
select * from emp where deptno != 10;
select * from emp where job = 'CLERK'; 
select * from emp where job = 'clerk'; -- 默认情况下不区分大小写 
select * from emp where binary job = 'clerk'; -- binary区分大小写
select * from emp where hiredate < '1981-12-25';

-- where 子句 + 逻辑运算符:and 

select * from emp where sal > 1500 and sal < 3000;  -- (1500,3000)
select * from emp where sal > 1500 && sal < 3000; 
select * from emp where sal > 1500 and sal < 3000 order by sal;
select * from emp where sal between 1500 and 3000; -- [1500,3000]


-- where 子句 + 逻辑运算符:or

select * from emp where deptno = 10 or deptno = 20;
select * from emp where deptno = 10 || deptno = 20;
select * from emp where deptno in (10,20); -- 这个的意思是 集合,看下面就知道了。集合元素就是10和20
select * from emp where job in ('MANAGER','CLERK','ANALYST');


-- where子句 + 模糊查询:
-- 查询名字中带A的员工  -- %代表任意多个字符 0,1,2,.....
select * from emp where ename like '%A%' ;
-- -任意一个字符
select * from emp where ename like '__A%' ;


-- 关于null的判断:
select * from emp where comm is null;
select * from emp where comm is not null;

select * from emp where job = 'SALESMAN' or job = 'CLERK' and sal >=1500; -- 先and再or  and > or
select * from emp where job = 'SALESMAN' or (job = 'CLERK' and sal >=1500); 
select * from emp where (job = 'SALESMAN' or job = 'CLERK') and sal >=1500;

14. 单行多行函数

-- 函数举例:
select empno,ename,lower(ename),upper(ename),sal from emp;
-- 函数的功能:封装了特定的一些功能,我们直接拿过来使用,可以实现对应的功能
-- 函数作用:为了提高select的能力
-- 注意:函数没有改变数据自身的值,而是在真实数据的上面进行加工处理,展示新的结果而已。

select max(sal),min(sal),count(sal),sum(sal),avg(sal) from emp;
-- 函数的分类:
-- lower(ename),upper(ename) :改变每一条结果,每一条数据对应一条结果  -- 单行函数
-- max(sal),min(sal),count(sal),sum(sal),avg(sal):多条数据,最终展示一个结果  -- 多行函数

-- 单行函数包含:
-- 1.字符串函数
select ename,length(ename),substring(ename,2,3) from emp;
-- substring字符串截取,2:从字符下标为2开始,3:截取长度3    (下标从1开始)
-- 2.数值函数
select abs(-5),ceil(5.3),floor(5.9),round(3.14) from dual; -- dual实际就是一个伪表 
select abs(-5) 绝对值,ceil(5.3) 向上取整,floor(5.9) 向下取整,round(3.14) 四舍五入;  -- 如果没有where条件的话,from dual可以省略不写
select ceil(sal) from emp;
select 10/3,10%3,mod(10,3) ;
-- 3.日期与时间函数 
select * from emp;
select curdate(),curtime() ; -- curdate()年月日 curtime()时分秒
select now(),sysdate(),sleep(3),now(),sysdate() from dual; -- now(),sysdate() 年月日时分秒
-- now()与sysdate的差异:睡3秒后,now()不更新,sysdate()更新,这是因为sysdate()是函数执行的时间

insert into emp values (9999,'lili','SALASMAN',7698,now(),1000,null,30);
-- now()可以表示年月日时分秒,但是插入数据的时候还是要参照表的结构的
desc emp;

-- 4.流程函数
-- if相关
select empno,ename,sal,if(sal>=2500,'高薪','低薪') as '薪资等级' from emp; -- if-else 双分支结构
select empno,ename,sal,comm,sal+ifnull(comm,0) from emp; -- 如果comm是null,那么取值为0 -- 单分支
select nullif(1,1),nullif(1,2) from dual; --  如果value1等于value2,则返回null,否则返回value1  
-- case相关:
-- case等值判断
select empno,ename,job,
case job 
 when 'CLERK' then '店员'
 when 'SALESMAN'  then '销售'
 when 'MANAGER' then '经理'
 else '其他'
end '岗位',
sal from emp;

-- case区间判断:
select empno,ename,sal,
case 
 when sal<=1000 then 'A'
 when sal<=2000 then 'B'
 when sal<=3000 then 'C'
 else 'D'
end '工资等级',
deptno from emp;


-- 5.JSON函数  

-- 6.其他函数
select database(),user(),version() from dual;

-- 7.多行函数(1-6都是单行函数)
select max(sal),min(sal),count(sal),sum(sal),sum(sal)/count(sal),avg(sal) from emp;
select * from emp;
-- 多行函数自动忽略null值
select max(comm),min(comm),count(comm),sum(comm),sum(comm)/count(comm),avg(comm) from emp;
-- max(),min(),count()针对所有类型   sum(),avg() 只针对数值型类型有效
select max(ename),min(ename),count(ename),sum(ename),avg(ename) from emp;

-- count --计数   
-- 统计表的记录数:方式1:
select * from emp;
select count(ename) from emp;
select count(*) from emp;

-- 统计表的记录数:方式2
select 1 from dual;
select 1 from emp;
select count(1) from emp;

15. group by 和 having

select * from emp;
select deptno from emp;
select avg(sal) from emp;

select deptno,avg(sal) from emp;-- 不科学!

select deptno,avg(sal) from emp group by deptno; -- 字段和多行函数不可以同时使用,除非这个字段属于分组
select deptno,avg(sal) from emp group by deptno order by deptno desc; -- 还可以加个排序

-- 统计各个岗位的平均工资
select job,avg(sal) from emp group by job;
select job,lower(job),avg(sal) from emp group by job;


-- 统计各个部门的平均工资 ,只显示平均工资2000以上的  - 分组以后进行二次筛选 having
select deptno,avg(sal) from emp group by deptno having avg(sal) > 2000;
select deptno,avg(sal) 平均工资 from emp group by deptno having 平均工资 > 2000;
select deptno,avg(sal) 平均工资 from emp group by deptno having 平均工资 > 2000 order by deptno desc;
-- 统计各个岗位的平均工资,除了MANAGER
-- 方法1:
select job,avg(sal) from emp where job != 'MANAGER' group by job;
-- 方法2:
select job,avg(sal) from emp group by job having job != 'MANAGER' ;
-- where在分组前进行过滤的,having在分组后进行后滤。

小结1-单表查询总结

  • select column, group_function(column) from table [where condition] [group by group_by_expression] [having group_condition] [order by column]; 顺序固定,不可以改变顺序。

  • 执行顺序:from–where – group by– select - having- order by

  • 小练习:

select * from emp;
select * from dept;

select job , min(sal) from emp where sal<2000 group by job;
select job , min(sal) from emp group by job having min(sal)<2000;

select job , deptno, avg(sal) from emp group by job,deptno having avg(sal)>1200 order by deptno;

select deptno,count(deptno),avg(sal) from emp group by deptno having count(deptno)<4 order by deptno;

select deptno,max(sal) from emp group by deptno having max(sal)>=3000 order by deptno;

16. 多表查询-内连接

-- 多表查询 :
-- 1.交叉连接:cross join
select * from emp
cross join dept; -- 14*4 = 56条 笛卡尔乘积 : 没有实际意义,有理论意义, 不常用。

select * from emp
join dept; -- cross 可以省略不写,mysql中可以,oracle中不可以


-- 2.自然连接:natural join 
-- 优点:自动匹配所有的同名列 ,同名列只展示一次 ,简单
select * 
from emp
natural join dept;

select empno,ename,sal,dname,loc 
from emp
natural join dept;

-- 缺点: 查询字段的时候,没有指定字段所属的数据库表,效率低
-- 解决: 指定表名:
select emp.empno,emp.ename,emp.sal,dept.dname,dept.loc,dept.deptno
from emp
natural join dept;

-- 缺点:表名太长
-- 解决:表起别名
select e.empno,e.ename,e.sal,d.dname,d.loc,d.deptno
from emp e
natural join dept d;

-- 自然连接 natural join 缺点:自动匹配表中所有的同名列,但是有时候我们希望只匹配部分同名列:
-- 解决: 3.内连接 - using子句:
select *
from emp e
inner join dept d -- inner可以不写 。-- 这里不能写natural join了 ,这里是内连接
using (deptno) -- 记得写括号,虽然不咋用这个using就是了

-- using缺点:关联的字段,必须是同名的 
-- 解决: 内连接 - on子句:
select * 
from emp e
inner join dept d
on (e.deptno = d.deptno);

-- 多表连接查询的类型: 1.交叉连接  cross join  2. 自然连接  natural join  
-- 3. 内连接 - using子句   4.内连接 - on子句
-- 综合看:内连接中, on子句用得最多。

select * 
from emp e
inner join dept d
on (e.deptno = d.deptno)
where sal > 3500; -- 还能再加一个where子句!

-- 条件:
-- 1.筛选条件  where  having
-- 2.连接条件 on,using,natural 
-- SQL99语法 :筛选条件和连接条件是分开的

-- inner join - on子句: 显示的是所有匹配的信息(不匹配的完全没显示出来。)
select * 
from emp e
inner join dept d
on e.deptno = d.deptno;


17.多表查询-外连接

select * from emp;
select * from dept;
-- 问题:
-- 1.40号部分没有员工,没有显示在查询结果中
-- 2.员工scott没有部门,没有显示在查询结果中

-- 外连接:除了显示匹配的数据之外,还可以显示不匹配的数据

-- 左外连接: left outer join   -- 左面的那个表的信息,即使不匹配也可以查看出效果
select * 
from emp e
left outer join dept d
on e.deptno = d.deptno;



-- 右外连接: right outer join   -- 右面的那个表的信息,即使不匹配也可以查看出效果
select * 
from emp e
right outer join dept d
on e.deptno = d.deptno;

-- 全外连接  full outer join -- 这个语法在mysql中不支持,在oracle中支持 -- 展示左,右表全部不匹配的数据 
-- scott ,40号部门都可以看到
select * 
from emp e
full outer join dept d
on e.deptno = d.deptno;


-- 解决mysql中不支持全外连接的问题:

select * 
from emp e
left outer join dept d
on e.deptno = d.deptno
union -- 两个之间加了一个union,表示两张表的合在一起,数据的并集,去重(此处指完全匹配的重复去掉)。效率低
select * 
from emp e
right outer join dept d
on e.deptno = d.deptno;

select * 
from emp e
left outer join dept d
on e.deptno = d.deptno
union all-- 加了一个 all 并集 不去重 效率高
select * 
from emp e
right outer join dept d
on e.deptno = d.deptno;

-- mysql中对集合操作支持比较弱,只支持并集操作,交集,差集不支持(oracle中支持)
-- outer可以省略不写

18.多表联查

-- ☆三表连查
-- 查询员工的编号、姓名、薪水、部门编号、部门名称、薪水等级
select * from emp;
select * from dept;
select * from salgrade;


select e.ename,e.sal,e.empno,e.deptno,d.dname,s.* from emp e 
right outer join dept d on e.deptno = d.deptno -- 外连接是因为 可能存在deptno为空但是要连起来放出来的情况。此处e.xxx=y.lll,字段名称可以是不同的。
inner join salgrade s on e.sal between s.losal and s.hisal; -- 内连接是因为不存在salgrade为空。就可以直接连起来。
-- 但是需要加一个on子句,而不是用交叉连接、自然连接或using
-- 为什么?交叉连接肯定不对。自然连接查了相同字段发现没有,又变成交叉连接,肯定也不对。using是只查指定字段,但是本来就没有相同的,所以也不对。最后就剩on子句。刚刚提到on子句是因为俩不重名,用on e.xxx=y.lll解决了,其实on就是一个条件。

19.自关联

-- 查询员工的编号、姓名、上级编号,上级的姓名
select * from emp;

select e1.empno 员工编号,e1.ename 员工姓名,e1.mgr 领导编号,e2.ename 员工领导姓名
from emp e1
inner join emp e2
on e1.mgr = e2.empno;

-- 左外连接:(为了避免没有领导的员工不在这张大表中显示的情况。)
select e1.empno 员工编号,e1.ename 员工姓名,e1.mgr 领导编号,e2.ename 员工领导姓名
from emp e1
left outer join emp e2
on e1.mgr = e2.empno;

注:92语法比此处99语法少了很多内置的连接类型,但大部分都可以通过where进行手动限制。

20.单行子查询

-- 单行子查询:
-- 查询工资高于平均工资的雇员名字和工资。
select ename,sal from emp where sal > (select avg(sal) from emp); -- 因为后面这个不是定值,也得查出来。后面这个查出来是一个值,所以叫“单行”

-- 查询和CLARK同一部门且比他工资低的雇员名字和工资。
select ename,sal from emp where deptno = (select deptno from emp where ename = 'CLARK') 
and 
sal < (select sal from emp where ename = 'CLARK');

-- 查询职务和SCOTT相同,比SCOTT雇佣时间早的雇员信息  
select * from emp where job = (select job from emp where ename = 'SCOTT') 
and 
hiredate < (select hiredate from emp where ename = 'SCOTT');


21.多行子查询

-- 多行子查询:
-- 【1】查询【部门20中职务同部门10的雇员一样的】雇员信息。
-- 查询雇员信息
select * from emp;
-- 查询部门20中的雇员信息
select * from emp where deptno = 20;-- CLERK,MANAGER,ANALYST
-- 部门10的雇员的职务:
select job from emp where deptno = 10; -- MANAGER,PRESIDENT,CLERK
-- 查询部门20中职务同部门10的雇员一样的雇员信息。
select * from emp 
where deptno = 20 
and job in (select job from emp where deptno = 10)
-- > Subquery returns more than 1 row
select * from emp 
where deptno = 20 
and job = any(select job from emp where deptno = 10)


-- 【2】查询工资比所有的“SALESMAN”都高的雇员的编号、名字和工资。
-- 查询雇员的编号、名字和工资
select empno,ename,sal from emp
-- “SALESMAN”的工资:
select sal from emp where job = 'SALESMAN'
-- 查询工资比所有的“SALESMAN”都高的雇员的编号、名字和工资。
-- 多行子查询:
select empno,ename,sal 
from emp 
where sal > all(select sal from emp where job = 'SALESMAN');
-- 单行子查询:
select empno,ename,sal 
from emp 
where sal > (select max(sal) from emp where job = 'SALESMAN');


-- 【3】查询工资低于任意一个“CLERK”的工资的雇员信息。  
-- 查询雇员信息
select * from emp;
-- 查询工资低于任意一个“CLERK”的工资的雇员信息
select * 
from emp
where sal < any(select sal from emp where job = 'CLERK')
and job != 'CLERK'

-- 单行子查询:
select * 
from emp
where sal < (select max(sal) from emp where job = 'CLERK')
and job != 'CLERK'



22.相关子查询

-- 相关子查询不能先运行子句再运行前面那句,因为本身是相关的。
select * from emp e where sal = (select max(sal) from emp where deptno = e.deptno) order by deptno

-- 练习:查询工资高于其所在岗位平均工资的员工(相关子查询)
select ename 姓名,job 岗位, sal 工资 , (select avg(sal) from emp where job = e.job) 平均工资  from emp e where sal >= (select avg(sal) from emp where job = e.job) order by deptno;-- 等号是怕一个部门只有一个人


23.事务

-- 创建账户表:
create table account(
        id int primary key auto_increment,
        uname varchar(10) not null,
        balance double
);

-- 查看账户表:
select * from account;
-- 在表中插入数据:
insert into account values (null,'丽丽',2000),(null,'小刚',2000);

-- 丽丽给小刚 转200元:
update account set balance = balance - 200 where id = 1;
update account set balance = balance + 200 where id = 2;
-- 默认一个DML语句是一个事务,所以上面的操作执行了2个事务。

update account set balance = balance - 200 where id = 1;
update account set balance = balance2 + 200 where id = 2;

-- 必须让上面的两个操作控制在一个事务中:

-- 手动开启事务:
start transaction;

update account set balance = balance - 200 where id = 1;
update account set balance = balance + 200 where id = 2;

-- 手动回滚:刚才执行的操作全部取消:
rollback;
-- 手动提交:
commit;

-- 在回滚和提交之前,数据库中的数据都是操作的缓存中的数据,而不是数据库的真实数据

事务的并发问题:脏读(感觉是读了缓存)、不可重复读(需锁一行)、幻读(需锁表)
解决并发问题的4种手段(事务隔离级别)。

-- 查看默认的事务隔离级别  MySQL默认的是repeatable read  
select @@transaction_isolation;  
-- 设置事务的隔离级别   (设置当前会话的隔离级别)
set session transaction isolation level read uncommitted;  
set session transaction isolation level read committed;  
set session transaction isolation level repeatable read;  
set session transaction isolation level serializable;  

start transaction ;
select * from account where id = 1;

http://www.kler.cn/a/18503.html

相关文章:

  • 类文件结构详解
  • 三菱QD77MS定位模块速度更改功能
  • 系统架构师2023版:习题
  • 书生实战营第四期-基础岛第四关-InternLM + LlamaIndex RAG 实践
  • 硬件基础06 滤波器——无源、有源(含Filter Solutions、Filter Pro、MATLAB Fdatool)
  • 论文阅读笔记:Depth Pro: Sharp Monocular Metric Depth in Less Than a Second
  • TCP四次挥手
  • Linux网络——Shell编程之数组
  • 天猫数据分析:2023年Q1天猫净水器品牌销售TOP10排行榜
  • 3. SQL底层执行原理详解
  • MVC分部视图的使用:Html.Partial/RenderPartial,Html.Action/RenderAction,RenderPage
  • 硬盘数据突然消失怎么回事?硬盘数据突然消失怎么找回
  • 【运动规划算法项目实战】八叉树地图(附ROS C++代码)
  • 如何用100天彻底学会Python?
  • JavaScript class和继承的原理
  • 【Queue新技法】用双数组实现一个队列 C++
  • C++类和对象(上)
  • 华为OD机试真题 Java 实现【猜字谜】【2023Q2】
  • Adobe考试
  • 【MySQL】索引
  • 字节跳动发放年终奖,远超预期~
  • 将sublime中的自定义代码片段snippet 转为vscode可用的代码片段 (cursor可用)
  • Java笔记_17(异常、File)
  • uboot 启动内核代码分析
  • C++结构体分别在:栈空间、堆空间、静态存储区中初始化
  • 【计算机专业漫谈】【计算机系统基础学习笔记】W2-2-1 原码和移码表示