博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

sql--oracle

Posted on 2023-03-01 13:42  马里奥--  阅读(40)  评论(0)    收藏  举报

SQL

SQL 是 Structured Query Language(结构化查询语言)的首字母缩写词,SQL 是数据库语言,通过 SQL可以实现与 Oracle 服务器的通信。可以执行CRUD等操作。

 

注:CRUD是指增加(Create)、检索(Retrieve)、更新(Update)和删除(Delete)

 

SQL分类

DDL(Data Definition Language):数据定义语言,用来定义表、列等;

如:创建数据表...

 

DML(Data Manipulation Language):数据操作语言,用来定义数据库记录(数据);

如:添加数据,修改数据,删除数据

 

DQL(Data Query Language):数据查询语言,用来查询记录(数据)。

如:查询数据

 

DTL (Data  Transaction  Language):数据事务语言,用来操作事务。

如:开启事务,提交事务

DCL (Data Control Language):数据控制语言。用来操作用户和权限

如:创建用户,授权。

一文搞懂什么是事务 - 知乎 (zhihu.com)

 

其中  总是会说增删改查   在分类中 为什么要将查询和增删改分成两部分那?

 

 

1.简单查询

1.简单查询语句的语法

select 列名,列名,...,列名 from 表名;

 

select ... from :它是查询语句的关键字

select后面跟是你要从数据库里取的数据

from后面跟表名,表示你要从哪张中读取这些数据

 

如:

--查询emp表中员工的编号、姓名、工作、工资

select empno,ename,job,sal from emp;

 

--查询emp表中所有列的信息

select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp;

 

如果要查询表中所有列的信息,那么select和from之间的列名可以用*来表示,注意:*号的执行效率比写列名时的执行效率低,(*在执行sql语句时,oracle会去查数据库中的数据字典,查询这个张表都有哪些列,然后查出这张表的所有列的数据)

2.注释

     单行注释:--

     多行注释:以/* 开始,以*/结尾     

 

 

3.sql中的别名

别名语法:

      对象名 as 别名

      对象名  别名

如:

select empno as 员工编号,ename 姓名,job 工作,mgr 上级编号,hiredate 入职日期,sal 工资,comm 佣金,deptno 部门编号 from emp;

 

注意:给表、视图取别名时不能加as

select e.* from emp e; --select * from emp;

select e.empno,e.ename,e.job,e.sal from emp e;

 

select emp.empno,emp.ename,emp.job,emp.sal from emp;

 

4.带条件的查询

 

select 列名,列名,...,列名 from 表名 where 条件表达式;

 

where:条件关键字,后面跟条件表达式,这个条件一般是和数据库中列相关

 

条件表达式:

>

<

>=

<=

!=,<>:表示不等于

=

--查询工资大于1500的员工信息

select * from emp where sal>1500;

--查询名字叫SMITH的员工的信息

select * from emp where ename='SMITH';

 

说明:在oracle数据库中,数字类型直接写就可以,字符串类型的数据要用单引号括起来

 

--查询不是10号部门的员工的信息

select * from emp where deptno!=10;

select * from emp where deptno<>10;

 

 

in:后面跟一个集合或者子查询

oracle中表示一个简单的集合 ,(元素,元素,元素,... 元素) 例如 (1,2,3,4,5)  ('a','b','c','d')

--查询emp表中,工资是800,1600,或者3000的员工信息

 

select * from  emp  where sal in(800,1600,3000);

 

not in:和in是相反的

select * from  emp  where sal not in(800,1600,3000);

 

 

like:它只用在字符串列,表示对字符串进行模糊匹配

     有两个点位符:

           %:表示在这个%出现的地方可以有0个或者多个字符

           _: 表示在_出现的地方有且只能一个任意字符

 

--查询员工姓名S结尾的员工信息

select * from emp where ename like '%S';

 

--查询emp表中员工姓名的第二个字符是L的员工信息

