Oracle表操作 #

一、表概述 #

1.1 表的分类 #

text
Oracle表类型
├── 堆组织表(Heap Table)
│   └── 默认表类型,数据无序存储
├── 索引组织表(IOT)
│   └── 按主键顺序存储数据
├── 外部表(External Table)
│   └── 访问外部文件数据
├── 临时表(Temporary Table)
│   └── 会话或事务级临时数据
├── 分区表(Partitioned Table)
│   └── 大表分区存储
└── 聚簇表(Clustered Table)
    └── 多表物理存储在一起

1.2 表的存储结构 #

text
表存储结构
├── 段(Segment)
│   └── 表占用的存储空间
├── 区(Extent)
│   └── 连续的数据块集合
├── 块(Block)
│   └── 最小I/O单位(默认8KB)
└── 行(Row)
    └── 实际数据记录

二、创建表 #

2.1 基本语法 #

sql
-- 创建表基本语法
CREATE TABLE table_name (
    column1 datatype [DEFAULT default_value] [NULL|NOT NULL],
    column2 datatype [DEFAULT default_value] [NULL|NOT NULL],
    ...
) [TABLESPACE tablespace_name];

2.2 创建简单表 #

sql
-- 创建员工表
CREATE TABLE employees (
    employee_id NUMBER(6) PRIMARY KEY,
    first_name VARCHAR2(50),
    last_name VARCHAR2(50) NOT NULL,
    email VARCHAR2(100) UNIQUE,
    phone_number VARCHAR2(20),
    hire_date DATE DEFAULT SYSDATE,
    job_id VARCHAR2(10),
    salary NUMBER(8,2),
    commission_pct NUMBER(2,2),
    manager_id NUMBER(6),
    department_id NUMBER(4)
);

-- 指定表空间
CREATE TABLE employees (
    employee_id NUMBER(6) PRIMARY KEY,
    first_name VARCHAR2(50),
    last_name VARCHAR2(50)
) TABLESPACE users_data;

-- 添加表注释
COMMENT ON TABLE employees IS '员工信息表';
COMMENT ON COLUMN employees.employee_id IS '员工ID';
COMMENT ON COLUMN employees.first_name IS '名';
COMMENT ON COLUMN employees.last_name IS '姓';

2.3 创建带约束的表 #

sql
-- 创建带完整约束的表
CREATE TABLE departments (
    department_id NUMBER(4) PRIMARY KEY,
    department_name VARCHAR2(30) NOT NULL,
    manager_id NUMBER(6),
    location_id NUMBER(4),
    
    CONSTRAINT uk_dept_name UNIQUE (department_name),
    CONSTRAINT fk_dept_manager FOREIGN KEY (manager_id) 
        REFERENCES employees(employee_id)
);

-- 创建带命名约束的表
CREATE TABLE orders (
    order_id NUMBER(10),
    customer_id NUMBER(6) NOT NULL,
    order_date DATE DEFAULT SYSDATE,
    total_amount NUMBER(12,2),
    status VARCHAR2(20),
    
    CONSTRAINT pk_orders PRIMARY KEY (order_id),
    CONSTRAINT chk_status CHECK (status IN ('PENDING', 'SHIPPED', 'DELIVERED')),
    CONSTRAINT chk_amount CHECK (total_amount >= 0)
);

2.4 使用子查询创建表 #

sql
-- 创建表并复制数据
CREATE TABLE employees_backup AS
SELECT * FROM employees;

-- 创建表结构(不复制数据)
CREATE TABLE employees_structure AS
SELECT * FROM employees WHERE 1=0;

-- 创建表并复制部分数据
CREATE TABLE high_salary_employees AS
SELECT employee_id, first_name, last_name, salary
FROM employees
WHERE salary > 10000;

-- 创建表并添加新列
CREATE TABLE employees_with_level AS
SELECT 
    employee_id,
    first_name,
    last_name,
    salary,
    CASE 
        WHEN salary >= 20000 THEN 'HIGH'
        WHEN salary >= 10000 THEN 'MEDIUM'
        ELSE 'LOW'
    END AS salary_level
FROM employees;

2.5 创建临时表 #

