一、题目相关
1.英文题目和英语选项和答案
Question #16, Topic 1
Which three statements are true about dropping and unused columns in an Oracle database? (Choose three.)
Options:
- A. A primary key column referenced by another column as a foreign key can be dropped if using the CASCADE option. (Most Voted)
- B. An UNUSED column's space is reclaimed automatically when the block containing that column is next queried.
- C. An UNUSED column's space is reclaimed automatically when the row containing that column is next queried.
- D. Partition key columns cannot be dropped. (Most Voted)
- E. A DROP COLUMN command can be rolled back
- F. A column that is set to UNUSED still counts towards the limit of 1000 columns per table (Most Voted)
Correct Answer: A, D, F
2.题目和选项的翻译,答案
题干翻译:
关于 Oracle 数据库中删除列(dropping)和未使用列(unused columns) ,下面哪三个陈述是正确的?(选三个)
选项翻译:
- A. 如果一个主键列被另一个列以外键方式引用 ,那么使用 CASCADE 选项就可以把它删掉。
- B. 当一个包含 UNUSED 列的数据块(block)下一次被查询时,该列占用的空间会被自动回收。
- C. 当一个包含 UNUSED 列的行(row)下一次被查询时,该列占用的空间会被自动回收。
- D. **分区键列(partition key columns)**不能被删除。
- E.
DROP COLUMN命令可以回滚(rolled back)。 - F. 被设置为 UNUSED 的列,仍然计入每张表 1000 列的上限之中。
答案:A、D、F
💡 一句话剧透:这道题考的就是 Oracle 对"删列"和"闲置列"的一堆硬性规矩。A(级联删主键列)、D(分区键不能动)、F(闲置列也算名额)是铁律;而 B/C(自动回收空间)和 E(能回滚)是典型的"想当然"陷阱。
3.考察的知识点摘要
| 序号 | 知识点 | 一句话理解 |
|---|---|---|
| 1 | SET UNUSED 与 DROP COLUMN 的区别 |
SET UNUSED = "标记退役,不真删";DROP COLUMN = 真正删除 |
| 2 | CASCADE CONSTRAINTS | 删被外键引用的主键列时,靠它级联清除约束 |
| 3 | 分区键列不可删除 | 删分区键会报 ORA-12984 |
| 4 | DDL 不可回滚 | DROP COLUMN 是 DDL,自动提交,ROLLBACK 无效 |
| 5 | UNUSED 列仍占 1000 列限额 | 不真正 DROP,它就一直"占坑" |
| 6 | UNUSED 空间回收方式 | 只能靠 ALTER TABLE ... DROP UNUSED COLUMNS 显式回收,查询不会自动回收 |
4.题目解析
咱们先把 6 个选项挨个"过堂",配合真实实验场景 👇
🔹 A. 被外键引用的主键列,用 CASCADE 就能删 ------ ✅ 正确(Most Voted)
主键列如果被别的外键"盯上"(引用),直接 DROP COLUMN 会报错。但只要加上 CASCADE CONSTRAINTS (题里说的 CASCADE option),Oracle 就会连带着把引用它的外键约束一起干掉,列也就删掉了。所以 A 对。
🔹 D. 分区键列不能删 ------ ✅ 正确(Most Voted)
分区表的分区键 决定了数据按哪个键值分到哪个分区,是分区的"命根子"。你要是把它删了,整个分区结构就崩了。Oracle 直接甩你一个 ORA-12984: cannot drop partitioning column。所以 D 对。
🔹 F. UNUSED 列仍计入 1000 列上限 ------ ✅ 正确(Most Voted)
SET UNUSED 只是给列打个"退役"标记,物理上它还在表里躺着 ,并不释放"每表最多 1000 列"的名额。官方文档原话:"Until you actually drop these columns, they continue to count toward the absolute limit of 1000 columns." 所以 F 对。
🔹 B. block 被查询时自动回收 UNUSED 空间 ------ ❌ 错误
查询(query)不会触发空间回收 。UNUSED 列的空间,要么等你显式执行 ALTER TABLE ... DROP UNUSED COLUMNS,要么(在 19c 某些场景下)是更新(update)行时才可能清理------绝不是"查一下就回收"。而且 B 说的是"block 级别查询",更不对。
🔹 C. row 被查询时自动回收 UNUSED 空间 ------ ❌ 错误
跟 B 一伙的坑。同样是"查询自动回收"这个错误前提。就算 19c 有延迟清理,触发条件是 UPDATE 不是 QUERY。所以 C 错。
🔹 E. DROP COLUMN 可以回滚 ------ ❌ 错误
DROP COLUMN 是 DDL 语句 ,Oracle 执行 DDL 时会先隐式 COMMIT,执行完再隐式 COMMIT,根本没法 ROLLBACK。这是所有 DDL 的通病,E 错。
⚠️ 一个易混点(考试常挖坑):
SET UNUSED≠ 真删:只是标记,列还占坑(对应 F 正确)、空间不释放(对应 B/C 错)。- 想彻底清理,必须再来一条
ALTER TABLE ... DROP UNUSED COLUMNS------这才是"唯一允许对 unused 列做的操作",也才真正回收磁盘空间。
5.考察的知识点详情
下面用 Oracle 实操场景逐个击破,帮你把这套"删列/闲置列"彻底玩明白。假设以普通用户登录,先建两张测试表:
sql
CREATE TABLE orders (
ord_no NUMBER PRIMARY KEY,
cust_no NUMBER,
amount NUMBER
);
CREATE TABLE order_items (
item_no NUMBER,
ord_no NUMBER,
product VARCHAR2(50),
CONSTRAINT fk_ord FOREIGN KEY (ord_no) REFERENCES orders(ord_no)
);
INSERT INTO orders VALUES (1, 100, 999);
INSERT INTO order_items VALUES (1, 1, 'Keyboard');
COMMIT;
1️⃣ CASCADE CONSTRAINTS 删被引用的主键列(对应选项 A)
❌ 不加 CASCADE ------ 报错:
sql
ALTER TABLE orders DROP COLUMN ord_no;
-- ORA-12991: column is referenced by a constraint (fk_ord)
✅ 加 CASCADE CONSTRAINTS ------ 成功:
sql
ALTER TABLE orders DROP COLUMN ord_no CASCADE CONSTRAINTS;
-- 主键列删掉了,order_items 上的外键约束 fk_ord 也被一并级联删除
📌 这就是 A 选项的正确姿势:CASCADE = "连引用它的约束一起带走"。
2️⃣ 分区键列不能删(对应选项 D)
sql
CREATE TABLE sales (
sale_id NUMBER,
sale_date DATE
) PARTITION BY RANGE (sale_date) (
PARTITION p1 VALUES LESS THAN (DATE '2023-01-01'),
PARTITION p2 VALUES LESS THAN (DATE '2024-01-01')
);
ALTER TABLE sales DROP COLUMN sale_date;
-- ORA-12984: cannot drop partitioning column
📌 sale_date 是分区键,删它 Oracle 直接拒绝。要改分区键只能重建表。D 对。
3️⃣ DDL 不可回滚(对应选项 E)
sql
ALTER TABLE orders DROP COLUMN cust_no; -- 假设列存在
ROLLBACK;
-- 没用!DROP COLUMN 是 DDL,早已自动提交,列已经没了
📌 记住口诀:DDL = 自动提交 = 无法回滚 。E 错得彻彻底底。想"后悔"只能靠闪回(Flashback)或备份恢复,ROLLBACK 帮不上忙。
4️⃣ SET UNUSED vs DROP COLUMN(对应 F、B、C)
sql
-- 先给 orders 加几列方便演示
ALTER TABLE orders ADD (col_a NUMBER, col_b NUMBER);
-- 方式一:SET UNUSED(标记退役,不真删)
ALTER TABLE orders SET UNUSED (col_a);
-- 此时 col_a 已不可访问,但仍占 1000 列的名额 → 对应 F 正确
-- 方式二:真正删除
ALTER TABLE orders DROP COLUMN col_b; -- DDL,立即生效且不可回滚
验证 F(UNUSED 仍占 1000 列限额):
sql
-- 当表接近 1000 列时,把一些列 SET UNUSED 并不会腾出"列数名额"
-- 只有真正 DROP 掉,名额才释放
SELECT COUNT(*) FROM user_tab_cols WHERE table_name = 'ORDERS';
验证 B/C(空间不会因查询自动回收):
sql
SELECT * FROM orders; -- 随便查,col_a 的空间纹丝不动 ❌不会回收
-- 唯一正确的回收姿势:显式 DROP UNUSED COLUMNS
ALTER TABLE orders DROP UNUSED COLUMNS; -- ✅ 这时才真正移除列、回收磁盘空间
📌 B/C 为什么错 :关键词是"queried(查询) "。查询从来不回收空间;回收要么靠上面这条显式命令,要么 19c 里是"更新行(update)"才可能顺带清理------绝不是查询。所以 B、C 都错。
5️⃣ 完整工作流小结(DBA 必备)
sql
-- Step 1:业务低峰期,先标记退役(速度快,不锁太久)
ALTER TABLE huge_table SET UNUSED (old_col);
-- Step 2:空闲时,真正删除并回收空间
ALTER TABLE huge_table DROP UNUSED COLUMNS CHECKPOINT 1000;
-- CHECKPOINT 分批提交,避免大表长时间锁表
6️⃣ 几个 DBA 必记的"坑"
- 🔴
SET UNUSED是单向操作:标记后列立刻不可访问,数据也读不回来了,慎用。 - 🔴 UNUSED 列只能通过
DROP UNUSED COLUMNS清理,没有其他操作允许作用在它身上。 - 🟡 压缩表 + UNUSED 列 容易撞 ORA-01792(超过 1000 列),MOS 文档 Doc ID 2259600.1 有专门说明------这正是 F 选项的现实来源。
- 🟡 CASCADE 会连带删约束,生产环境先查
user_constraints确认影响,别盲目级联。
好问题!这个 UNUSED 是 Oracle 里一个特别实用、但又容易让人迷糊的概念。一句话先给结论:
UNUSED 列 = 被"打上退役标签"的列------Oracle 假装它不存在了,但它其实还躺在表里没走。
下面我用 DBA 小白最好懂的方式讲透它。
二、UNUSED 列是啥?
1.先搞清楚:为什么要"闲置列"这种东西?
想象一下这个场景👇
你有一张几十亿行的大表,现在业务改造,决定不要某一列了。如果你直接:
sql
ALTER TABLE huge_table DROP COLUMN old_col;
会发生什么?Oracle 得逐行扫描、把每一行的这个列数据抠掉 ------几十亿行啊,耗时巨久、锁表巨长、日志巨多,业务直接卡死。
于是 Oracle 想了个聪明的折中方案:
"要不咱先不真删,只是给它贴个'退役'标签,让所有人当它不存在?等哪天业务不忙了,再偷偷彻底删掉?"
这个"退役标签",就是 UNUSED。
2.UNUSED 列到底是什么状态 🔍
用一句话 + 一个比喻:
UNUSED 列 ≈ 公司里的"退休员工" :花名册上还占着编制(占名额),工位也还没腾(占空间),但门禁卡注销了、谁也联系不上他了(不能访问)。
具体来说,一列被 SET UNUSED 后:
| 维度 | 表现 |
|---|---|
| 能不能 SELECT / INSERT / UPDATE? | ❌ 不行,像"消失"了一样 |
| 还在不在表结构里? | ✅ 还在,占着"每表 1000 列"的名额 |
| 磁盘空间释放了吗? | ❌ 没释放,数据还占着块 |
| 还能恢复回来吗? | ❌ 不行,标记不可逆 |
| 怎么才能真正删掉? | ALTER TABLE ... DROP UNUSED COLUMNS |
3.动手看看:UNUSED 列长啥样
1️⃣ 建表 + 标记退役
sql
CREATE TABLE employees (
emp_id NUMBER,
name VARCHAR2(50),
old_phone NUMBER, -- 打算废弃的旧电话列
salary NUMBER
);
-- 把它标记为 UNUSED
ALTER TABLE employees SET UNUSED (old_phone);
2️⃣ 试试访问它 → 直接报错
sql
SELECT old_phone FROM employees;
-- ORA-00904: "OLD_PHONE": invalid identifier
📌 对外的感觉就像"这列蒸发了",但其实它还在底层躺着。
3️⃣ 去数据字典里抓它 → 藏在 USER_TAB_COLS 里
sql
SELECT column_name, hidden_column, unused_column
FROM user_tab_cols
WHERE table_name = 'EMPLOYEES';
你会看到 old_phone 的 UNUSED_COLUMN = YES。
⚠️ 注意:普通的
USER_TAB_COLUMNS视图看不到 UNUSED 列,得用USER_TAB_COLS才能揪出来。这也是它"对外隐身"的体现。
4.UNUSED 的两大"坑点"(正是上一题考点)
🔴 坑点 1:它占着 1000 列的名额不放
Oracle 规定一张表最多 1000 列 。你以为 SET UNUSED 就腾出名额了?想多了,名额照占!
sql
-- 假设表已经有 999 列,再把 1 列 SET UNUSED
ALTER TABLE t SET UNUSED (col_x); -- col_x 退役了
-- 你以为能加新列?错!
ALTER TABLE t ADD (col_new NUMBER);
-- ORA-01792: maximum number of columns in a table or view is 1000
📌 只有真正 DROP 掉,名额才释放。 这就是上一题 F 选项正确的原因。
🔴 坑点 2:它的空间不会自动回收
你以为放着不管它会慢慢"自己消失"?不会。 查询、更新都不会自动清理它。
唯一的"清道夫"命令:
sql
ALTER TABLE employees DROP UNUSED COLUMNS;
-- ✅ 这时 old_phone 才被真正移除,磁盘空间才回收
大表怕锁太久?分批来:
sql
ALTER TABLE huge_table DROP UNUSED COLUMNS CHECKPOINT 1000;
-- 每处理 1000 行提交一次,避免长时间锁表
5.SET UNUSED vs DROP COLUMN 对照表 ⚖️
| 对比项 | SET UNUSED |
DROP COLUMN |
|---|---|---|
| 速度 | ⚡ 极快(只改字典) | 🐢 慢(逐行清数据) |
| 锁表时长 | 很短 | 很长(大表灾难) |
| 数据是否还在 | ✅ 还在(不可访问) | ❌ 真删了 |
| 空间是否释放 | ❌ 不释放 | ✅ 释放 |
| 能否回滚 | 否(DDL) | 否(DDL) |
| 是否占 1000 名额 | ✅ 占 | ❌ 不占 |
| 适用场景 | 大表、业务高峰 | 小表、空闲时 |
6.标准工作流(DBA 最佳实践)💼
sql
-- Step 1【业务运行时】:先快速标记退役,几乎不影响业务
ALTER TABLE huge_table SET UNUSED (old_col);
-- Step 2【业务低谷期】:再彻底清理 + 回收空间
ALTER TABLE huge_table DROP UNUSED COLUMNS CHECKPOINT 1000;
📌 这就是 UNUSED 的设计初衷:把"耗时的真删除"推迟到合适的时间再做,两步走,业务丝滑不断档。
7.一句话总结(背下来)🎯
UNUSED 列 = "假删除 / 退役标记"。
- 对外:像消失了(不能访问);
- 对内:还赖着不走(占名额、占空间);
- 清理:只能靠
DROP UNUSED COLUMNS,查询和更新都不会自动回收。
顺口溜:"SET UNUSED 贴标签,列还在、名还在、空间还在;想彻底,DROP UNUSED 来清理;名额不腾别怪我,查询不收是真理。"
这样就把上一题 B/C(查询不回收)、E(DDL 不可回滚)、F(占 1000 名额) 三个选项为什么对/错,彻底串起来了------它们本质上都是在考你对 UNUSED 列"赖着不走"这个特性的理解。
最后,各位学习者,点个关注吧!我们一起成长,一起成为大佬!
📌 一句话记忆法(背下来考试稳):
删列三件套 ------ A 能删(CASCADE)、D 不能删(分区键)、F 占坑(1000 限额) ;
两大陷阱 ------ B/C 查询不回收(要 DROP UNUSED COLUMNS)、E 是 DDL 不能回滚。
顺口溜:"SET UNUSED 是标记,DROP 才真离;回收靠命令,查询不搭理;分区键别碰,外键要级联;DDL 不回头,名额照常占。"