select * from emp where ename like '_L%';

 

--查询emp表中员工姓名第三个字符是A的员工信息

select * from emp where ename like '__A%';

 

--查询员工姓名中有S的员工信息

select * from emp where ename like '%S%';

 

not like:和like相反

--查询名字中没有S的员工信息

select * from emp swhere ename not like '%S%';

 

 

insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(7311,'qer_q%oasf','etl',7369,sysdate,3000,200,null);

 

like中的转义字符:\

在新版的oracle中,使用转义字符需要手动去定义 定义  escape '\'

转义字符,它会把紧跟在它后面的字符当作一个普通的字符去处理

select * from emp where ename like '%\_%' escape '\';

 

select * from emp where ename like '___\_%' escape '\';

 

select * from emp where ename like '%a%%'  escape 'a';

 

all、any:后面都跟一个集合或者子查询

>all:表示大于集合中最大的元素  >all(1,2,3,4,5) 等价于 >5

<all:表示小于集合中最小的元素  <all(1,2,3,4,5) 等价于 <1

>any:表示大于集合中最小的元素  >any(1,2,3,4,5) 等价于 >1

<any:表示小于集合中最大的元素  <any(1,2,3,4,5) 等价于 <5

--查询员工信息,要求员工的工资比以下的值都低 1600,2000,3000

select * from emp where sal <all(1600,2000,3000);

 

--查询比下任意一个(1600,2000,3000)工资高的员工信息

select * from emp where sal>any(1000,2000,3000);

 

--查询工资比所有人(1600,2000,3000)都高的员工信息

select * from emp where sal > all(1600,2000,3000);

 

exists:它不和任何列一起使用,后面跟的是一个子查询(查询语句select语句),如果子查询能查出结果,那么这个条件就是成立的,查不出结果条件不成立

not exists:和exists相反

 

select * from emp where exists(select * from emp where 1=0);

 

select * from emp where exists(select * from emp);

 

 

条件连接符

and:表示并且,当and连接的两个条件同时成立时,总条件才算成立,只要有一个条件不成立,整体不成立

or:表示或者,当or连接的两个条件有一个条件成立,整体条件成立,只有两个条件都不成立时,整体才不成立

between value1 and value2:value1的值比value2值小,value1和value2一般是数字类型,还可以是日期,表示值在value1和value2之间

         它的取值是包含value1和value2的。

--查询10号部门,工资大于1000的员工信息

select * from emp where deptno=10 and sal>1000;

 

 

--查询10号部门,或者工资小于2000的员工信息

select * from emp where deptno=10 or sal<2000;

 

--查询工资在1000到3000之间的员工信息

select * from emp where sal>=1000 and sal<=3000;

 

select * from emp where sal between 1000 and 3000;

 

--查询工资大于1000并且小于3000的员工信息

select * from emp where sal>1000 and sal<3000;

 

select * from emp where sal between 1000 and 3000 and sal!=1000 and sal!=3000;

 

is null:表示这个值是空时条件成立

is not null:表示值不为空间条件成立

 

select * from emp where comm is null;

 

select * from emp where comm is not null;

 

dual表:它是oracle内置的一个单行表,

 

select 1 from dual;

select 'abc' from dual;

select 2*3 from dual;

select 1,2,3,4 from dual;

 

select 1 from emp;

--查询员工的年薪

select sal*12 from emp;

 

 

 

2.排序分组

1.排序

select 列名,列名,..,列名 from 表名 where 条件表达式 order by 排序列的列名 asc|desc;

 

asc|desc: asc表示升序,desc表示降序

 

--查询员工信息,按照员工的工资升序排序

select * from emp order by sal asc;  ---如果是升序排序,asc可以省略

select * from emp order by sal;

 

--查询员工信息,按照员工编号降序排序

select * from emp order by empno desc;

 

 

order by :后面可以跟多个排序列,跟多个排序列时,

