Oracle从入门到精通:SQLPLUS登录、表空间创建与存储过程实战避坑指南
发布时间:2026/10/2 9:31:10来源:尧图网络
简介《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 为什么不能跳过结构直接学 SQLOracle 和 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#2024192.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 FETCH12c最接近 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 21 # 检查执行结果 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 再决定留不留。这个习惯让我少背了很多「加了索引反而更慢」的锅。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网