文章目录
1 找出stu表中年龄第三大的学生基本信息
select * from
(select stu.sno 学号, stu.sname 姓名,stu.sage 年龄,
stu.sbirth 出生年月,stu.sdept 所在班级,
dense_rank() over (order by sage desc) rank from stu)
where rank =3
先对sage的进行降序排列后以rank值的方式对stu表中所有记录排序,年龄最大记录的rank值为1,次之为2;
dense_rank()
:
- 聚合函数
- 根据order by子句表达式的值,从查询的每一行,计算它们与其他行的相对位置;
- 生成的序列从1开始,往后累加 ;
- 每次order by 表达式的值发生变化,该序列也随之增加
2 查找列存在重复值的记录
select * from stu s
where s.sdept in( select s.sdept
from stu s
group by s.sdept having count(*) > 1)
group by s.sdept having count(*) > 1
所在班级(s.sdept)列分组显示的行数大于1
判断某列是否存在重复值,使用having字句实现,判断其count值是否大于1 即可。
3 只保留一行列存在重复值的记录
delete from stu
where
#查找出重复值记录
sdept in (
select sdept from stu
group by sdept having count(*) >1)
and
#找出班级列重复值记录的rowid值,非最小rowid
rowid not in (
select min(rowid) from stu group by sdept having count(*) >1);
rowid的大小根据其写入数据表的顺序排列,先写入的rowid值更小;
因此最终保留的2行存在重复值的记录都是先写入的记录。
4 创建脚本文件
在SQL的最后一条语句中,不要以“;”代替“/”符号,否则运行报错。
update stu set sage=sage+1 where sdept='12计算机’ /
select stu.sno 学号,stu.sname 姓名,stu.sage 年龄
from stu
order by sdept
/
5 运行脚本文件
- @d:1.sql
- start d:1.sql
6 提取表中的[N,M]条语句
select sno 学号,sname 姓名
from
(select rownum rn,t.* from stu t where rownum <= 4)
where s.rn>=2
/
由于rownum是伪列(根据查询的数据后生成的,只能=,<,<=),不能用>=2来实现;
上述代码首先通过子查询找出stu表中前4行记录,再在父查询中将伪列值小于2的排除;
也可用减法集合运算实现,即将两个select获得的结果进行剑法运算。
7 快速编译所有视图。
spool d:1.sql
select 'alter view '||tname ||' compile;'
from tab
/
8 创建编号自动增加的列
alter table stu add sid varchar2(10);
create sequence sid_seq
increment by 1
start with 9
maxvalue 9999
nocache
nocycle
/
9 更新数据前先保存旧值
create or replace trigger tri_update
before update
on stu
for each row
begin
insert into del_emp
values(:old.sno,:old.sname,:old.sgentle);
end;
/
将数据保存在另一个临时表del_tmp中,可用create del_tmp as select sno,sname,sgentle from stu where 1=2
复制表stu结构。
10 设置多条记录具有相同值
update stu set (sgentle,sage,sdept)=
(select sgentle,sage,sdept from stu where sno='12001')
where sno='12008'
/
11 列值为NULL情形的处理
update stu set sage = nvl(sage,0) +1
/
nvl(sage,0):当sage为空时,用0代替
create or replace procedure emp_proc_select(v_empno number)
as
myename varchar2(20);
begin
select ename into myename from myemp where empno=v_empno;
dbms_output.put_line('myename:'||myename);
exception
when no_data_found then
dbms_output.put_line('没有数据');
end;
/
12 通过having子句查询
与where的差别:
- where是在分组前对每一行进行过滤的。
- having是对查询出结果集分组(
group by
)后的结果进行过滤。
- WHERE 不能放在GROUP BY 后面
- HAVING 是跟GROUP BY 连在一起用的,放在GROUP BY 后面,此时的作用相当于WHERE
- WHERE 后面的条件中不能有聚集函数,比如SUM(),AVG()等,而HAVING 可以
查询每个部门工资低于1500的人数
SQL> select deptno 所在部门 ,count(deptno) 所在部门人数
2 from emp
3 group by deptno
4 having deptno in
5 ( select deptno from emp
6 where sal >1500 )
7 order by deptno
8 /
所在部门 所在部门人数
---------- ------------
10 3
20 3
30 6