它的含义:按照第一排序列(紧跟前order by 关键字的列)排序,

如果第一个排序字段的值相同时,它会按照第二个排序字段进行排序

 

--查询员工信息,按照部门编号升序排序,如果部门编号相同时,按照工资的升序排序

 

select * from emp order by deptno asc,sal asc;

 

--查询员工信息,按照部门编号降序排序,如果部门编号相同,按照员工编号升序排序

 

select * from emp order by deptno desc,empno;

 

--查询员工的编号、姓名、工作、工资、部门编号,按照部门编号升序排序,如果部门相同时,按照工资降序排序

select empno,ename,job,sal,deptno from emp order by deptno,sal desc;

 

注意:order by 后面除了可以跟表中的列名外,还可以跟select 和from之间查询结果的序号

select empno,ename,job,sal,deptno from emp order by 5,4 desc;

 

select empno,sal,job,ename,deptno from emp order by 5,2 desc;

 

2.聚合函数

聚合函数:对一组值执行计算,并返回单个值

count(列名|*|常数):它求记录数(数据条数)

max(列名):取最大值

min(列名):取最小值

avg(列名):取平均值

sum(列名):求和

 

--查询员工表中的员工人数

select count(empno) from emp;

select count(*) from emp;

select count(1) from emp;

 

count(主键列或索引列)

count(*)

count(常数)

count(普通列)

它们执行效率从上到下,依次降低

 

--查询emp表中的部门数

select count(deptno) from emp;

select deptno from emp;

 

distinct:去重关键字,跟在列的最前面

select distinct deptno from emp;

 

select count(distinct deptno) from emp;

 

 

select empno,distinct deptno from emp;  --这个sql语句是错误的

 

select distinct empno,deptno from emp;  

 

注意:distinct后面跟多个列时,判断重复数据,所有列的值完全相同时,它才会认为是重复数据

 

--查询工资总和

select sum(sal) from emp;

 

--查询员工的平均工资

select avg(sal) from emp;

 

--查询10号部门的最高工资

select max(sal) from emp where deptno=10;

 

--查询最低工资

select min(sal) from emp;

 

 

3.分组

 

select 列名,列名,...,列名 from 表名

where 条件

group by 分组列

order by 排序列 asc|desc

 

group by:分组的关键字,后面跟分组列名,可以是一个分组列,也可以是多个列

 

 

--查询各个部门的部门编号和部门的平均工资

select deptno,avg(sal) from emp group by deptno;

 

select empno,min(sal),max(sal),avg(sal),sum(sal),count(*)  from emp group by empno;

 

 

--查询各个部门的员工人数

select deptno,count(empno) from emp group by deptno;

 

select job,deptno,count(*) from emp group by job,deptno;

注意:group by 后面跟多个列时,只有当多个列的值同时相等时,它才会分为同一个组;

 

 

4.having

select col_name,col_name,...,col_name

from 表名

where 条件

group by 分组列

having 条件

order by 排序列

 

having:它是对分组后的数据进行筛选,条件表达式中可以使用聚合函数

 

 

--查询各个部门的部门编号和部门的平均工资

select deptno,avg(sal) from emp group by deptno;

 

--求平均工资大于2000的部门编号和平均工资

select deptno,avg(sal) from emp group by deptno having avg(sal)>2000;

 

where和having的异同

where:条件,where后面跟的条件比having后的条件先执行,条件中不允许使用聚合函数。

having:条件中可以使用聚合函数,一般having和group by联用。

 

 

3. 集合、联合查询

1.集合

集合:每一个sql查询的结果就是一个集合

(1,3,4,65,234,123,12)

 

select * from emp;

 

并集:取两个集合中所有元素

union all:表示取两个集合的并集,不删除重复元素

union :取两个集合的并集,删除重复的元素

 

--查询员工工资大于1000的员工信息

select * from emp where sal>1000;

 

