简介:这份Oracle期末复习题PDF面向高校数据库课程学生与备考Oracle认证的初学者,聚焦SQLPLUS操作、数据库连接、表空间管理、PL/SQL子程序及网络配置等核心考点,帮助读者在考前系统梳理易混淆概念。资源包内共1个PDF文件,大小约401KB,内容以选择题形式覆盖SQLPLUS工具定位、sqlplus /nolog与CONN命令、DESC查看表结构、SET SERVEROUTPUT ON回显设置、TRUNCATE与DELETE效率对比、PMON资源释放、侦听器位置、逻辑存储结构层级、STARTUP MOUNT启动方式、tnsnames.ora中PORT与SID参数、过程与函数返回值差异以及数据库包编译机制等高频知识点。目前已有253人学习浏览,题目附带选项与解析线索,适合用于自测查漏、课堂复习与考前突击,也可作为教师出题参考。
1. 从一份 Oracle 期末复习题.pdf 说起:它到底在考什么
很多人拿到「Oracle期末复习题.pdf」的第一反应是背答案,但真正做过企业项目的人会告诉你,这份 PDF 里藏着的是一套完整的数据库操作链路。它考的不是死记硬背,而是你能不能在一个 Oracle 实例里把数据查出来、改对、算准。从 SQLPlus 连库、PL/SQL 写块,到分页查询、函数嵌套、存储过程调试,这些内容恰好就是 Oracle 入门到进阶的主干。如果你正在准备考试,或者刚接手一个 Oracle 项目需要快速补齐基础,这份复习题覆盖的范围就是你的最小可行知识集。我见过太多人 SQL 语句写得出来,但一到 SQLPlus 里连不上库、一到 PL/SQL 块就报错、一到分页就写错 rownum 顺序,问题全出在「知道语法但没跑通」。这篇笔记就按复习题里最常出现的几类题型,把每个知识点落到可执行的命令和参数上,让你不只是会做题,而是能在真实库里跑出结果。
2. SQL*Plus 连库与基础查询:复习题里最容易翻车的第一关
2.1 为什么 SQL*Plus 是 Oracle 复习题的默认入口
Oracle 期末复习题里几乎每道操作题都默认你能连上数据库。SQLPlus 是 Oracle 自带的命令行工具,不需要额外装客户端,考试环境里通常直接可用。它的核心价值在于:所有 SQL 语句、PL/SQL 块、格式化命令都能在同一个会话里执行,而且输出格式可控。很多新手习惯用图形化工具,比如 PL/SQL Developer 或 Navicat,但考试和很多生产环境只给你 SQLPlus,所以先把命令行连库跑通是绕不过去的。
连接命令的写法直接决定你能不能进库。常见做法是:
# 以普通用户身份连接本地实例,@后面跟服务名或SID sqlplus scott/tiger@orcl # 如果不想暴露密码,可以先只输用户名,回车后再输密码 sqlplus scott@orcl # 以管理员身份连接,用于解锁用户或查数据字典 sqlplus / as sysdba这里有几个参数需要说清楚。scott/tiger是经典示例用户,但 Oracle 19c 默认不启用,需要先用alter user scott account unlock;解锁。@orcl是网络服务名,对应tnsnames.ora里的配置,如果你连的是本地默认实例,也可以省略。/ as sysdba是操作系统认证,要求当前系统用户在dba组里,Windows 上通常是ORA_DBA组。连上之后第一件事是确认当前用户和实例:
-- 查看当前登录用户 show user; -- 查看当前数据库实例名 select instance_name from v$instance; -- 查看当前会话的日期格式,避免后面日期查询出错 select sysdate from dual;show user是 SQL*Plus 命令,不是 SQL 语句,所以不加分号也能执行。dual是 Oracle 特有的伪表,用来做不依赖具体表的计算,比如select 1+1 from dual;。复习题里经常考dual的用法,注意它只有一行一列,不能存大量数据,热词里问「oracle中dual最多存多大」其实是个误区——dual是系统表,你不应该往里面存业务数据。
2.2 期末题里高频的查询写法与参数陷阱
复习题里的查询题通常围绕emp和dept两张表展开。最基础的select语句谁都会写,但考试会卡在几个细节上:空值处理、字符串拼接、日期格式、去重和排序。比如下面这条查询,要求查出每个部门的平均工资,并且只显示平均工资大于 2000 的部门:
-- 按部门分组计算平均工资,having过滤分组后的结果 select deptno, round(avg(sal), 2) as avg_sal from emp group by deptno having avg(sal) > 2000 order by avg_sal desc;round(avg(sal), 2)里的2是保留两位小数,不写的话 Oracle 会返回一长串精度。having和where的区别是考试必考:where在分组前过滤行,having在分组后过滤组。如果你把avg(sal) > 2000写到where里,Oracle 会直接报错,因为聚合函数不能出现在where子句中。
另一个高频坑是空值。null在 Oracle 里不等于任何值,包括它自己。下面这条语句查不出任何结果:
-- 错误写法:= null 永远为假 select * from emp where comm = null; -- 正确写法:用 is null 判断空值 select * from emp where comm is null; -- 空值参与运算结果仍为空,用 nvl 给默认值 select ename, sal, nvl(comm, 0) as comm_display from emp;nvl(comm, 0)的意思是如果comm为空就返回 0,否则返回comm本身。复习题里经常要求把空值显示成 0 或者「无」,就是考这个函数。注意nvl的两个参数类型要兼容,第二个参数是数字时第一个也应该是数字,否则会隐式转换,数据量大时影响性能。
字符串拼接用||,不是+。select ename || '的工资是' || sal from emp;会返回拼接后的字符串。如果sal是数字,Oracle 会自动转成字符串,但建议显式写to_char(sal)避免格式问题。日期查询要用to_date或to_char转换,直接写where hiredate = '1981-01-01'可能因为会话的nls_date_format不同而失败。稳妥写法是:
-- 显式指定日期格式,避免依赖会话设置 select * from emp where hiredate = to_date('1981-01-01', 'yyyy-mm-dd');to_date的第二个参数是格式模型,yyyy是四位年,mm是两位月,dd是两位日。如果格式写错,比如把mm写成mi,会报「无效的月份」错误。复习题里日期题丢分大多是因为格式模型写错。
3. PL/SQL 块与存储过程:从会写语法到能调试
3.1 PL/SQL 匿名块的结构与变量声明
PL/SQL 是 Oracle 对 SQL 的过程化扩展,复习题里通常要求写一个匿名块或者存储过程来完成某个逻辑,比如根据员工号涨工资、统计部门人数、处理异常。匿名块的基本结构是declare、begin、exception、end四段。下面这个块根据员工号给员工涨薪 10%,如果员工不存在就输出提示:
-- 匿名块:根据输入的员工号涨薪,处理找不到员工的情况 declare v_empno emp.empno%type := &input_empno; -- & 是 SQL*Plus 的替换变量 v_sal emp.sal%type; v_ename emp.ename%type; begin -- 查询员工当前工资和姓名 select sal, ename into v_sal, v_ename from emp where empno = v_empno; -- 更新工资 update emp set sal = sal * 1.1 where empno = v_empno; -- 输出结果 dbms_output.put_line('员工 ' || v_ename || ' 原工资 ' || v_sal || ',涨薪后完成'); commit; exception when no_data_found then dbms_output.put_line('员工号 ' || v_empno || ' 不存在'); when others then dbms_output.put_line('发生错误:' || sqlerrm); rollback; end; /这里有几个关键点。emp.empno%type表示变量类型和emp表的empno列一致,表结构变了变量类型自动跟着变,比写number(4)更稳。&input_empno是 SQLPlus 的替换变量,执行时会提示你输入值,适合交互式测试。select ... into ...必须保证只返回一行,如果返回多行会抛too_many_rows,返回零行会抛no_data_found。dbms_output.put_line要看到输出,必须先执行set serveroutput on;,这是 SQLPlus 的环境设置,不打开的话块执行成功但什么都不显示,很多人以为代码没跑,其实是输出被吞了。
异常处理里when others then能捕获所有未列出的异常,但生产环境不建议直接吞掉,至少要把sqlerrm打出来。commit和rollback的位置也要注意:如果更新成功但后面输出报错,没有commit的话事务会回滚,数据不会变。复习题里经常考「块执行完数据没变」的原因,八成是忘了commit或者异常分支里rollback了。
3.2 存储过程的参数模式与调试方法
存储过程和匿名块的区别是它有名字、能带参数、存在数据库里可以反复调用。复习题里常考的参数模式有三种:in、out、in out。in是只读输入,out是只写输出,in out可读可写。下面这个存储过程根据部门号返回该部门的最高工资和平均工资:
-- 存储过程:输入部门号,输出最高工资和平均工资 create or replace procedure get_dept_salary( p_deptno in emp.deptno%type, p_max_sal out emp.sal%type, p_avg_sal out emp.sal%type ) is begin -- 查询最高工资和平均工资 select max(sal), avg(sal) into p_max_sal, p_avg_sal from emp where deptno = p_deptno; -- 如果部门不存在,max和avg返回null,这里给默认值 if p_max_sal is null then p_max_sal := 0; p_avg_sal := 0; end if; exception when others then dbms_output.put_line('查询失败:' || sqlerrm); raise; -- 重新抛出异常,让调用方知道出错了 end get_dept_salary; /创建完之后在 SQL*Plus 里调用:
-- 声明绑定变量接收输出参数 variable v_max number; variable v_avg number; -- 执行存储过程 execute get_dept_salary(20, :v_max, :v_avg); -- 打印输出参数的值 print v_max; print v_avg;variable是 SQL*Plus 命令,用来声明绑定变量,:前缀在 SQL 里引用绑定变量。execute是begin ... end;的简写,只能执行一行。如果存储过程有多个out参数,用print逐个查看。调试存储过程时,如果报「ORA-06575: 程序包或函数处于无效状态」,先用show errors procedure get_dept_salary;看具体编译错误。常见原因是表名写错、列名写错、或者select into的列数和变量数不匹配。
复习题里还经常考「包状态被丢弃」的问题,热词里也出现了「oracle 为什么会出现 包状态 被丢弃」。这通常是因为包依赖的对象被重新编译或修改,导致包变成invalid状态。解决办法是重新编译:alter package 包名 compile;或者alter procedure 过程名 compile;。如果依赖的对象本身有问题,要先修依赖对象再编译包。
4. 分页查询与函数嵌套:复习题里的计算题怎么拿满分
4.1 Oracle 分页的三种写法与 rownum 的坑
Oracle 分页是期末复习题里必考的计算题,也是实际项目里最容易写错的地方。热词里「oracle分页」出现频率很高,说明很多人在这上面踩过坑。Oracle 没有limit关键字,分页要靠rownum或者 12c 之后的offset fetch。先看最经典的rownum写法,查第 6 到第 10 条记录:
-- 方法一:嵌套子查询,先排序再取 rownum,最后过滤区间 select * from ( select a.*, rownum rn from ( select empno, ename, sal from emp order by sal desc ) a where rownum <= 10 ) where rn >= 6;这个写法的关键是三层嵌套。最内层排序,中间层加rownum并限制上界,最外层过滤下界。为什么不能直接写where rownum between 6 and 10?因为rownum是在结果集生成过程中逐行分配的,where rownum > 6永远为假——第一行rownum是 1,不满足大于 6,被过滤掉;第二行变成新的第一行,rownum又是 1,还是不满足,最终返回空。这是 Oracle 分页最经典的坑,复习题里经常用这个来区分「背过语法」和「真正理解」。
Oracle 12c 之后可以用offset ... fetch,写法更直观:
-- 方法二:12c+ 的 offset fetch,跳过5行取5行 select empno, ename, sal from emp order by sal desc offset 5 rows fetch next 5 rows only;offset 5 rows是跳过前 5 行,fetch next 5 rows only是取接下来的 5 行。注意offset和fetch必须配合order by使用,否则顺序不确定,分页结果没有意义。如果你的数据库是 11g 或更早版本,只能用rownum嵌套写法。考试时先确认版本,19c 的话两种都能用,但复习题答案可能只认rownum写法,建议两种都掌握。
4.2 常用函数嵌套与「过滤不可转为数字的字符串」
复习题里的函数题通常要求组合使用字符函数、数字函数、日期函数和转换函数。热词里有一个很具体的问题:「oracle 过滤不可转为数字的字符串」。这个场景在实际项目里很常见:某个varchar2列里混了数字和字母,你要只取能转成数字的行。直接写where to_number(col) > 100会报ORA-01722: 无效数字,因为 Oracle 会尝试转换所有行,遇到字母就报错。
稳妥的做法是用regexp_like先过滤:
-- 只取 col 中全是数字的行,再转数字比较 select * from test_table where regexp_like(col, '^[0-9]+$') and to_number(col) > 100;regexp_like(col, '^[0-9]+$')的意思是col从开头到结尾全是数字,^是开头,$是结尾,[0-9]+是一个或多个数字。这样先过滤掉含字母的行,to_number就不会报错。如果允许小数点和负号,正则要改成'^-?[0-9]+(\.[0-9]+)?$'。注意regexp_like在数据量大时比普通like慢,但胜在准确。如果列上有函数索引或者可以加虚拟列,性能会更好。
另一个高频函数题是日期计算。trunc(sysdate)返回当天零点,sysdate带时分秒。复习题里常考「查询今天入职的员工」,写法是:
-- trunc 去掉时分秒,比较日期部分 select * from emp where trunc(hiredate) = trunc(sysdate);如果直接写hiredate = sysdate,因为sysdate带时分秒,几乎永远不相等。trunc的第二个参数可以指定截断精度,比如trunc(sysdate, 'mm')返回当月第一天,trunc(sysdate, 'yyyy')返回当年第一天。这些在报表统计里很常用。
decode和case when也是复习题常客。decode是 Oracle 特有,case when是标准 SQL。比如把部门号转成部门名:
-- decode 写法 select ename, decode(deptno, 10, '财务部', 20, '研发部', 30, '销售部', '其他') as dept_name from emp; -- case when 写法,更通用 select ename, case deptno when 10 then '财务部' when 20 then '研发部' when 30 then '销售部' else '其他' end as dept_name from emp;两种写法结果一样,decode更短,case when可读性更好且支持复杂条件。考试时如果题目没指定,用哪种都行,但case when在跨数据库时更安全。
5. 复习题里那些「看起来会做但一跑就错」的避坑清单
5.1 避坑一:SQL*Plus 里执行 PL/SQL 块忘了加斜杠
现象:在 SQL*Plus 里输入完end;回车,块没有执行,而是又出现一个行号提示,继续输入也不对。
原因:SQLPlus 里执行 PL/SQL 块,end;后面必须单独一行写/才会提交执行。只写分号的话 SQLPlus 认为语句还没结束。
解决:在end;的下一行输入/然后回车。如果是用@脚本文件.sql的方式执行,脚本里也要在end;后加/。另外注意set serveroutput on;要先执行,否则块跑完了也看不到dbms_output的输出。
5.2 避坑二:select into 返回多行导致 too_many_rows
现象:匿名块或存储过程执行时报ORA-01422: exact fetch returns more than requested number of rows。
原因:select ... into ...要求查询结果最多一行,但where条件不够精确,返回了多行。
解决:先单独执行select语句确认返回行数,给where加上唯一条件比如主键,或者用rownum = 1限制(但要确认业务上取哪一行)。如果确实需要处理多行,改用游标cursor或者bulk collect into集合。复习题里如果题目说「查询员工信息」但没给唯一条件,要检查是不是漏了empno条件。
5.3 避坑三:日期格式依赖会话设置导致查询结果不对
现象:同样的日期查询语句,在 SQL*Plus 里能查出数据,在 PL/SQL Developer 里查不出,或者反过来。
原因:不同客户端的nls_date_format会话参数不同,'1981-01-01'这种字符串在不同格式下解析结果不一样,甚至报错。
解决:所有日期比较都用to_date('1981-01-01', 'yyyy-mm-dd')显式指定格式,不要依赖隐式转换。查询当前会话日期格式用select * from nls_session_parameters where parameter = 'NLS_DATE_FORMAT';。如果需要修改,用alter session set nls_date_format = 'yyyy-mm-dd hh24:mi:ss';,但只对当前会话有效。
5.4 避坑四:rownum 分页排序错乱
现象:分页查询第一页和第二页有重复数据,或者某些数据从来没出现过。
原因:rownum是在排序之前分配的,如果先取rownum再排序,分页结果就乱了。或者order by的列有重复值,Oracle 排序不稳定,每次执行顺序可能不同。
解决:分页必须三层嵌套,最内层先order by,中间层加rownum,最外层过滤区间。如果排序列有重复值,在order by里加上主键做第二排序键,比如order by sal desc, empno asc,保证顺序确定。
5.5 避坑五:存储过程编译报错但看不到具体错误
现象:create or replace procedure执行后提示「已创建,但存在编译错误」,但不知道错在哪。
原因:SQL*Plus 默认不显示编译错误详情。
解决:执行show errors procedure 过程名;或者show errors;查看具体错误行和错误信息。常见错误包括:表名或列名拼写错误、select into变量类型不匹配、end后面忘了过程名(创建过程时end后要跟过程名,匿名块不用)。修改后重新执行create or replace即可,不需要先drop。
6. 把复习题变成真实能力的进阶练法
复习题做完一遍,很多人就扔了。但真正把 Oracle 用起来的人会做一件事:把每道题改成一个可重复执行的脚本,加上异常处理和日志,然后在一个测试库里跑通。比如分页查询那道题,你可以写一个存储过程,输入页码和每页条数,返回对应数据,这样就把一道选择题变成了一个可复用的分页组件。再比如函数嵌套那道题,你可以建一张测试表,故意插入一些非数字字符串,验证regexp_like过滤是否真的有效,顺便测一下数据量到十万行时性能下降多少。
我自己的习惯是每学一个 Oracle 知识点,就在本地 19c 实例里建一张小表,把边界情况都插进去:空值、超长字符串、特殊字符、日期边界。然后写查询验证结果。这样考试时遇到「以下哪个 SQL 返回正确结果」的题,你脑子里有实际跑出来的画面,而不是靠排除法猜。复习题里的dual、rownum、nvl、decode、trunc这些,每一个我都至少写过二十遍,直到不用查文档就能写对参数。
还有一个进阶方向是把复习题里的单表查询改成多表连接加分析函数。比如「查询每个部门工资最高的员工」,基础写法是子查询加max,进阶写法用row_number() over(partition by deptno order by sal desc)。分析函数在 19c 里很稳定,实际项目里做排名、累计、同比环比都靠它。复习题可能不考,但你如果能把每道基础题都用分析函数重写一遍,Oracle 进阶教程里大半内容就通了。
最后说一个我踩过的坑:不要在生产库上直接跑复习题里的update和delete。我见过有人在测试库跑惯了,连上生产库顺手执行了一个没有where的update,整张表工资翻倍,最后靠flashback table才救回来。复习题里的 DML 语句,先在本地实例跑,确认where条件没问题再考虑上测试环境。commit之前先select确认影响行数,这个习惯能帮你省下很多后悔药。
希望帮到你。
本文还有配套的精品资源,点击获取