简介:《oracle从入门到精通.pdf》是一份面向数据库初学者与运维人员的Oracle学习资料,围绕SQL基础、数据库设计与数据库管理三大模块展开,帮助读者从零建立Oracle知识体系并逐步进阶到日常管理应用。资源包内共1个PDF文件,大小约102KB,内容以文字讲解与语法示例为主,便于随时查阅和打印学习。目前已有299人学习浏览,适合作为入门阶段的系统梳理材料。资料从SQL基本概念讲起,涵盖数据库、表、字段与记录等基础定义,并延伸至用户身份验证、权限控制与数据加密等安全要点;随后详细讲解SELECT语句语法、WHERE/AND/OR条件、别名、连接操作符、DISTINCT及SQLPLUS与SQL的关系,还涉及单行函数中的字符、数字与日期处理。数据库设计部分介绍规范化原则与schema结构,管理部分则覆盖性能优化、备份恢复与安全管理,并提及Oracle Tuning Advisor、SQL Trace等工具,目录层级清晰,方便按章节查漏补缺。
1. 从一份 oracle从入门到精通.pdf 说起:为什么多数人卡在 SQLPLUS 登录那一步
很多人拿到一份 oracle从入门到精通.pdf,第一反应是照着目录从第一章翻起,结果翻到第三章就卡住了——SQLPLUS 登录报错、监听没起、表空间建不出来,然后开始怀疑这份文档是不是过时了。问题不在文档,在于 Oracle 的学习路径和普通软件完全不一样:它不是装完就能用的工具,而是一套需要先理解「实例—数据库—表空间—用户—表」五层结构的系统。你跳过结构直接敲 SQL,就像没打地基就砌墙,登录那一步就会翻车。
这份标题真正要解决的问题是:让一个没碰过 Oracle 的人,能在本地或测试环境把实例跑起来,用 SQLPLUS 连上,建自己的表空间和用户,然后开始写 SQL 和存储过程。它适合后端开发、运维、数据分析师,以及需要从 MySQL 或 SQL Server 转过来的工程师。热搜里反复出现的「oracle 19c创建用户表空间」「sqlplus登录oracle数据库出现缓慢」「oracle 过滤不可转为数字的字符串」,其实都指向同一件事——基础环境没搭对,后面全是玄学问题。这篇笔记就按「先立结构、再动手、最后排坑」的顺序,把这条路走一遍。
2. 先把五层结构立住:实例、数据库、表空间、用户、表到底谁管谁
2.1 为什么不能跳过结构直接学 SQL
Oracle 和 MySQL 最大的认知差异在于:MySQL 里你建个 database 就能建表,Oracle 里你连「数据库」这个词的含义都不一样。Oracle 的「数据库」指的是磁盘上的一堆物理文件(数据文件、控制文件、重做日志),而「实例」是内存结构加后台进程。一个实例挂载一个数据库,用户连的其实是实例,实例再去操作数据库文件。这中间还夹着一层「表空间」——它是数据文件的逻辑分组,用户建表时必须指定表空间,否则就落到默认的 SYSTEM 表空间里,这是新手最容易埋的雷。
所以正确的理解链条是:实例启动 → 挂载数据库 → 数据库里有若干表空间 → 表空间由数据文件组成 → 用户默认绑定某个表空间 → 用户建的表存在表空间里。你只要记住一句话:用户不直接拥有表,表属于某个表空间,用户只是有权限在里面建表。热搜里「oracle 19c创建用户表空间」之所以被反复搜,就是因为很多人建完用户发现建不了表,报「ORA-01950: 对表空间 USERS 无权限」,根子就在这。
2.2 用一条 SQL 看清当前实例的全貌
登录之后别急着建表,先跑几条查询把结构摸清楚。下面这段 SQL 在 SQLPLUS 里执行,能一次性看到实例名、数据库名、表空间和数据文件的关系:
-- 查看当前实例和数据库基本信息 SELECT instance_name, host_name, version, status FROM v$instance; -- 查看数据库名和创建时间 SELECT name, created, log_mode, open_mode FROM v$database; -- 查看所有表空间及其类型和状态 SELECT tablespace_name, status, contents, extent_management FROM dba_tablespaces ORDER BY tablespace_name; -- 查看表空间对应的数据文件路径和大小 SELECT tablespace_name, file_name, bytes/1024/1024 AS size_mb, autoextensible FROM dba_data_files ORDER BY tablespace_name;逻辑说明:v$instance和v$database是动态性能视图,任何有权限的用户都能查,用来确认实例是否正常打开。dba_tablespaces和dba_data_files需要 DBA 权限,能看到每个表空间由哪些文件撑起来、是否自动扩展。参数上重点看autoextensible,如果是 NO,表空间写满就会报 ORA-01653,这是生产环境最常见的故障之一。extent_management一般是 LOCAL,这是 10g 之后的默认值,不用改。
2.3 建表空间和用户的标准动作
摸清结构后,建一套自己的表空间和用户。下面这段是 19c 单实例下最常用的写法,注意路径要换成你实际的数据文件目录:
-- 创建永久表空间,初始 100M,自动扩展,每次 50M,上限 2G CREATE TABLESPACE app_data DATAFILE '/u01/app/oracle/oradata/ORCL/app_data01.dbf' SIZE 100M AUTOEXTEND ON NEXT 50M MAXSIZE 2G EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO; -- 创建临时表空间 CREATE TEMPORARY TABLESPACE app_temp TEMPFILE '/u01/app/oracle/oradata/ORCL/app_temp01.dbf' SIZE 50M AUTOEXTEND ON NEXT 25M MAXSIZE 1G; -- 创建用户并绑定默认表空间 CREATE USER app_user IDENTIFIED BY "App#2024" DEFAULT TABLESPACE app_data TEMPORARY TABLESPACE app_temp QUOTA UNLIMITED ON app_data; -- 给最小权限集 GRANT CONNECT, RESOURCE TO app_user; GRANT CREATE SESSION, CREATE TABLE, CREATE VIEW, CREATE PROCEDURE TO app_user;逻辑说明:EXTENT MANAGEMENT LOCAL让区管理交给位图,避免数据字典争用;SEGMENT SPACE MANAGEMENT AUTO让段内空间自动管理,减少碎片。QUOTA UNLIMITED ON app_data是关键,不写这句用户建表会直接报无权限。密码用双引号包住是因为含特殊字符,Oracle 默认密码大小写敏感从 11g 就开始了。GRANT CONNECT, RESOURCE是经典组合,但 RESOURCE 角色在新版本里权限被收窄过,所以额外补了 CREATE TABLE 等具体权限,避免踩坑。
提示:生产环境不要用 UNLIMITED,按业务预估给配额,比如 QUOTA 5G ON app_data,防止单个用户把表空间写爆。
3. SQLPLUS 登录慢和报错的排查:从监听、服务名到密码过期
3.1 登录慢的三种典型原因
热搜里「sqlplus登录oracle数据库出现缓慢或者错误的原因可能很多」这句话说得很实在。我踩过的登录慢,基本逃不出三类:第一类是 DNS 反解超时,客户端连上来时服务器要反查客户端 IP 的主机名,DNS 不通就卡几十秒;第二类是监听日志文件过大,listener.log涨到几个 G 后写入变慢,连带登录变慢;第三类是密码过期或账号被锁,登录时反复重试认证。这三类的现象都是「卡」,但排查路径完全不同。
先看监听状态和日志大小:
# 查看监听状态,注意 Service 是否显示 READY lsnrctl status # 查看监听日志大小,超过 2G 就要清理 ls -lh $ORACLE_BASE/diag/tnslsnr/*/listener/trace/listener.log # 清理监听日志(先停监听再清,避免文件句柄问题) lsnrctl set log_status off mv listener.log listener.log.bak lsnrctl set log_status on逻辑说明:lsnrctl status输出里重点看「Service "ORCL" has 1 instance(s)」和状态 READY,如果显示 BLOCKED 说明实例没注册上。监听日志路径随版本变化,19c 一般在$ORACLE_BASE/diag/tnslsnr/主机名/listener/trace/下。清理时不能直接rm,因为监听进程还持有文件句柄,要先关日志再改名,最后重新打开。
3.2 服务名和 SID 写错导致的 ORA-12514
另一个高频报错是 ORA-12514: TNS:listener does not currently know of service requested in connect descriptor。原因通常是连接串里写的是 SID,但监听注册的是服务名,或者反过来。19c 默认的服务名是ORCL或ORCLPDB(多租户下),SID 是ORCL。用 SQLPLUS 连接时两种写法:
# 用服务名连接(推荐) sqlplus app_user/App#2024@//192.168.1.100:1521/ORCL # 用 SID 连接(老写法,多租户下容易出错) sqlplus app_user/App#2024@192.168.1.100:1521/ORCL逻辑说明://主机:端口/服务名是 EZConnect 写法,不依赖 tnsnames.ora,最省事。如果服务名不确定,在数据库服务器上用lsnrctl services看注册了哪些服务。多租户架构下,PDB 的服务名才是你该连的,CDB 的根容器一般不给业务用。
3.3 密码过期和账号锁定
Oracle 默认的 DEFAULT profile 里PASSWORD_LIFE_TIME是 180 天,过期后登录报 ORA-28001。查当前 profile 和用户状态:
-- 查看用户状态和使用的 profile SELECT username, account_status, expiry_date, profile FROM dba_users WHERE username = 'APP_USER'; -- 查看 profile 的密码策略 SELECT profile, resource_name, limit FROM dba_profiles WHERE profile = 'DEFAULT' AND resource_name IN ('PASSWORD_LIFE_TIME','FAILED_LOGIN_ATTEMPTS','PASSWORD_LOCK_TIME'); -- 解锁并重置密码 ALTER USER app_user ACCOUNT UNLOCK; ALTER USER app_user IDENTIFIED BY "NewApp#2024"; -- 把密码有效期改成无限制(测试环境用,生产慎用) ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED;逻辑说明:account_status常见值有 OPEN、LOCKED、EXPIRED。EXPIRED 就是密码过期,改密码即可;LOCKED 是失败次数超限,要先 UNLOCK。FAILED_LOGIN_ATTEMPTS默认 10 次,超过就锁。生产环境不建议把 PASSWORD_LIFE_TIME 设 UNLIMITED,合规上过不去,等保检查会盯这一条。
注意:改 profile 的 LIMIT 只影响之后的新密码策略,已经过期的账号还是要单独重置密码才能恢复。
4. 从 SQL 到存储过程:分页、函数和类型转换的实战写法
4.1 Oracle 分页的三种写法和选型
热搜里「oracle分页」是高频词,因为 Oracle 没有 MySQL 的 LIMIT,新手第一反应是懵的。主流有三种写法:ROWNUM 嵌套、ROW_NUMBER() 分析函数、12c 之后的 OFFSET FETCH。下面把三种都写出来对比:
-- 写法一:ROWNUM 双层嵌套(兼容老版本,最通用) SELECT * FROM ( SELECT a.*, ROWNUM rn FROM ( SELECT id, name, created_at FROM orders ORDER BY created_at DESC ) a WHERE ROWNUM <= 20 ) WHERE rn > 10; -- 写法二:ROW_NUMBER() 分析函数(逻辑清晰,适合复杂排序) SELECT * FROM ( SELECT id, name, created_at, ROW_NUMBER() OVER (ORDER BY created_at DESC) AS rn FROM orders ) WHERE rn BETWEEN 11 AND 20; -- 写法三:OFFSET FETCH(12c+,最接近 MySQL 语法) SELECT id, name, created_at FROM orders ORDER BY created_at DESC OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;逻辑说明:写法一的坑在于 ROWNUM 是在排序前分配的,所以必须嵌套两层,内层先排序,中层限制上界,外层取下界。写法二用分析函数,排序和编号一步到位,但要注意ORDER BY里的字段如果有重复值,分页结果可能不稳定,最好加个唯一列做次级排序。写法三最简洁,但 11g 不支持,如果项目要兼容老库就别用。参数上 OFFSET 是从 0 开始,OFFSET 10表示跳过前 10 行。
4.2 存储过程的基本骨架和异常处理
Oracle 存储过程是 PL/SQL 的核心,热搜里「oracle存储过程」一直有人搜。一个能上生产的存储过程,至少要包含参数定义、业务逻辑、异常捕获和事务控制四部分:
CREATE OR REPLACE PROCEDURE proc_sync_order( p_start_date IN DATE, p_end_date IN DATE, p_count OUT NUMBER ) AS v_batch_id NUMBER; BEGIN -- 初始化 p_count := 0; SELECT seq_batch.NEXTVAL INTO v_batch_id FROM dual; -- 业务逻辑:把符合条件的订单标记为已同步 UPDATE orders SET sync_status = 'Y', sync_batch = v_batch_id, sync_time = SYSDATE WHERE created_at BETWEEN p_start_date AND p_end_date AND sync_status = 'N'; p_count := SQL%ROWCOUNT; -- 记录日志 INSERT INTO sync_log(batch_id, start_date, end_date, row_count, log_time) VALUES(v_batch_id, p_start_date, p_end_date, p_count, SYSDATE); COMMIT; EXCEPTION WHEN NO_DATA_FOUND THEN ROLLBACK; p_count := -1; RAISE_APPLICATION_ERROR(-20001, '未找到符合条件的订单'); WHEN OTHERS THEN ROLLBACK; p_count := -1; INSERT INTO sync_log(batch_id, start_date, end_date, row_count, log_time, err_msg) VALUES(v_batch_id, p_start_date, p_end_date, 0, SYSDATE, SQLERRM); COMMIT; RAISE; END proc_sync_order; /逻辑说明:SQL%ROWCOUNT取上一条 DML 影响的行数,必须在 COMMIT 之前取,否则会重置。RAISE_APPLICATION_ERROR抛出自定义错误码,范围是 -20000 到 -20999。异常分支里先 ROLLBACK 再写日志,日志用独立 COMMIT,保证出错记录不丢。WHEN OTHERS里用SQLERRM拿错误信息,但要注意它可能被后续语句覆盖,最好先存到变量里。
4.3 过滤不可转为数字的字符串
热搜里「oracle 过滤不可转为数字的字符串」是个经典难题。Oracle 的 TO_NUMBER 遇到非数字直接抛 ORA-01722,不像有些数据库返回 NULL。常见做法是用正则先过滤:
-- 只保留纯数字的行 SELECT id, col_value FROM source_table WHERE REGEXP_LIKE(col_value, '^[0-9]+$'); -- 安全转换:非数字返回 NULL SELECT id, CASE WHEN REGEXP_LIKE(col_value, '^[0-9]+$') THEN TO_NUMBER(col_value) ELSE NULL END AS num_value FROM source_table; -- 12c+ 可以用 DEFAULT ... ON CONVERSION ERROR SELECT id, TO_NUMBER(col_value DEFAULT NULL ON CONVERSION ERROR) AS num_value FROM source_table;逻辑说明:REGEXP_LIKE(col_value, '^[0-9]+$')只匹配纯数字,不含小数点、负号、空格。如果要支持负数和小数,正则改成'^-?[0-9]+(\.[0-9]+)?$'。12c 的DEFAULT NULL ON CONVERSION ERROR更省事,但 11g 不支持。注意正则在大表上走不了索引,如果数据量大,建议在 ETL 阶段就清洗好,别在查询时实时过滤。
5. 避坑与排查:表空间、DBF 文件和慢 SQL 的五个血泪记录
5.1 表空间写满报 ORA-01653
现象:插入数据时报 ORA-01653: unable to extend table XXX by 128 in tablespace APP_DATA。原因:表空间的数据文件达到 MAXSIZE 或磁盘满了,无法再扩展。解决:先查使用率,再决定加数据文件还是开自动扩展。
-- 查看表空间使用率 SELECT d.tablespace_name, ROUND(d.total_mb, 2) AS total_mb, ROUND(d.total_mb - f.free_mb, 2) AS used_mb, ROUND((d.total_mb - f.free_mb) / d.total_mb * 100, 2) AS used_pct FROM (SELECT tablespace_name, SUM(bytes)/1024/1024 AS total_mb FROM dba_data_files GROUP BY tablespace_name) d, (SELECT tablespace_name, SUM(bytes)/1024/1024 AS free_mb FROM dba_free_space GROUP BY tablespace_name) f WHERE d.tablespace_name = f.tablespace_name; -- 加数据文件 ALTER TABLESPACE app_data ADD DATAFILE '/u01/app/oracle/oradata/ORCL/app_data02.dbf' SIZE 500M AUTOEXTEND ON NEXT 100M MAXSIZE 4G;5.2 DBF 文件损坏导致实例起不来
现象:数据库启动到 mount 阶段报 ORA-01157 或 ORA-01110,提示某个 dbf 文件无法识别。原因:磁盘故障、误删、文件系统损坏。解决:如果有备份就恢复,没有备份只能走数据文件离线再重建的路线,代价很大。热搜里「oracle dbf文件坏了」搜的人不少,但真正能救回来的前提是你有 RMAN 备份。所以第一件事永远是确认备份可用,而不是急着修文件。
5.3 慢 SQL 的定位顺序
现象:业务反馈某功能变慢,但不知道是哪条 SQL。原因:可能是执行计划变了、统计信息过期、索引失效。解决:按顺序查 v$session、v$sql、执行计划。
-- 找当前正在跑的慢 SQL SELECT sid, serial#, sql_id, event, seconds_in_wait, blocking_session FROM v$session WHERE status = 'ACTIVE' AND type = 'USER'; -- 根据 sql_id 看完整 SQL 和统计 SELECT sql_id, elapsed_time/1000000 AS elapsed_sec, executions, buffer_gets, disk_reads, sql_text FROM v$sql WHERE sql_id = '&sql_id'; -- 看执行计划 SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('&sql_id', NULL, 'ALLSTATS LAST'));逻辑说明:seconds_in_wait大且event是 db file sequential read,说明在等 IO,可能是索引没走对。buffer_gets高说明逻辑读多,通常是全表扫描。执行计划里重点看 TABLE ACCESS FULL 和 INDEX RANGE SCAN 的比例,以及预估行数和实际行数的偏差,偏差大说明统计信息不准,跑DBMS_STATS.GATHER_TABLE_STATS重新收集。
5.4 包状态被丢弃
现象:调用存储过程报 ORA-04068: existing state of packages has been discarded。原因:包依赖的对象被重新编译,或者包本身被 ALTER 过,导致会话里的包状态失效。解决:重新调用一次即可,但如果频繁出现,要查是谁在改依赖对象。热搜里「oracle 为什么会出现 包状态 被丢弃」就是这个场景。生产环境改包要挑低峰期,改完让应用重连。
5.5 等保命令和审计的注意点
现象:等保检查要求开审计,但开了之后性能下降、日志暴涨。原因:审计级别设太高,比如 AUDIT ALL。解决:按需审计,只审关键表和关键操作。
-- 查看当前审计配置 SELECT * FROM dba_audit_mgmt_config_params; -- 只审计对敏感表的删除操作 AUDIT DELETE ON app_user.orders BY ACCESS; -- 查看审计记录 SELECT username, action_name, obj_name, timestamp FROM dba_audit_trail WHERE obj_name = 'ORDERS' ORDER BY timestamp DESC;逻辑说明:BY ACCESS每次访问都记,BY SESSION每会话记一次,后者日志量小。审计表默认在 SYSTEM 表空间,大库要迁到独立表空间,否则 SYSTEM 写满整个库都起不来。
6. 进阶技巧:用 SQLPLUS 脚本化和 AWR 报告定位性能拐点
学到这一步,你已经能建库、建用户、写 SQL 和存储过程了。但真正让 Oracle 从「能用」到「好用」的,是两件事:把重复操作脚本化,以及学会看 AWR 报告。我一般会在项目里放一个init.sql,把建表空间、建用户、授权、建表全部串起来,新环境一条命令跑完:
# 静默执行初始化脚本,-S 减少回显,-L 只登录一次 sqlplus -S / as sysdba @init.sql > init.log 2>&1 # 检查执行结果 grep -i "ORA-" init.loginit.sql里用WHENEVER SQLERROR EXIT SQL.SQLCODE让脚本遇到错误就退出,避免半拉子状态。这个习惯能省掉大量手工操作,也方便版本管理。
AWR 报告是另一个分水岭。很多人装了 Oracle 只会用,不会看性能。生成 AWR 报告的命令:
-- 找到快照 ID SELECT snap_id, begin_interval_time, end_interval_time FROM dba_hist_snapshot ORDER BY snap_id DESC FETCH FIRST 10 ROWS ONLY; -- 生成 HTML 报告 @?/rdbms/admin/awrrpt.sql看 AWR 报告,我一般按这个顺序:先看 DB Time 和 Elapsed 的比例,判断负载;再看 Top 10 Foreground Events,找等待事件;然后看 SQL ordered by Elapsed Time,定位最耗时的 SQL;最后看 Instance Activity Stats,确认逻辑读和物理读的趋势。如果 db file sequential read 排第一,说明索引读多,可能是索引设计有问题;如果 log file sync 排第一,说明提交太频繁,要考虑批量提交。
一个具体技巧:把 AWR 报告里的 SQL 按Elapsed Time per Exec排序,而不是按总时间。总时间高的可能是执行次数多但单次很快的 SQL,单次慢的才是真正要优化的。这个视角切换,能帮你从一堆 SQL 里快速找到那个「一颗老鼠屎」。
我自己踩过最大的坑,是早期不看执行计划就加索引,结果索引加了一堆,写入反而变慢,因为每次 INSERT 都要维护所有索引。后来养成习惯:加索引前先看DBA_INDEXES里现有索引的列顺序,能复用就复用,不能复用再新建,新建后观察一周的 AWR 再决定留不留。这个习惯让我少背了很多「加了索引反而更慢」的锅。希望帮到你。
本文还有配套的精品资源,点击获取