--查询员工工资小于3000的员工信息

select * from emp where sal<3000;

 

select * from emp where sal>1000

union all

select * from emp where sal<3000;

 

 

select * from emp where sal>1000

union

select * from emp where sal<3000;

 

union、union all:union all执行效率高,union执行效率低(先进行union all把两个集合合并,之后对合并后的数据进行排序,去掉重复元素)

 

交集:取两个集合重叠部分的元素

intersect:表示交集

--查询工资在1000到3000之间的员工信息

 

select * from emp where sal>1000 and sal<3000;

 

select * from emp where sal>1000

intersect

select * from emp where sal<3000;

 

差集:第一个集合的所有元素减去两个集合重叠部分的元素

Minus::表示差集

 

 

select * from emp where sal>1000

minus

select * from emp where sal<3000;

 

select * from emp where sal>=3000;

 

 

select * from emp where sal<3000

minus

select * from emp where sal>1000;

 

select * from emp where sal<=1000;

 

集合运算,关键字前后的两个sql表示的结果集要完全相同,

 

select ename,job from emp

union all

select ename,job from emp;

 

2.联合查询

交叉连接(笛卡尔积连接)、内连接、自连接、外连接(全连接、左外连接、右外连接)、自然连接

 

(1)交叉连接(笛卡尔积连接)

将会返回被连接的两个表的笛卡尔积,返回结果的行数等于两个表行数的乘积.

语法:

select 列名,列名,...

from a表  cross join b表;

 

select * from emp;

select * from dept;

 

select e.*,d.deptno dno,d.dname,d.loc from emp e cross join dept d;

 

select e.*,d.deptno dno,d.dname,d.loc from emp e,dept d;

 

 

(2)内连接

内连接:是把两个表中符合条件的数据连接为一条数据,如果哪个表中存在不符合连接条件的数据,那么这些数据就会被过滤掉(不显示)

语法:

select 列名,...,列名

from a表  inner join b表  on 连接条件

 

inner join:中的inner可以省略不写

 

--查询员工信息及他的部门信息

select e.*,d.* from emp e inner join dept d on e.deptno=d.deptno;

 

select e.*,d.* from emp e join dept d on e.deptno=no;

 

select e.*,d.* from emp e,dept d where e.deptno=d.deptno;

 

 

3)自连接

自连接是一个特殊的内连接,内连接一般是两个表的连接,自连接将一个表和它自已进行连接

 

--查询员工信息,并显示它的上级姓名

select e1.*,e2.ename 上级姓名 from emp e1 join emp e2 on e1.mgr=e2.empno

 

select e1.*,e2.ename from emp e1,emp e2 where e1.mgr=e2.empno;

 

(4)不等连接

不等连接:连接条件是不等条件,(大于、小于、不等于)

--查询员工信息,并显示员工的工资等级

 

select * from salgrade;

 

select e.*,s.grade,s.losal,s.hisal from emp e join salgrade s on e.sal between s.losal and s.hisal;

 

 

(5) 全连接

全连接:它会查出两个表中的所有数据,

 1.如果两个表中的数据都符合连接条件,那么它会和内连接一样,将符合条件的数据连接为一条记录

 2.如果第一表中的一条数据,在第二张表中没有找到和它对应的记录(第二张表没有和第一张表这条数据符合连接条件),

 那么它同样会显示第一张表的这条记录,同时它对应的第二张表数据的位置会显示为空

 3.同理,如果第二张的一条记录,在第一张表中没有找到符合连接条件的数据,那么同样会显示,在显示第一张表数据的位置显示为空

 

语法:

select 列名,列名,列名,....

from 表A full outer join 表B on 连接条件;

 

full outer join :中的outer可以省略

 

 

--查询所有部门和员工信息

 

select e.*,d.* from emp e full outer join dept d on e.deptno=d.deptno;

(6)左外连接