sql
-- 创建会话级临时表
CREATE GLOBAL TEMPORARY TABLE temp_session_data (
    id NUMBER,
    name VARCHAR2(100),
    create_time DATE DEFAULT SYSDATE
) ON COMMIT PRESERVE ROWS;

-- 创建事务级临时表
CREATE GLOBAL TEMPORARY TABLE temp_transaction_data (
    id NUMBER,
    value NUMBER
) ON COMMIT DELETE ROWS;

-- 临时表特点
-- 1. 数据只在会话或事务期间存在
-- 2. 结构永久保存
-- 3. 数据自动清理
-- 4. 不产生redo日志

2.6 创建索引组织表 #

sql
-- 创建索引组织表(IOT)
CREATE TABLE iot_employees (
    employee_id NUMBER(6) PRIMARY KEY,
    first_name VARCHAR2(50),
    last_name VARCHAR2(50),
    email VARCHAR2(100)
) ORGANIZATION INDEX;

-- 带溢出区的IOT
CREATE TABLE iot_orders (
    order_id NUMBER(10) PRIMARY KEY,
    customer_id NUMBER(6),
    order_date DATE,
    total_amount NUMBER(12,2),
    notes VARCHAR2(4000)
) ORGANIZATION INDEX
OVERFLOW TABLESPACE users_data;

-- IOT特点
-- 1. 按主键顺序存储
-- 2. 适合主键查询
-- 3. 节省存储空间

三、修改表 #

3.1 添加列 #

sql
-- 添加单列
ALTER TABLE employees ADD (
    middle_name VARCHAR2(50)
);

-- 添加多列
ALTER TABLE employees ADD (
    address VARCHAR2(200),
    city VARCHAR2(50),
    country VARCHAR2(50) DEFAULT 'China'
);

-- 添加带约束的列
ALTER TABLE employees ADD (
    status VARCHAR2(20) DEFAULT 'ACTIVE' NOT NULL,
    CONSTRAINT chk_emp_status CHECK (status IN ('ACTIVE', 'INACTIVE'))
);

3.2 修改列 #

sql
-- 修改列数据类型
ALTER TABLE employees MODIFY (
    first_name VARCHAR2(100)
);

-- 修改列约束
ALTER TABLE employees MODIFY (
    phone_number VARCHAR2(20) NOT NULL
);

-- 修改列默认值
ALTER TABLE employees MODIFY (
    hire_date DATE DEFAULT SYSDATE
);

-- 修改多列
ALTER TABLE employees MODIFY (
    first_name VARCHAR2(100),
    last_name VARCHAR2(100) NOT NULL
);

-- 修改列名
ALTER TABLE employees RENAME COLUMN middle_name TO second_name;

3.3 删除列 #

sql
-- 删除单列
ALTER TABLE employees DROP COLUMN middle_name;

-- 删除多列
ALTER TABLE employees DROP (address, city, country);

-- 设置列为UNUSED(不立即删除,减少影响)
ALTER TABLE employees SET UNUSED (old_column);

-- 删除UNUSED列
ALTER TABLE employees DROP UNUSED COLUMNS;

-- 查看UNUSED列
SELECT * FROM USER_UNUSED_COL_TABS WHERE TABLE_NAME = 'EMPLOYEES';

3.4 添加约束 #

sql
-- 添加主键约束
ALTER TABLE employees ADD CONSTRAINT pk_employees 
PRIMARY KEY (employee_id);

-- 添加唯一约束
ALTER TABLE employees ADD CONSTRAINT uk_email 
UNIQUE (email);

-- 添加外键约束
ALTER TABLE employees ADD CONSTRAINT fk_dept 
FOREIGN KEY (department_id) REFERENCES departments(department_id);

-- 添加检查约束
ALTER TABLE employees ADD CONSTRAINT chk_salary 
CHECK (salary > 0);

-- 添加非空约束
ALTER TABLE employees MODIFY last_name NOT NULL;

3.5 删除约束 #

sql
-- 删除约束
ALTER TABLE employees DROP CONSTRAINT uk_email;

-- 删除主键(级联删除外键)
ALTER TABLE employees DROP PRIMARY KEY CASCADE;

-- 删除唯一约束
ALTER TABLE employees DROP UNIQUE (email);

-- 禁用约束
ALTER TABLE employees DISABLE CONSTRAINT chk_salary;

