SQL中DQL常见面试题以92语法与99语法的分析
1 常见面试题
/*
判断表是否存在的存储过程
*/
declare
numb number;
begin
select count(1) into numb from user_tables where table_name = upper('stu_score');
if numb>0 then
execute immediate 'drop table stu_score';
end if;
end;
/*
创建表的注释
oracle表示整形浮点都是number,而mysql有double,int,bigint,tinyint,float
*/
create table stu_score(
stu_name varchar2(30),
course varchar2(20),
score number(5,2),
primary key(stu_name,course)
);
comment on column stu_score.stu_name is '学生姓名';
comment on column stu_score.course is '学生成绩';
comment on column stu_score.course is '学生课程';
insert into stu_score values('张三','语文',78.98);
insert into stu_score values('张三','数学',88.98);
insert into stu_score values('张三','英语',99.98);
insert into stu_score values('李四','语文',98.98);
insert into stu_score values('李四','英语',100);
insert into stu_score values('李四','数学',88.98);
insert into stu_score values('王二','语文',85.98);
insert into stu_score values('王二','数学',84.98);
insert into stu_score values('王二','英语',90.98);
commit;
-- 用一条SQL查询出每门课程都大于80分的学生姓名
select distinct stu_name from stu_score where stu_name not in (select distinct stu_name from stu_score where score<=80);
/*
双引号:双引号的作用:关键字,对象名、字段名加双引号,则示意 Oracle将严格区分大小写,否则Oracl都默认大写。
单引号:一般表示字符串
*/
-- 行列互换1
select stu_name,
sum(case when course = '语文'then score else 0 end) "语文",
sum(case when course = '数学'then score else 0 end) "数学",
sum(case when course = '英语'then score else 0 end) "英语"
from stu_score group by stu_name;
-- 行列互换2
select stu_name,
sum(decode(course,'语文',score,0)) "语文",
sum(decode(course,'数学',score,0)) "数学",
sum(decode(course,'英语',score,0)) "英语"
from stu_score group by stu_name;
-- 2学生表,删除冗余数据
declare
n number;
begin
select count(1) into n from user_tables where table_name=upper('yp_stu');
if n>0 then
execute immediate 'drop table yp_stu';
end if;
end;
-- 2.1创建学生表
create table yp_stu(
stu_id number(11) primary key,
stu_sno number(11) default 0 not null,
stu_name varchar2(20) default '' not null,
course varchar2(30) default '' not null,
score number(5,3) default 0 not null
);
comment on column yp_stu.stu_id is '自增ID';
comment on column yp_stu.stu_sno is '学号';
comment on column yp_stu.stu_name is '姓名';
comment on column yp_stu.score is '分数';
comment on column yp_stu.course is '课程';
-- 2.2 创建自增序列
create sequence stu_id_sequence
increment by 1
start with 1
nomaxvalue
nocycle
cache 20;
-- 2.3插入数据
insert into yp_stu values(stu_id_sequence.nextval,1,'张三','语文',78.9);
insert into yp_stu values(stu_id_sequence.nextval,2,'李四','语文',78.9);
insert into yp_stu values(stu_id_sequence.nextval,1,'张三','语文',78.9);
insert into yp_stu values(stu_id_sequence.nextval,1,'张三','语文',78.9);
commit;
-- 2.4 删除冗余数据
delete yp_stu where stu_id not in (select min(stu_id) from yp_stu group by stu_sno);
commit;
select * from yp_stu;
-- 3 获取四个球队比赛的所有可能组合
declare
n1 number;
begin
select count(1) into n1 from user_tables where table_name=upper('yp_team');
if n1>0 then
execute immediate 'drop table yp_team';
end if;
end;
-- 创建表
create table yp_team(
team_name varchar2(10)
);
comment on column yp_team.teamname is '球队的名称';
insert into yp_team values('a');
insert into yp_team values('b');
insert into yp_team values('c');
insert into yp_team values('d');
select t1.team_name team1,t2.team_name team2 from yp_team t1 ,yp_team t2 where t1.team_name < t2.team_name;
/*
4.
请用SQL 语句实现:从TestDB 数据表中查询出所有月份的发生额都比101 科目相应月份的发生额高的科目。请注意:TestDB 中有很多科目,都有1 -12 月份的发生额。
AccID :科目代码,Occmonth :发生额月份,DebitOccur :发生额。
*/
declare
n2 number;
begin
select count(1) into n2 from user_tables where table_name=upper('yp_test_db');
if n2>0 then
execute immediate 'drop table yp_test_db';
end if;
end;
create table yp_test_db(
acc_id number(11),
occ_month number(2),
amount number(7,2)
);
alter table yp_test_db add constraint test_db_key primary key(acc_id,occ_month);
create sequence test_db_sequence
increment by 1
start with 1
nocycle
nomaxvalue
cache 20;
insert into yp_test_db values(test_db_sequence.nextval,1,34.54);
insert into yp_test_db values(test_db_sequence.currval,2,44.54);
insert into yp_test_db values(test_db_sequence.currval,3,55.54);
insert into yp_test_db values(test_db_sequence.currval,4,66.54);
insert into yp_test_db values(test_db_sequence.currval,5,33.54);
insert into yp_test_db values(test_db_sequence.currval,6,43.54);
insert into yp_test_db values(test_db_sequence.currval,7,45.54);
insert into yp_test_db values(test_db_sequence.currval,8,57.54);
insert into yp_test_db values(test_db_sequence.currval,9,58.54);
insert into yp_test_db values(test_db_sequence.currval,10,68.54);
insert into yp_test_db values(test_db_sequence.currval,11,41.54);
insert into yp_test_db values(test_db_sequence.currval,12,22.54);
insert into yp_test_db values(test_db_sequence.nextval,1,74.54);
insert into yp_test_db values(test_db_sequence.currval,2,84.54);
insert into yp_test_db values(test_db_sequence.currval,3,55.54);
insert into yp_test_db values(test_db_sequence.currval,4,66.54);
insert into yp_test_db values(test_db_sequence.currval,5,33.54);
insert into yp_test_db values(test_db_sequence.currval,6,93.54);
insert into yp_test_db values(test_db_sequence.currval,7,65.54);
insert into yp_test_db values(test_db_sequence.currval,8,57.54);
insert into yp_test_db values(test_db_sequence.currval,9,58.54);
insert into yp_test_db values(test_db_sequence.currval,10,68.54);
insert into yp_test_db values(test_db_sequence.currval,11,71.54);
insert into yp_test_db values(test_db_sequence.currval,12,62.54);
insert into yp_test_db values(test_db_sequence.nextval,1,74.54);
insert into yp_test_db values(test_db_sequence.currval,2,84.54);
insert into yp_test_db values(test_db_sequence.currval,3,55.54);
insert into yp_test_db values(test_db_sequence.currval,4,66.54);
insert into yp_test_db values(test_db_sequence.currval,5,33.54);
insert into yp_test_db values(test_db_sequence.currval,6,93.54);
insert into yp_test_db values(test_db_sequence.currval,7,65.54);
insert into yp_test_db values(test_db_sequence.currval,8,57.54);
insert into yp_test_db values(test_db_sequence.currval,9,58.54);
insert into yp_test_db values(test_db_sequence.currval,10,68.54);
insert into yp_test_db values(test_db_sequence.currval,11,71.54);
insert into yp_test_db values(test_db_sequence.currval,12,62.54);
insert into yp_test_db values(test_db_sequence.nextval,1,74.54);
insert into yp_test_db values(test_db_sequence.currval,2,84.54);
insert into yp_test_db values(test_db_sequence.currval,3,55.54);
insert into yp_test_db values(test_db_sequence.currval,4,66.54);
insert into yp_test_db values(test_db_sequence.currval,5,33.54);
insert into yp_test_db values(test_db_sequence.currval,6,93.54);
insert into yp_test_db values(test_db_sequence.currval,7,65.54);
insert into yp_test_db values(test_db_sequence.currval,8,57.54);
insert into yp_test_db values(test_db_sequence.currval,9,58.54);
insert into yp_test_db values(test_db_sequence.currval,10,68.54);
insert into yp_test_db values(test_db_sequence.currval,11,71.54);
insert into yp_test_db values(test_db_sequence.currval,12,62.54);
insert into yp_test_db values(101,1,35.54);
insert into yp_test_db values(101,2,46.54);
insert into yp_test_db values(101,3,36.54);
insert into yp_test_db values(101,4,37.54);
insert into yp_test_db values(101,5,34.54);
insert into yp_test_db values(101,6,47.54);
insert into yp_test_db values(101,7,46.54);
insert into yp_test_db values(101,8,38.54);
insert into yp_test_db values(101,9,49.54);
insert into yp_test_db values(101,10,38.54);
insert into yp_test_db values(101,11,42.54);
insert into yp_test_db values(101,12,23.54);
select * from yp_test_db;
-- select tmp1.acc_id, tmp1.month1,tmp1.month2,tmp1.month3,tmp1.month4,tmp1.month5,tmp1.month6,tmp1.month7,tmp1.month8,tmp1.month9,tmp1.month10,tmp1.month11,tmp1.month12 from (
select tmp1.acc_id, tmp1."month1",tmp1."month2",tmp1."month3",tmp1."month4",tmp1."month5",tmp1."month6",tmp1."month7",tmp1."month8",tmp1."month9",tmp1."month10",tmp1."month11",tmp1."month12" from
(
select acc_id,
sum(decode(occ_month,1,amount,0)) "month1",
sum(decode(occ_month,2,amount,0)) "month2",
sum(decode(occ_month,3,amount,0)) "month3",
sum(decode(occ_month,4,amount,0)) "month4",
sum(decode(occ_month,5,amount,0)) "month5",
sum(decode(occ_month,6,amount,0)) "month6",
sum(decode(occ_month,7,amount,0)) "month7",
sum(decode(occ_month,8,amount,0)) "month8",
sum(decode(occ_month,9,amount,0)) "month9",
sum(decode(occ_month,10,amount,0)) "month10",
sum(decode(occ_month,11,amount,0)) "month11",
sum(decode(occ_month,12,amount,0)) "month12"
from yp_test_db group by acc_id) tmp1
select distinct tmp3.* from yp_test_db tmp3, (select acc_id,occ_month,amount from yp_test_db where acc_id=101) tmp2 where tmp3.occ_month=tmp2.occ_month and tmp3.amount<tmp2.amount order by tmp3.acc_id,tmp3.occ_month asc;
-- 6.复制表
drop table b;
create table b
as
select * from yp_test_db where 1<>1;
-- mysql中
-- 创建表
drop table if exists stu_score;
create table stu_score(
stu_name varchar(30) comment '学生姓名',
course varchar(20) comment '课程',
score double(5,2) comment '成绩',
primary key(stu_name,course)
);
# 批量插入数据
insert into stu_score
values('张三','语文',78.98),
('张三','数学',88.98),
('张三','英语',99.98),
('李四','语文',98.98),
('李四','英语',100),
('李四','数学',88.98),
('王二','语文',85.98),
('王二','数学',84.98),
('王二','英语',90.98);
# 行列互换1
select stu_name ,
sum(case when course='语文' then score else 0 end) as "语文",
sum(case when course='数学' then score else 0 end) as "数学",
sum(case when course='英语' then score else 0 end) as "英语"
from stu_score group by stu_name;
-- 行列互换2
select stu_name,
sum(IF(course='语文',score,0)) as "语文",
sum(IF(course="数学",score,0)) as "数学",
sum(IF(course="英语",score,0)) as "英语"
from stu_score group by stu_name;
2 to_char的函数的掌握以及truncate、delete和drop的区别
/*
% 表示零或多个字符
_ 表示一个字符
规定转义字符 escape
*/
select * from emp;
update emp set ename='SMI_TH'where empno=7369;
select * from emp where ename like '%\_%' escape '\';
-- 使用to_char的使用
select to_char(hiredate,'YYYY-MM-DD HH12:MI:SS') from emp
select to_char(sal,'$000,000.00') from emp;
-- 对于null的函数
-- nvl(e1,e2),nvl2(value,e1,e2),decode(value,if,then,if...,else)
select * from emp;
select nvl2(mgr,2,-1) from emp;
-- 对于group by相当于多行函数
-- 如果需要对group by 增加限制条件使用 having
-- 执行顺序 from->where->group by->having->select->order by
select deptno,avg(sal) "avgsal" from emp group by deptno having avg(sal)>1200;
-- 统计人数小于4的部门的平均工资
select deptno, avg(sal) from emp group by deptno having count(nvl(sal,0))<4;
select count(1),avg(sal) from emp where deptno = 10;
-- 统计各部门的最高工资,排除最高工资小于3000的部门
select deptno,max(sal) from emp group by deptno having max(sal)<3000;
delete from yp_team;
/*
TRUNCATE之后的自增字段从头开始计数了,而DELETE的仍保留原来的最大数值
1. truncate和 delete只删除数据不删除表的结构(定义)
drop语句将删除表的结构被依赖的约束(constrain),触发器(trigger),索引(index); 依赖于该表的存储过程/函数将保留,但是变为invalid状态.
2.delete语句是dml,这个操作会放到rollback segement中,事务提交之后才生效;如果有相应的trigger,执行的时候将被触发.
truncate,drop是ddl, 操作立即生效,原数据不放到rollback segment中,不能回滚. 操作不触发trigger.
3.delete语句不影响表所占用的extent, 高水线(high watermark)保持原位置不动
显然drop语句将表所占用的空间全部释放
truncate 语句缺省情况下见空间释放到 minextents个 extent,除非使用reuse storage; truncate会将高水线复位(回到最开始).
4.速度,一般来说: drop>; truncate >; delete
5.安全性:小心使用drop 和truncate,尤其没有备份的时候.否则哭都来不及
使用上,想删除部分数据行用delete,注意带上where子句. 回滚段要足够大.
想删除表,当然用drop
想保留表而将所有数据删除. 如果和事务无关,用truncate即可. 如果和事务有关,或者想触发trigger,还是用delete.
如果是整理表内部的碎片,可以用truncate跟上reuse stroage,再重新导入/插入数据
*/
3 表连接查询的基本方法与特点
3.1 表连接语法的两大类
所谓的92与99语法其实就是1992和1999年归纳出来的语法
92语法:
主要有:笛卡尔集、等值连接、非等值连接、外连接、自连接
99语法:
主要有:交叉连接、自然连接、using、on、外连接
3.2 语法的详细介绍
/*
99与92语法pk
1.交叉连接(cross join)与笛卡儿积结果一样
2.等值连接与using连接结果一样,自然连接条件列只有一列
3.运用left join 和right join 与table1=table2(+)和table1(+)=table2结果一致,只是参照物不一样,
其中,99是以join为参照物,left join 就是左边的表全部展示出来,right join 就是右边的表全部展示出来
92 是以=为参照物,在(+)在右边就是左连接,左边的表数据全部展示出来,而右边没有匹配的就补null,因此个人理解(+)其实有补足的意思。
4.92语法与99语法的区别在于
*/
-- 1.92与99的左连接,右连接类似
select * from dept d,emp e where d.deptno = e.deptno(+);
select * from dept left join emp using(deptno);
-- 2.92等值连接与99using,以及99自然连接和99的on
select * from dept d,emp e where d.deptno = e.deptno;
select * from dept join emp using(deptno);-- 两张表一定要有同名的字段
select * from dept natural join emp;-- 两张表一定要有同名的字段
select * from dept d join emp e on d.deptno = e.deptno;-- 两张表没有同名字段也可以
-- 总而言之 92等值连接类似与99的自然连接和using连接类似,92非等值连接类似与99的on连接,当然罗,99的on连接也可以连接等值的
-- 3.92的笛卡儿积和99的交叉连接一样
select * from dept ,emp;
select * from dept cross join emp;
/*
总结92语法与99语法的区别
共同点:不管是99语法还是92语法都是实现表连接的,92与99语法都是相同的
区别:1.99语法简化了直观上的过滤条件,把过滤条件单独区分开用on或using实现,或自然连接不用写过滤条件;而92语法如有过滤条件全部都用where实现
2.对于外连接99拓展了92语法增加了满外连接
*/