语义:查出左表(left outer join关键字前面的表)的所有数据,根据连接条件去右表中找对应的数据

     如果找到变显示出来,如果找不到就显示空

     

--查询所有部门信息,以及各部门下的员工信息

select 列名,列名,...

from 表A left outer join 表B on 连接条件

 

left outer join :其中outer可以省略

 

select d.*,e.* from dept d left join emp e on d.deptno=e.deptno;

 

select d.*,e.* from dept d,emp e where d.deptno=e.deptno(+);

 

注意:用(+)表示的左连接或者右连接,如果是左连接,那么符号加在右表的关系列上,如果是右连接,那么符号加在左表的关系列上

--左连接

select d.*,e.* from dept d,emp e where e.deptno(+)=d.deptno;

--右连接

select d.*,e.* from dept d,emp e where d.deptno(+)=e.deptno;

 

 

(7)右外连接

语义:它会查出右表的所有数据,根据连接条件去左表查找对应的数据,如果找到就显示,如果找不到就显示为空语法:

select 列名,列名,列名,...

from 左表 right outer join 右表 on 连接条件

 

right outer join:其中outer可以省略

 

--查询员工信息,并显示它的部门信息

select d.*,e.* from dept d right outer join emp e on d.deptno=e.deptno;

 

select d.*,e.* from dept d,emp e where d.deptno(+) = e.deptno;

 

 

8)自然连接

   自然连接是在两张表中寻找那些数据类型和列名都相同的字段,

然后自动地将他们连接起来,并返回所有符合条件按的结果。     

语法:

 

   select col_name,col_name,...

   from table_a natural join table_b;

   

  select col_name,....

   from table_a natural join table_b

   using(关系列)

 

select * from emp natural join dept;        --自然连接

 

select * from emp join dept using(deptno); --自然连接using用来指定关系列

 

4.子查询

子查询指一个查询语句嵌套在另一个查询语句内部的查询

1.from后面的子查询

--查询员工的姓名和他上级的姓名

select e.*, e2.empno, e2.ename mname, e2.job, e2.sal, e2.deptno

from emp e, emp e2

where e.mgr = e2.empno(+);

 

select e.empno,

       e.ename,

       e.job,

       e.mgr,

       e.hiredate,

       e.sal,

       e.comm,

       e.deptno,

       d.empno,

       d.ename,

       d.job,

       d.mgr,

       d.hiredate,

       d.sal,

       d.comm,

       d.deptno

from emp e,emp d

where e.mgr=d.empno;

 

 

select ename, mname

  from (select e.*, d.empno, d.ename mname, d.job, d.sal, d.deptno

          from emp e, emp d

         where e.mgr = d.empno(+));

 

2.where后面的子查询

(1)单行子查询

单行子查询:子查询的sql语句只查出一条记录

--查询工资大于10号部门平均工资的员工信息

--查询10号部门的员工平均工资

select avg(sal) from emp where deptno=10;

 

select * from emp where sal>(select avg(sal) from emp where deptno=10);

 

(2)多行子查询

多行子查询:子查询的sql语句查出若干条记录

in、not in、exists、not exists、all、any

 

--查询工资比20号部门所有人工资都高的员工信息

1)用单选子查询来完

 --查询20号部门的最高工资

 select max(sal) from emp where deptno=20;

 

 select * from emp where sal>( select max(sal) from emp where deptno=20);

2)>all

--20号部门的员工工资是一个集合

select sal from emp where deptno=20;

 

select * from emp where sal>all(select sal from emp where deptno=20);

 

3.existsnot exists

--查询有员工的部门信息

select * from dept;

--根据部门编号查询员工人数

select count(*) from emp where deptno=10;

 

select * from dept d where (select count(*) from emp where deptno=d.deptno)!=0;

 

exists:后面跟子查询,如果子查询能查出数据,那么条件是真的,如果子查询查不出结果,条件不成立

 