-- 启用约束
ALTER TABLE employees ENABLE CONSTRAINT chk_salary;

-- 禁用约束(不验证现有数据)
ALTER TABLE employees ENABLE NOVALIDATE CONSTRAINT chk_salary;

3.6 重命名表 #

sql
-- 重命名表
ALTER TABLE employees RENAME TO staff;

-- 或使用RENAME命令
RENAME employees TO staff;

四、删除表 #

4.1 删除表 #

sql
-- 删除表
DROP TABLE employees;

-- 删除表(级联删除约束)
DROP TABLE employees CASCADE CONSTRAINTS;

-- 删除表(清除回收站)
DROP TABLE employees PURGE;

-- 删除表(检查依赖)
-- 如果有外键引用,需要先删除外键或使用CASCADE CONSTRAINTS

4.2 闪回删除的表 #

sql
-- 查看回收站
SELECT * FROM USER_RECYCLEBIN;
SELECT * FROM RECYCLEBIN;

-- 闪回删除的表
FLASHBACK TABLE employees TO BEFORE DROP;

-- 闪回并重命名
FLASHBACK TABLE employees TO BEFORE DROP RENAME TO employees_restored;

-- 清空回收站
PURGE RECYCLEBIN;

-- 清空指定表
PURGE TABLE employees;

-- 彻底删除(不进入回收站)
DROP TABLE employees PURGE;

4.3 截断表 #

sql
-- 截断表(删除所有数据,保留结构)
TRUNCATE TABLE employees;

-- 截断表(释放存储空间)
TRUNCATE TABLE employees DROP ALL STORAGE;

-- TRUNCATE vs DELETE
-- TRUNCATE:DDL,不可回滚,速度快,重置高水位线
-- DELETE:DML,可回滚,速度慢,不重置高水位线

五、表约束 #

5.1 约束类型 #

text
约束类型
├── PRIMARY KEY - 主键约束
│   └── 唯一标识每一行
├── UNIQUE - 唯一约束
│   └── 列值唯一,允许NULL
├── NOT NULL - 非空约束
│   └── 列值不能为空
├── FOREIGN KEY - 外键约束
│   └── 引用其他表的主键
├── CHECK - 检查约束
│   └── 自定义条件验证
└── REF - 引用约束
    └── 引用对象类型

5.2 主键约束 #

sql
-- 创建表时定义主键
CREATE TABLE employees (
    employee_id NUMBER(6) PRIMARY KEY,
    name VARCHAR2(50)
);

-- 命名主键约束
CREATE TABLE employees (
    employee_id NUMBER(6),
    name VARCHAR2(50),
    CONSTRAINT pk_employees PRIMARY KEY (employee_id)
);

-- 复合主键
CREATE TABLE order_items (
    order_id NUMBER(10),
    item_id NUMBER(5),
    product_id NUMBER(6),
    quantity NUMBER(5),
    CONSTRAINT pk_order_items PRIMARY KEY (order_id, item_id)
);

-- 添加主键
ALTER TABLE employees ADD PRIMARY KEY (employee_id);
ALTER TABLE employees ADD CONSTRAINT pk_emp PRIMARY KEY (employee_id);

5.3 外键约束 #

sql
-- 创建表时定义外键
CREATE TABLE orders (
    order_id NUMBER(10) PRIMARY KEY,
    customer_id NUMBER(6),
    order_date DATE,
    CONSTRAINT fk_customer FOREIGN KEY (customer_id) 
        REFERENCES customers(customer_id)
);

-- 外键选项
CREATE TABLE orders (
    order_id NUMBER(10) PRIMARY KEY,
    customer_id NUMBER(6),
    CONSTRAINT fk_customer FOREIGN KEY (customer_id) 
        REFERENCES customers(customer_id)
        ON DELETE CASCADE        -- 删除父记录时删除子记录
        -- ON DELETE SET NULL    -- 删除父记录时设置子记录为NULL
        -- ON DELETE NO ACTION   -- 默认行为,不允许删除
);

-- 自引用外键
CREATE TABLE employees (
    employee_id NUMBER(6) PRIMARY KEY,
    manager_id NUMBER(6),
    CONSTRAINT fk_manager FOREIGN KEY (manager_id) 
        REFERENCES employees(employee_id)
);

