1. 从零开始为什么选择Oracle以及它能为你带来什么如果你正准备踏入数据库的世界或者正从其他数据库系统比如MySQL、PostgreSQL转向企业级应用那么Oracle数据库绝对是一个绕不开的名字。我从业十几年从早期的Oracle 10g一路用到现在的19c、21c亲眼见证了它在金融、电信、大型制造业等核心业务系统中不可撼动的地位。很多人一听到Oracle第一反应是“庞大”、“复杂”、“昂贵”进而望而却步。但我想说作为入门者恰恰应该从理解这样一个“重量级选手”开始。这就像学开车如果你一开始就能驾驭手动挡的复杂路况那么自动挡对你来说就是轻而易举。掌握Oracle的核心思想和架构会让你对“数据库”这个概念的理解远超于仅仅会写几条SQL语句。Oracle的强大根植于它几十年积累下来的稳定性、安全性和丰富的功能集。它的并发控制机制多版本读一致性、强大的PL/SQL编程能力、完善的备份恢复体系RMAN、以及高可用解决方案如Data Guard, RAC共同构成了一个能够支撑7x24小时关键业务运转的坚实底座。对于初学者而言学习Oracle不仅仅是学习一个软件的使用更是学习一套严谨的数据管理哲学和最佳实践。你在这里踩过的每一个“坑”理解的每一个“为什么”都会成为你数据库知识体系中最为牢固的基石。本教程的目的就是帮你卸下对Oracle的畏惧感用最直接、最务实的方式带你走过从安装配置到写出第一个复杂查询的全过程并分享那些官方手册里不会写的实操心得。2. 环境准备与安装避开初学者的第一个大坑动手之前我们先得把“战场”准备好。Oracle数据库的安装尤其是对新手来说确实是个门槛。它不像MySQL那样一条apt-get install就能搞定需要更多的前置检查和配置。但别担心只要按步骤来完全可以一次成功。2.1 平台选择与安装包获取对于个人学习和入门我强烈建议在Linux环境下进行。这不仅是因为大多数生产环境的Oracle都跑在Linux上更因为Linux环境能让你更清晰地理解Oracle的进程、内存结构和文件组织。Windows环境下的安装虽然图形化更友好但容易掩盖很多细节。首先访问Oracle官方网站的下载页面。你需要注册一个免费的Oracle账户这很正常。搜索“Oracle Database 19c”或“21c”的Linux x86-64版本。你会看到类似LINUX.X64_193000_db_home.zip这样的安装包。这里有个关键点请务必下载“Release Update”版本而不是“Base Release”。RU版本包含了最新的补丁能避免很多已知的安装和运行问题。网络上流传的一些百度云盘分享的安装包版本可能陈旧且存在安全隐患不推荐使用。除了数据库软件包另一个至关重要的文件是p35940989_190000_Linux-x86-64.zip这样的补丁包编号。对于19.3的基版本通常需要应用这个“Release Update 19.13”的补丁。我的经验是先解压主安装包在运行安装程序runInstaller之前就应用最新的RU补丁这被称为“Out-of-Place”打补丁方式比安装后再打要干净、省事得多。2.2 系统环境预配置细节决定成败这是安装成功的关键90%的安装失败都源于此。你需要以root身份逐一检查和配置以下项目内核参数调整编辑/etc/sysctl.conf文件确保以下参数满足最小值。这些参数定义了系统级的内存、信号量、网络等资源限制Oracle是个资源大户默认的Linux配置不够用。fs.aio-max-nr 1048576 fs.file-max 6815744 kernel.shmall 2097152 # 共享内存总页数 kernel.shmmax 4294967296 # 单个共享内存段最大字节数建议设为物理内存一半以上 kernel.shmmni 4096 kernel.sem 250 32000 100 128 net.ipv4.ip_local_port_range 9000 65500 net.core.rmem_default 262144 net.core.rmem_max 4194304 net.core.wmem_default 262144 net.core.wmem_max 1048576修改后执行sysctl -p使其生效。shmmax参数特别重要设置过小会导致实例启动失败。用户与组创建Oracle强烈建议使用独立的用户和组来安装、运行数据库这符合最小权限原则。groupadd -g 54321 oinstall groupadd -g 54322 dba groupadd -g 54323 oper useradd -u 54321 -g oinstall -G dba,oper oracle echo “oracle” | passwd --stdin oracle # 为oracle用户设置密码资源限制配置编辑/etc/security/limits.conf在文件末尾为oracle用户添加oracle soft nproc 2047 oracle hard nproc 16384 oracle soft nofile 1024 oracle hard nofile 65536 oracle soft stack 10240 oracle hard stack 32768这保证了Oracle进程有足够的进程数、文件描述符和栈空间。目录创建与权限设置创建Oracle的基目录和软件目录并赋予正确的权限。这是最佳实践路径。mkdir -p /u01/app/oracle mkdir -p /u01/app/oraInventory chown -R oracle:oinstall /u01/app chmod -R 775 /u01/app环境变量配置切换到oracle用户(su - oracle)编辑其家目录下的.bash_profile添加以下核心变量export ORACLE_BASE/u01/app/oracle export ORACLE_HOME$ORACLE_BASE/product/19.3.0/dbhome_1 export ORACLE_SIDorcl # 你的实例名可自定义 export PATH$ORACLE_HOME/bin:$PATH export LD_LIBRARY_PATH$ORACLE_HOME/lib:$LD_LIBRARY_PATH export NLS_LANGAMERICAN_AMERICA.AL32UTF8 # 设置字符集避免中文乱码 注意ORACLE_SID是实例标识符在同一个服务器上必须唯一。NLS_LANG的设置至关重要它决定了客户端工具的字符集若与数据库字符集不匹配中文数据就会显示为乱码。2.3 运行安装程序与建库完成上述配置后注销并重新以oracle用户登录使环境变量生效。将下载的安装包和补丁包上传至服务器解压。先应用补丁假设补丁包已解压到/path/to/patchcd $ORACLE_HOME opatchauto apply /path/to/patch等待补丁应用完成。进入解压后的数据库安装包目录运行图形化安装程序./runInstaller如果服务器没有图形界面可以通过设置DISPLAY变量将界面转发到有X11服务的本地机器或者使用静默安装方式。在安装向导中选择“仅安装数据库软件”稍后再用DBCA建库。这样步骤更清晰。选择“单实例数据库安装”。在“典型安装”配置中确认ORACLE_BASE、ORACLE_HOME路径正确。操作系统组选择dba。最后安装程序会提示你以root身份运行两个脚本/u01/app/oraInventory/orainstRoot.sh和$ORACLE_HOME/root.sh。务必按顺序执行并注意观察脚本输出有无报错。使用DBCA建库软件安装成功后在终端输入dbca启动数据库配置助手。选择“创建数据库”建议选择“高级模式”以获得更多控制权。数据库类型对于学习选择“一般用途或事务处理”。数据库标识全局数据库名设为orcl.yourdomain.com可简化为orclSID保持为orcl。管理选项取消勾选“配置企业管理器”初学可以简化。数据库身份证明为所有管理账户SYS, SYSTEM等设置统一密码务必牢记。存储位置使用“文件系统”存储位置默认为$ORACLE_BASE/oradata即可。快速恢复区启用并设置一个路径如$ORACLE_BASE/fast_recovery_area这是RMAN备份的默认区域。数据库字符集这是重中之重。选择AL32UTF8Unicode UTF-8编码。这是目前最通用、支持最好的字符集除非你有非常明确的遗留系统兼容需求否则不要选择ZHS16GBK等区域性字符集。后续步骤保持默认最后生成创建脚本并执行。这个过程会持续十几到几十分钟请耐心等待。安装完成后使用sqlplus / as sysdba连接执行SELECT status FROM v$instance;看到OPEN状态就大功告成了。3. 核心概念与SQL操作构建你的第一块积木数据库安装好了我们终于可以开始和它对话了。对话的语言就是SQL。Oracle全面支持标准SQL并拥有其强大的扩展PL/SQL。我们从最基础的开始。3.1 连接数据库与基础对象操作首先学会连接。最原始也最强大的工具是sqlplus。sqlplus username/passwordhostname:port/service_name # 例如连接本地刚建好的orcl库 sqlplus system/your_passwordlocalhost:1521/orcl如果是在数据库服务器本机可以使用操作系统认证免密码登录为超级管理员sqlplus / as sysdba。注意sysdba权限极大日常操作切勿使用。连接成功后我们来创建第一个表空间、用户和表。-- 1. 创建表空间数据文件的逻辑容器 CREATE TABLESPACE mytbs DATAFILE /u01/app/oracle/oradata/orcl/mytbs01.dbf SIZE 100M AUTOEXTEND ON NEXT 10M MAXSIZE UNLIMITED EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO; -- 解释创建了一个名为mytbs的表空间初始数据文件100M用满后自动扩展10M不设上限。本地管理区自动段空间管理是现代Oracle的默认推荐。 -- 2. 创建用户并指定默认表空间 CREATE USER myuser IDENTIFIED BY mypassword DEFAULT TABLESPACE mytbs QUOTA UNLIMITED ON mytbs; -- 解释创建用户myuser密码mypassword其创建的对象默认存放在mytbs表空间且在该表空间上配额无限制。 -- 3. 授予基本权限 GRANT CREATE SESSION, CREATE TABLE, CREATE VIEW, CREATE SEQUENCE TO myuser; -- 解释授予连接数据库、创建表、视图、序列的权限。这是最基础的资源创建权限。 -- 4. 切换到新用户连接 CONNECT myuser/mypasswordorcl -- 5. 创建第一张表 CREATE TABLE employees ( emp_id NUMBER(10) PRIMARY KEY, emp_name VARCHAR2(50) NOT NULL, hire_date DATE DEFAULT SYSDATE, salary NUMBER(10, 2), department_id NUMBER(6) ); -- 解释创建员工表。NUMBER是精度数字类型VARCHAR2是变长字符串Oracle推荐用VARCHAR2而非VARCHARDATE是日期类型。PRIMARY KEY定义主键约束NOT NULL是非空约束DEFAULT设置默认值。3.2 数据操作语言与基础查询有了表就可以进行增删改查。-- 插入数据 INSERT INTO employees (emp_id, emp_name, salary, department_id) VALUES (1, ‘张三’, 8000.00, 10); INSERT INTO employees VALUES (2, ‘李四’, DATE ‘2023-05-01’, 9500.00, 20); -- 第二种写法必须按表结构顺序提供所有列的值。 -- 查询数据 SELECT * FROM employees; -- 查询所有列 SELECT emp_name, salary FROM employees WHERE department_id 10; -- 带条件的查询 SELECT emp_name, salary * 12 as annual_salary FROM employees; -- 使用表达式和别名 -- 更新数据 UPDATE employees SET salary salary * 1.1 WHERE department_id 10; -- 给10号部门员工加薪10% COMMIT; -- 提交事务使更改永久化。在SQL*Plus中默认不会自动提交。 -- 删除数据 DELETE FROM employees WHERE emp_id 2; ROLLBACK; -- 回滚事务撤销刚才的删除操作。数据恢复。 TRUNCATE TABLE employees; -- 快速清空整张表不可回滚效率远高于DELETE。3.3 约束的深入理解与应用约束是保证数据完整性的核心机制。上面我们用到了PRIMARY KEY和NOT NULL。这里系统性地讲解一下主键约束唯一且非空一张表只能有一个。可以是单列也可以是组合多列复合主键。CREATE TABLE orders ( order_id NUMBER, product_id NUMBER, quantity NUMBER, PRIMARY KEY (order_id, product_id) -- 复合主键 );唯一约束保证列值唯一但允许有空值Oracle中空值不参与唯一性比较。ALTER TABLE employees ADD CONSTRAINT uk_emp_email UNIQUE (email);外键约束建立表间关联保证引用完整性。CREATE TABLE departments ( dept_id NUMBER(6) PRIMARY KEY, dept_name VARCHAR2(50) ); -- 为employees表的department_id添加外键引用departments表的主键 ALTER TABLE employees ADD CONSTRAINT fk_emp_dept FOREIGN KEY (department_id) REFERENCES departments(dept_id); -- 外键行为默认情况下如果departments表中的某行被删除而employees表还有记录引用它则会报错。 -- 可以指定ON DELETE CASCADE级联删除或ON DELETE SET NULL设为空。检查约束自定义业务规则。ALTER TABLE employees ADD CONSTRAINT ck_salary CHECK (salary 0); 实操心得关于约束的命名我强烈建议使用显式命名如CONSTRAINT pk_emp_id而不是依赖Oracle的系统自动命名如SYS_C0012345。这样在后续的错误排查、文档编写和性能分析中你能一眼就知道这个约束是干什么的管理起来方便得多。4. PL/SQL编程入门让数据库拥有“大脑”SQL是声明式的告诉数据库“要什么”。而PL/SQL是过程式的可以告诉数据库“怎么一步步做”。它是Oracle数据库的编程语言能力强大可以直接在数据库端执行业务逻辑。4.1 匿名块与基本结构PL/SQL程序的基本单元是“块”。一个匿名块的结构如下DECLARE -- 声明部分定义变量、常量、游标等。 v_emp_name employees.emp_name%TYPE; -- 使用%TYPE引用表中列的类型这是好习惯 v_bonus NUMBER : 0; -- 声明并初始化变量 BEGIN -- 执行部分逻辑代码写在这里。 SELECT emp_name INTO v_emp_name FROM employees WHERE emp_id 1; IF v_emp_name ‘张三’ THEN v_bonus : 1000; ELSE v_bonus : 500; END IF; DBMS_OUTPUT.PUT_LINE(‘员工’ || v_emp_name || ‘的奖金是’ || v_bonus); EXCEPTION -- 异常处理部分当执行部分发生错误时跳转到这里。 WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE(‘未找到该员工’); WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(‘发生未知错误’ || SQLERRM); END; /要看到DBMS_OUTPUT的输出需要在SQL*Plus或SQL Developer中先执行SET SERVEROUTPUT ON。4.2 存储过程与函数匿名块不能保存可复用的代码需要写成存储过程或函数。存储过程执行一系列操作不必须返回值。CREATE OR REPLACE PROCEDURE raise_salary ( p_dept_id IN employees.department_id%TYPE, p_ratio IN NUMBER ) AS v_count NUMBER; BEGIN -- 更新指定部门员工的薪水 UPDATE employees SET salary salary * (1 p_ratio) WHERE department_id p_dept_id; -- 获取更新的行数 v_count : SQL%ROWCOUNT; COMMIT; DBMS_OUTPUT.PUT_LINE(‘成功为’ || v_count || ‘名员工加薪。’); EXCEPTION WHEN OTHERS THEN ROLLBACK; RAISE; -- 将异常再次抛出让调用者知晓 END raise_salary; / -- 调用存储过程 EXEC raise_salary(p_dept_id 10, p_ratio 0.05);函数必须返回一个值通常用于计算。CREATE OR REPLACE FUNCTION get_annual_salary ( p_emp_id IN employees.emp_id%TYPE ) RETURN NUMBER AS v_salary employees.salary%TYPE; BEGIN SELECT salary INTO v_salary FROM employees WHERE emp_id p_emp_id; RETURN v_salary * 12; EXCEPTION WHEN NO_DATA_FOUND THEN RETURN 0; -- 未找到员工返回0 END get_annual_salary; / -- 在SQL中调用函数 SELECT emp_name, get_annual_salary(emp_id) as annual FROM employees;4.3 游标的使用逐行处理结果集当查询返回多行数据时需要使用游标来逐行处理。DECLARE CURSOR cur_emp IS SELECT emp_id, emp_name, salary FROM employees WHERE department_id 10; v_emp_id employees.emp_id%TYPE; v_emp_name employees.emp_name%TYPE; v_salary employees.salary%TYPE; BEGIN OPEN cur_emp; LOOP FETCH cur_emp INTO v_emp_id, v_emp_name, v_salary; EXIT WHEN cur_emp%NOTFOUND; -- 没有更多行时退出循环 -- 对每一行数据进行处理 IF v_salary 10000 THEN DBMS_OUTPUT.PUT_LINE(v_emp_name || ‘需要加薪’); END IF; END LOOP; CLOSE cur_emp; END; /更现代的写法是使用FOR ... IN LOOP它能自动打开、获取、关闭游标更简洁安全。BEGIN FOR emp_rec IN (SELECT emp_id, emp_name, salary FROM employees WHERE department_id 10) LOOP DBMS_OUTPUT.PUT_LINE(‘处理员工’ || emp_rec.emp_name); -- 通过emp_rec.列名 访问数据 END LOOP; END; /5. 性能基础与日常管理从能用走向好用数据库不能只建不管。了解一些基本的性能知识和日常管理操作能让你的数据库运行得更顺畅。5.1 执行计划看懂SQL的“体检报告”当一条SQL语句跑得慢时第一件事就是查看它的执行计划。执行计划显示了Oracle将如何执行这条SQL走哪个索引、用什么连接方式等。最常用的方法是使用EXPLAIN PLAN FOREXPLAIN PLAN FOR SELECT e.emp_name, d.dept_name FROM employees e JOIN departments d ON e.department_id d.dept_id WHERE e.salary 5000; -- 查看生成的执行计划 SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);输出结果中你需要关注Operation操作类型如TABLE ACCESS FULL全表扫描通常不好、INDEX RANGE SCAN索引范围扫描好。Name操作的对象表名或索引名。RowsOracle预估的返回行数。CostOracle计算出的成本值是一个相对值用于比较不同执行计划的优劣。Predicate Information过滤条件。 避坑技巧如果发现某张大表经常TABLE ACCESS FULL而查询条件中的列有选择性即能过滤掉大部分数据就应该考虑为该列创建索引。CREATE INDEX idx_emp_salary ON employees(salary); CREATE INDEX idx_emp_dept ON employees(department_id, hire_date); -- 复合索引创建索引不是越多越好索引会占用空间并降低INSERT/UPDATE/DELETE的速度。通常只为高频查询的WHERE条件列、JOIN列和ORDER BY列创建索引。5.2 基础监控与维护语句作为DBA或开发者以下是一些你每天或每周都可能用到的语句查看数据库状态和会话SELECT instance_name, status, database_status FROM v$instance; SELECT sid, serial#, username, program, status FROM v$session; -- 查看当前所有会话 SELECT count(*) FROM v$session WHERE status ‘ACTIVE’; -- 查看活跃会话数查看表空间使用情况SELECT tablespace_name, ROUND(SUM(bytes) / 1024 / 1024, 2) total_mb, ROUND(SUM(bytes - NVL(free_space, 0)) / 1024 / 1024, 2) used_mb, ROUND((SUM(bytes - NVL(free_space, 0)) / SUM(bytes)) * 100, 2) pct_used FROM (SELECT tablespace_name, file_id, SUM(bytes) bytes FROM dba_data_files GROUP BY tablespace_name, file_id) df LEFT JOIN (SELECT tablespace_name, file_id, SUM(bytes) free_space FROM dba_free_space GROUP BY tablespace_name, file_id) fs USING (tablespace_name, file_id) GROUP BY tablespace_name;定期检查防止表空间爆满导致业务中断。收集统计信息Oracle优化器依赖统计信息来生成好的执行计划。统计信息过旧会导致性能下降。-- 收集单张表的统计信息 EXEC DBMS_STATS.GATHER_TABLE_STATS(ownname ‘MYUSER’, tabname ‘EMPLOYEES’, estimate_percent 20, cascade TRUE); -- estimate_percent: 采样百分比对于大表不要用100%20-30%通常足够。 -- cascade: TRUE表示同时收集索引的统计信息。对于生产系统通常使用自动统计信息收集任务但了解手动收集方法在排查问题时很有用。简单的锁排查-- 查看当前被锁定的对象 SELECT l.session_id sid, s.serial#, l.locked_mode, o.object_name, s.username, s.osuser FROM v$locked_object l, dba_objects o, v$session s WHERE l.object_id o.object_id AND l.session_id s.sid; -- 如果发现死锁或长时间锁可以强制结束会话谨慎操作 -- ALTER SYSTEM KILL SESSION ‘sid,serial#’;6. 常见问题与实战排查实录理论说再多不如踩一次坑。下面是我在多年实践中总结的几个新手高频问题及其解决方法。6.1 安装与连接类问题问题1安装时runInstaller弹不出图形界面。排查确保已正确设置DISPLAY环境变量如export DISPLAYlocalhost:10.0并且本地X11服务如Xming, VcXsrv已启动并允许远程连接。备选方案使用静默安装。先通过runInstaller -record -destinationFile /tmp/install.rsp生成响应文件模板编辑该文件后使用runInstaller -silent -responseFile /tmp/install.rsp进行安装。问题2sqlplus连接时报错“ORA-12541: TNS:no listener”。排查监听器服务没启动。切换到oracle用户执行lsnrctl status查看状态lsnrctl start启动监听。深入监听器配置在$ORACLE_HOME/network/admin/listener.ora中。默认配置通常够用但如果修改了端口或使用了非标准服务名需要检查配置。问题3远程客户端无法连接。排查服务器防火墙是否开放了1521端口默认端口firewall-cmd --query-port1521/tcp。监听器是否配置了正确的主机名或IP检查listener.ora中的HOST。数据库服务是否注册到了监听器在服务器上sqlplus / as sysdba执行ALTER SYSTEM REGISTER;然后lsnrctl services查看。客户端tnsnames.ora文件配置是否正确需要正确配置主机、端口和服务名。6.2 SQL与PL/SQL开发类问题问题4查询中文数据出现乱码。原因客户端如SQL*Plus, SQL Developer的字符集由NLS_LANG环境变量决定与数据库服务器字符集不匹配。解决查询数据库字符集SELECT parameter, value FROM nls_database_parameters WHERE parameter LIKE ‘%CHARACTERSET’;设置客户端字符集。例如数据库是AL32UTF8则在客户端环境Windows系统变量或Linux.bash_profile中设置NLS_LANGAMERICAN_AMERICA.AL32UTF8。对于Windows上的SQL*Plus这个设置尤其关键。问题5PL/SQL中DBMS_OUTPUT.PUT_LINE不输出。解决在工具中需要先开启输出缓冲区。在SQL*Plus中执行SET SERVEROUTPUT ON SIZE UNLIMITED。在SQL Developer中查看“视图”菜单下的“DBMS输出”面板并点击绿色的“”号添加连接。问题6执行UPDATE/DELETE后忘记COMMIT或ROLLBACK导致表被锁。现象其他会话对该表的操作尤其是DML挂起。排查使用SELECT * FROM v$locked_object;和SELECT * FROM v$session WHERE sid IN (...);找到阻塞的会话。解决让原会话执行COMMIT或ROLLBACK。如果原会话已断开可能需要DBA介入通过ALTER SYSTEM KILL SESSION终止该会话。生产环境慎用KILL。6.3 性能与运维类问题问题7应用突然变慢发现大量会话在等待“enq: TX - row lock contention”。诊断这是行锁等待通常是因为一个事务长时间锁定了某些行比如更新了大批量数据没提交而其他事务也要修改这些行。排查查询v$session找到BLOCKING_SESSION不为空的会话它就是阻塞者。查看它在执行什么SQL。解决联系阻塞会话的持有者提交或回滚事务。如果是无人值守的批处理作业卡住可能需要评估后强制KILL。问题8临时表空间或UNDO表空间不足。现象执行复杂排序或大量DML操作时报错“ORA-01652: unable to extend temp segment”或“ORA-30036: unable to extend segment in undo tablespace”。临时表空间解决-- 查看临时表空间使用率 SELECT * FROM dba_temp_free_space; -- 为临时表空间添加数据文件 ALTER TABLESPACE TEMP ADD TEMPFILE ‘/u01/app/oracle/oradata/orcl/temp02.dbf’ SIZE 2G AUTOEXTEND ON;UNDO表空间解决-- 查看UNDO表空间使用情况 SELECT tablespace_name, status, SUM(bytes)/1024/1024 size_mb FROM dba_undo_extents GROUP BY tablespace_name, status; -- 添加数据文件或创建新的UNDO表空间并切换 CREATE UNDO TABLESPACE undotbs2 DATAFILE ‘/path/to/undotbs2.dbf’ SIZE 10G; ALTER SYSTEM SET undo_tablespaceundotbs2 SCOPEBOTH; -- 等旧的UNDO表空间段过期后再删除它。问题9如何查看一条正在运行的慢SQL的执行计划方法找到该SQL的SQL_ID。-- 从v$session中找到慢会话的SQL_ID SELECT sid, serial#, sql_id, sql_child_number FROM v$session WHERE username ‘MYUSER’ AND status ‘ACTIVE’; -- 使用DBMS_XPLAN显示该SQL的实时执行计划 SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(‘sql_id’, child_number));这比EXPLAIN PLAN更准确因为它显示的是实际运行时采用的计划。学习Oracle是一个持续的过程这个教程涵盖了从安装到基础开发、再到简单运维的核心路径。真正的精通来自于在真实项目中的实践、踩坑和解决问题。建议你在自己的实验环境中反复练习这里的每一个步骤和命令尝试去破坏它比如填满表空间、制造死锁然后再修复它这个过程会让你成长飞快。记住官方文档是你的终极武器遇到任何不确定的问题去查Oracle官方文档总是最靠谱的。