select * from dept d where exists(select * from emp where deptno=d.deptno);

 

--查询没有有员工的部门信息

select * from dept d where not exists(select * from emp where deptno=d.deptno);

 

 

 

4.having后面的子查询

 

--查询各个部门的部门编号和员工人数,要求部门的平均工资大于30号部门的平均工资

select deptno,count(*),avg(sal) from emp group by deptno having avg(sal)>1500;

 

--查询30号部门的平均工资

select avg(sal) from emp where deptno=30;

 

select deptno,count(*) from emp group by deptno having avg(sal)>(select avg(sal) from emp where deptno=30);

 

5.select from 之间的子查询

 

select empno,ename,(select 1 from dual) from emp;

 

注意:select 和from之间的子查询,子查询的结果只能是单行单列

原始排序:

 

 order by 9;

 

5.分页sql

伪列:rownum 它是oracle数据库内置列,任何表都可以使用,它作用是显示表中数字的行号

 

 

select * from emp;

 

select emp.*,rownum from emp;

 

select t.*,rownum r from (select * from emp order by sal) t;

 

--查询工资最低的5名员工信息

select t.*,rownum r from (select  *  from emp order by sal) t where rownum<=5;

 

--注意如果给伪列加条件,小于一个值是可以,不能让它大于某个值

 

select t.*,rownum r from (select *  from emp order by sal) t where rownum>=2; --伪列不能直接大于一个值

 

select t.*,rownum r from (select  *  from emp order by sal) t where rownum=5;  --伪列不能直接等于一个不等于1的值

 

select t.*,rownum r from (select  *  from emp order by sal) t where rownum=1;  --伪列可以直接等于1

 

使用rownum的分页sql,rownum伪列的序号,只连续的不考虑值相等的情况(值相同序号不相同)

--查询5到10名的员工信息

select * from (select t.*,rownum r from (select * from emp order by sal) t) t2 where t2.r between 5 and 10;--包三层查询

 

row_number():需要和over分析函数联用,排序的序号和rownum伪列相同,连续序号,不考虑值相等的情况(值相同序号不相同)

dense_rank():可以用来做排序,它序号连续,考虑重复数据,如果值相等序号就相同

rank():可以用来做排序,它序号不连续,考虑重复数据,如果值相等序号相同

 

over(partition by 分组列 order by 排序列)over子句中的分组partition by和group by的分组不同,它不会把数据聚合成一条,在over子名中可以省略

 

select e.*,row_number()over(order by sal desc) r from emp e;

 

select e.*,dense_rank()over(order by sal desc) r from emp e;

 

select e.*,rank()over(order by sal desc) r from emp e;

 

select e.*,row_number()over(partition by deptno order by sal desc) r from emp e;

 

select e.*,dense_rank()over(partition by deptno order by sal desc) r from emp e;

 

select e.*,rank()over(partition by deptno order by sal desc) r from emp e;

 

 

使用row_number(),rank(),dense_rank()的分页sql,只需要一层子查询

 

select * from (select e.*,row_number()over(order by sal) r from emp e) t where t.r between 5 and 10;

 

 

6.case when语句

语法:

case

   when 条件表达式1 then

     

   when 条件表达式2 then

     

   when 条件表达式3 then

     

     ...

   else

     默认值

end

 

语义:如果表达式成立,那么整个语句值为表达式,then后面的值,

      如果所有表达式都不成立,会取else后的默认值

      else语句可以省略

select * from student;

 

select count(*) from student where ssex='男';

 

select s.*,(select count(*) from student where ssex='男') 男生人数,(select count(*) from student where ssex='女') 女生人数  from student s;

 

使用case when统计男生人数

select sum(case when ssex='男' then 1 else 0 end) 男生人数,sum(case when ssex='男' then 0 else 1 end) 女生人数,sum(case when ssex='女' then 1 else 0 end) 女生人数 from student s;