5.4 检查约束 #

sql
-- 创建表时定义检查约束
CREATE TABLE products (
    product_id NUMBER(6) PRIMARY KEY,
    product_name VARCHAR2(100),
    price NUMBER(10,2),
    stock_quantity NUMBER(5),
    status VARCHAR2(20),
    
    CONSTRAINT chk_price CHECK (price > 0),
    CONSTRAINT chk_stock CHECK (stock_quantity >= 0),
    CONSTRAINT chk_status CHECK (status IN ('ACTIVE', 'INACTIVE', 'DISCONTINUED'))
);

-- 复杂检查约束
ALTER TABLE employees ADD CONSTRAINT chk_salary_range 
CHECK (salary BETWEEN 1000 AND 100000);

-- 条件检查约束
ALTER TABLE employees ADD CONSTRAINT chk_commission 
CHECK (commission_pct IS NULL OR (commission_pct >= 0 AND commission_pct <= 1));

5.5 约束状态 #

sql
-- 约束状态
-- ENABLE VALIDATE:启用并验证所有数据(默认)
-- ENABLE NOVALIDATE:启用但不验证现有数据
-- DISABLE VALIDATE:禁用但验证新数据
-- DISABLE NOVALIDATE:禁用且不验证

-- 启用约束(验证所有数据)
ALTER TABLE employees ENABLE VALIDATE CONSTRAINT chk_salary;

-- 启用约束(不验证现有数据)
ALTER TABLE employees ENABLE NOVALIDATE CONSTRAINT chk_salary;

-- 禁用约束
ALTER TABLE employees DISABLE CONSTRAINT chk_salary;

-- 查看约束状态
SELECT 
    CONSTRAINT_NAME,
    CONSTRAINT_TYPE,
    STATUS,
    VALIDATED
FROM USER_CONSTRAINTS
WHERE TABLE_NAME = 'EMPLOYEES';

5.6 延迟约束 #

sql
-- 创建延迟约束
CREATE TABLE orders (
    order_id NUMBER(10) PRIMARY KEY,
    customer_id NUMBER(6),
    CONSTRAINT fk_customer FOREIGN KEY (customer_id) 
        REFERENCES customers(customer_id)
        DEFERRABLE INITIALLY DEFERRED
);

-- DEFERRABLE:允许延迟检查
-- INITIALLY IMMEDIATE:默认立即检查
-- INITIALLY DEFERRED:默认延迟到事务提交时检查

-- 在事务中设置
SET CONSTRAINTS ALL DEFERRED;
SET CONSTRAINTS ALL IMMEDIATE;
SET CONSTRAINT fk_customer DEFERRED;

六、表信息查询 #

6.1 查看表结构 #

sql
-- 查看表结构
DESC employees;
DESCRIBE employees;

-- 查看表的列信息
SELECT 
    COLUMN_NAME,
    DATA_TYPE,
    DATA_LENGTH,
    NULLABLE,
    DATA_DEFAULT
FROM USER_TAB_COLUMNS
WHERE TABLE_NAME = 'EMPLOYEES'
ORDER BY COLUMN_ID;

-- 查看表注释
SELECT 
    TABLE_NAME,
    COMMENTS
FROM USER_TAB_COMMENTS
WHERE TABLE_NAME = 'EMPLOYEES';

-- 查看列注释
SELECT 
    COLUMN_NAME,
    COMMENTS
FROM USER_COL_COMMENTS
WHERE TABLE_NAME = 'EMPLOYEES';

6.2 查看约束信息 #

sql
-- 查看表的约束
SELECT 
    CONSTRAINT_NAME,
    CONSTRAINT_TYPE,
    STATUS,
    VALIDATED
FROM USER_CONSTRAINTS
WHERE TABLE_NAME = 'EMPLOYEES';

-- 查看约束列
SELECT 
    c.CONSTRAINT_NAME,
    c.CONSTRAINT_TYPE,
    cc.COLUMN_NAME
FROM USER_CONSTRAINTS c
JOIN USER_CONS_COLUMNS cc ON c.CONSTRAINT_NAME = cc.CONSTRAINT_NAME
WHERE c.TABLE_NAME = 'EMPLOYEES';

-- 约束类型说明
-- P:主键
-- R:外键
-- U:唯一
-- C:检查
-- O:视图只读
-- V:视图检查选项

6.3 查看表统计信息 #

sql
-- 查看表统计信息
SELECT 
    TABLE_NAME,
    NUM_ROWS,
    BLOCKS,
    EMPTY_BLOCKS,
    AVG_ROW_LEN,
    LAST_ANALYZED
FROM USER_TABLES
WHERE TABLE_NAME = 'EMPLOYEES';

-- 收集统计信息
EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'EMPLOYEES');

-- 查看表大小
SELECT 
    SEGMENT_NAME,
    SEGMENT_TYPE,
    BYTES/1024/1024 AS SIZE_MB
FROM USER_SEGMENTS
WHERE SEGMENT_NAME = 'EMPLOYEES';

七、表设计最佳实践 #

7.1 命名规范 #

sql
-- 表命名规范
-- 1. 使用小写字母和下划线
-- 2. 使用复数形式
-- 3. 添加业务前缀

-- 好的命名
CREATE TABLE hr_employees (...);
CREATE TABLE fin_accounts (...);
CREATE TABLE inv_products (...);

-- 列命名规范
-- 1. 使用小写字母和下划线
-- 2. 主键:表名_id 或 id
-- 3. 外键:关联表名_id
-- 4. 布尔:is_xxx 或 has_xxx
-- 5. 日期:xxx_date 或 xxx_time

CREATE TABLE orders (
    order_id NUMBER PRIMARY KEY,         -- 主键
    customer_id NUMBER,                   -- 外键
    order_date DATE,                      -- 日期
    is_paid NUMBER(1) DEFAULT 0,          -- 布尔
    create_time TIMESTAMP DEFAULT SYSTIMESTAMP
);

7.2 数据类型选择 #

sql
-- 数值类型
-- 主键:NUMBER(10) 或 NUMBER
-- 金额:NUMBER(18,4)
-- 百分比:NUMBER(5,4)

-- 字符类型
-- 定长编码:CHAR
-- 变长字符串:VARCHAR2
-- 多语言:NVARCHAR2

-- 日期类型
-- 一般日期:DATE
-- 精确时间:TIMESTAMP

-- 大对象
-- 长文本:CLOB
-- 二进制:BLOB

7.3 约束设计 #

sql
-- 1. 总是定义主键
CREATE TABLE employees (
    employee_id NUMBER(6) PRIMARY KEY,
    ...
);

-- 2. 合理使用外键
-- 考虑性能影响,必要时使用应用层约束

-- 3. 使用检查约束保证数据完整性
CREATE TABLE products (
    price NUMBER(10,2),
    CONSTRAINT chk_price CHECK (price > 0)
);

-- 4. 为约束命名
-- 便于后续管理和识别
ALTER TABLE employees ADD CONSTRAINT uk_email UNIQUE (email);

7.4 性能考虑 #

sql
-- 1. 选择合适的表类型
-- 默认堆表适合大多数场景
-- 主键查询频繁考虑IOT

-- 2. 合理设置存储参数
CREATE TABLE large_table (
    id NUMBER PRIMARY KEY,
    data VARCHAR2(4000)
) PCTFREE 10 PCTUSED 80;

-- 3. 使用分区表处理大表
CREATE TABLE sales (
    sale_id NUMBER,
    sale_date DATE,
    amount NUMBER
)
PARTITION BY RANGE (sale_date) (
    PARTITION p2023 VALUES LESS THAN (TO_DATE('2024-01-01', 'YYYY-MM-DD')),
    PARTITION p2024 VALUES LESS THAN (TO_DATE('2025-01-01', 'YYYY-MM-DD'))
);

-- 4. 定期收集统计信息
EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'EMPLOYEES');

八、总结 #

表操作要点:

操作 命令
创建表 CREATE TABLE
修改表 ALTER TABLE
删除表 DROP TABLE
截断表 TRUNCATE TABLE
重命名 ALTER TABLE RENAME / RENAME
添加列 ALTER TABLE ADD
修改列 ALTER TABLE MODIFY
删除列 ALTER TABLE DROP COLUMN

下一步,让我们学习约束管理!

最后更新:2026-03-27