数据库与表操作

最后更新: 2026-04-15 作者: Oracle Team
页面目录

第四章:数据库与表操作

文档信息
  • 适用版本:Oracle 12c / 18c / 19c / 21c
  • 阅读时间:约 50 分钟
  • 前置知识:第三章 SQL 基础

4.1 数据库管理

4.1.1 创建数据库(CDB 模式)

# 1. 设置环境变量
export ORACLE_SID=ORCL
export ORACLE_HOME=/u01/app/oracle/product/19c/dbhome_1
export PATH=$ORACLE_HOME/bin:$PATH

# 2. 创建初始化参数文件
$ORACLE_HOME/dbs/orainitORCL.ora

# 3. 创建密码文件
orapwd FILE=$ORACLE_HOME/dbs/orapwORCL password=SysPassword123 entries=30

# 4. 创建目录
mkdir -p /u01/app/oracle/oradata/ORCL
mkdir -p /u01/app/oracle/fast_recovery_area/ORCL

# 5. 使用 DBCA 图形化创建(推荐)
dbca

4.1.2 数据库启动与关闭

-- 启动数据库(3 种模式)
STARTUP NOMOUNT;     -- 仅启动实例,读取参数文件
STARTUP MOUNT;       -- 加载数据库,打开控制文件
STARTUP OPEN;        -- 打开数据库(默认)
STARTUP FORCE;       -- 强制重启

-- 关闭数据库
SHUTDOWN IMMEDIATE;  -- 立即关闭,回滚未提交事务(推荐)
SHUTDOWN TRANSACTIONAL; -- 等待事务完成
SHUTDOWN NORMAL;     -- 等待所有用户断开(不推荐)
SHUTDOWN ABORT;      -- 强制终止(紧急情况,恢复需更长)

-- 只读打开(DataGuard 场景)
STARTUP MOUNT;
ALTER DATABASE OPEN READ ONLY;

4.1.3 数据库状态查询

-- 查看数据库基本信息
SELECT 
    name,
    database_role,
    open_mode,
    log_mode,
    flashback_on,
    guard_status
FROM v$database;

-- 查看实例信息
SELECT 
    instance_name,
    host_name,
    version,
    status,
    startup_time,
    database_status
FROM v$instance;

-- 查看连接会话
SELECT 
    sid,
    serial#,
    username,
    status,
    program,
    logon_time
FROM v$session
WHERE username IS NOT NULL;

4.2 表空间管理

4.2.1 表空间类型

┌─────────────────────────────────────────────────────────────────┐
│                     Oracle 表空间架构                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  永久表空间 (Permanent)                                          │
│  ├── SYSTEM      - 数据字典(不能脱机)                           │
│  ├── SYSAUX      - 辅助系统表空间                               │
│  ├── USERS       - 用户数据                                     │
│  └── 自定义表空间  - 业务数据                                     │
│                                                                 │
│  临时表空间 (Temporary)                                          │
│  └── TEMP        - 排序、Hash join、临时结果集                    │
│                                                                 │
│  UNDO 表空间                                                     │
│  └── UNDOTBS1    - 回滚段,事务一致性                            │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

4.2.2 创建表空间

-- 基础表空间
CREATE TABLESPACE users_ts
DATAFILE '/u01/app/oracle/oradata/ORCL/users01.dbf'
SIZE 100M
AUTOEXTEND ON NEXT 10M MAXSIZE 10G
EXTENT MANAGEMENT LOCAL
SEGMENT SPACE MANAGEMENT AUTO
NOLOGGING;  -- 不记录重做日志(快速加载)

-- 大文件表空间(适合海量数据)
CREATE BIGFILE TABLESPACE bigdata_ts
DATAFILE '/u01/app/oracle/oradata/ORCL/bigdata01.dbf'
SIZE 100G
AUTOEXTEND ON NEXT 10G MAXSIZE 32T;

-- 加密表空间
CREATE TABLESPACE secure_ts
DATAFILE '/u01/app/oracle/oradata/ORCL/secure01.dbf'
SIZE 100M
ENCRYPTION USING 'AES256'
DEFAULT STORAGE (ENCRYPT);

-- 临时表空间
CREATE TEMPORARY TABLESPACE temp_ts
TEMPFILE '/u01/app/oracle/oradata/ORCL/temp01.dbf'
SIZE 500M
AUTOEXTEND ON NEXT 100M MAXSIZE 10G;

-- UNDO 表空间
CREATE UNDO TABLESPACE undotbs2
DATAFILE '/u01/app/oracle/oradata/ORCL/undotbs201.dbf'
SIZE 1G
AUTOEXTEND ON;

4.2.3 表空间维护

-- 修改表空间大小
ALTER DATABASE DATAFILE '/u01/app/oracle/oradata/ORCL/users01.dbf' RESIZE 200M;

-- 添加数据文件
ALTER TABLESPACE users_ts ADD DATAFILE 
'/u01/app/oracle/oradata/ORCL/users02.dbf' SIZE 100M;

-- 收缩数据文件(释放空间)
ALTER TABLESPACE users_ts SHRINK SPACE KEEP 100M;

-- 脱机/联机表空间
ALTER TABLESPACE users_ts OFFLINE NORMAL;
ALTER TABLESPACE users_ts ONLINE;

-- 重命名数据文件
ALTER TABLESPACE users_ts RENAME DATAFILE 
'/u01/app/oracle/oradata/ORCL/users01.dbf' TO 
'/u01/app/oracle/oradata/ORCL/users_new01.dbf';

-- 删除表空间
DROP TABLESPACE users_ts INCLUDING CONTENTS AND DATAFILES;

4.2.4 表空间监控

-- 查看表空间使用情况
SELECT 
    tablespace_name,
    ROUND(tablespace_size/1024/1024/1024, 2) AS size_gb,
    ROUND(tablespace_used_space/1024/1024/1024, 2) AS used_gb,
    ROUND(tablespace_used_percent, 2) AS usage_pct
FROM dba_tablespace_usage_metrics
ORDER BY usage_pct DESC;

-- 详细使用情况(包含空闲空间)
SELECT 
    a.tablespace_name,
    a.total_size_gb,
    a.total_size_gb - b.free_size_gb AS used_size_gb,
    b.free_size_gb,
    ROUND((1 - b.free_size_gb/a.total_size_gb) * 100, 2) AS usage_pct
FROM (
    SELECT tablespace_name, SUM(bytes)/1024/1024/1024 AS total_size_gb
    FROM dba_data_files
    GROUP BY tablespace_name
) a,
(
    SELECT tablespace_name, SUM(bytes)/1024/1024/1024 AS free_size_gb
    FROM dba_free_space
    GROUP BY tablespace_name
) b
WHERE a.tablespace_name = b.tablespace_name;

4.3 表管理

4.3.1 创建表

-- 基础建表
CREATE TABLE employees (
    employee_id    NUMBER(10) PRIMARY KEY,
    first_name    VARCHAR2(50) NOT NULL,
    last_name     VARCHAR2(50) NOT NULL,
    email         VARCHAR2(100) UNIQUE,
    phone_number  VARCHAR2(20),
    hire_date     DATE DEFAULT SYSDATE,
    job_id        VARCHAR2(20),
    salary        NUMBER(10,2) CHECK (salary > 0),
    commission_pct NUMBER(5,2),
    manager_id    NUMBER(10),
    department_id NUMBER(10),
    created_at    TIMESTAMP DEFAULT SYSTIMESTAMP,
    updated_at    TIMESTAMP DEFAULT SYSTIMESTAMP
);

-- 使用子查询建表
CREATE TABLE emp_high_salary AS
SELECT * FROM employees WHERE salary > 10000;

-- 使用 CTAS 创建表
CREATE TABLE dept_salary_summary AS
SELECT 
    department_id,
    COUNT(*) AS emp_count,
    SUM(salary) AS total_salary,
    AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id;

-- 创建全局临时表
CREATE GLOBAL TEMPORARY TABLE temp_results (
    session_id VARCHAR2(50),
    result_data CLOB
) ON COMMIT DELETE ROWS;  -- 事务结束删除
-- 或 ON COMMIT PRESERVE ROWS;  -- 会话结束删除

4.3.2 修改表结构

-- 添加列
ALTER TABLE employees ADD (
    bonus NUMBER(10,2),
    profile_pic BLOB
);

-- 修改列
ALTER TABLE employees MODIFY (
    email VARCHAR2(200) NOT NULL,  -- 扩大并设为非空
    salary NUMBER(12,2)             -- 扩大精度
);

-- 重命名列
ALTER TABLE employees RENAME COLUMN email TO email_address;

-- 删除列(Oracle 10g+)
ALTER TABLE employees DROP COLUMN profile_pic;

-- 设置不可用列(标记删除,节省空间)
ALTER TABLE employees SET UNUSED COLUMN bonus;
ALTER TABLE employees DROP UNUSED COLUMNS;

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

-- 重命名表
RENAME employees TO staff_members;

4.3.3 表的高级特性

-- 压缩表(节约存储空间)
CREATE TABLE compressed_emp (
    employee_id NUMBER(10),
    name VARCHAR2(100)
) COMPRESS FOR OLTP;

-- 压缩现有表
ALTER TABLE employees COMPRESS FOR OLTP;

-- 启用行移动(闪回表、分区操作必需)
ALTER TABLE employees ENABLE ROW MOVEMENT;

-- 只读表
ALTER TABLE employees READ ONLY;
ALTER TABLE employees READ WRITE;

-- 表注释
COMMENT ON TABLE employees IS '员工信息表';
COMMENT ON COLUMN employees.email IS '员工邮箱地址';

4.4 约束管理

4.4.1 约束类型

约束 说明 关键字
主键 唯一标识,非空 PRIMARY KEY
唯一键 唯一,允许空值 UNIQUE
外键 引用完整性 FOREIGN KEY
检查约束 条件限制 CHECK
非空约束 不允许空值 NOT NULL
-- 创建表时定义约束
CREATE TABLE orders (
    order_id     NUMBER(10) PRIMARY KEY,
    customer_id  NUMBER(10) NOT NULL,
    order_date   DATE NOT NULL,
    total_amount NUMBER(12,2) CHECK (total_amount >= 0),
    status       VARCHAR2(20) CHECK (status IN ('PENDING', 'SHIPPED', 'DELIVERED')),
    
    -- 外键约束
    CONSTRAINT fk_orders_customer 
        FOREIGN KEY (customer_id) 
        REFERENCES customers(customer_id)
        ON DELETE CASCADE
        ON UPDATE CASCADE,
    
    -- 唯一约束
    CONSTRAINT uk_orders_order_no 
        UNIQUE (customer_id, order_date, order_seq)
);

-- 独立创建约束
ALTER TABLE employees ADD CONSTRAINT 
    uk_employees_email UNIQUE (email);

ALTER TABLE employees ADD CONSTRAINT 
    fk_employees_dept 
    FOREIGN KEY (department_id) 
    REFERENCES departments(department_id);

-- 检查约束
ALTER TABLE employees ADD CONSTRAINT 
    chk_employees_salary 
    CHECK (salary > 0 AND salary < 1000000);

ALTER TABLE employees ADD CONSTRAINT 
    chk_employees_date 
    CHECK (hire_date >= TO_DATE('1990-01-01', 'YYYY-MM-DD'));

4.4.2 约束管理

-- 禁用/启用约束
ALTER TABLE employees DISABLE CONSTRAINT uk_employees_email;
ALTER TABLE employees ENABLE CONSTRAINT uk_employees_email;

-- 级联禁用(外键)
ALTER TABLE employees DISABLE CONSTRAINT fk_employees_dept CASCADE;

-- 删除约束
ALTER TABLE employees DROP CONSTRAINT uk_employees_email;

-- 重命名约束
ALTER TABLE employees RENAME CONSTRAINT old_name TO new_name;

-- 查询约束
SELECT constraint_name, constraint_type, status, validated
FROM user_constraints
WHERE table_name = 'EMPLOYEES';

-- 查询约束列
SELECT constraint_name, column_name
FROM user_cons_columns
WHERE table_name = 'EMPLOYEES';

4.5 分区表

4.5.1 分区类型

┌─────────────────────────────────────────────────────────────────┐
│                      Oracle 分区表类型                            │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  范围分区 (RANGE)                                                │
│  ─────────────────                                              │
│  CREATE TABLE sales (                                          │
│      sale_date DATE                                            │
│  ) PARTITION BY RANGE (sale_date) (                           │
│      PARTITION p2023 VALUES LESS THAN (DATE '2024-01-01'),   │
│      PARTITION p2024 VALUES LESS THAN (DATE '2025-01-01'),   │
│      PARTITION p_future VALUES LESS THAN (MAXVALUE)            │
│  );                                                            │
│                                                                 │
│  列表分区 (LIST)                                                │
│  ─────────────────                                              │
│  CREATE TABLE customers (                                      │
│      region VARCHAR2(20)                                       │
│  ) PARTITION BY LIST (region) (                                │
│      PARTITION p_east VALUES ('北京', '上海'),                │
│      PARTITION p_west VALUES ('西安', '成都'),                │
│      PARTITION p_other VALUES (DEFAULT)                        │
│  );                                                            │
│                                                                 │
│  哈希分区 (HASH)                                                │
│  ─────────────────                                              │
│  CREATE TABLE orders (                                        │
│      order_id NUMBER                                           │
│  ) PARTITION BY HASH (order_id) PARTITIONS 16;               │
│                                                                 │
│  组合分区                                                       │
│  ─────────                                                     │
│  RANGE-LIST: 范围 + 列表组合                                    │
│  RANGE-HASH: 范围 + 哈希组合                                     │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

4.5.2 创建分区表

-- 范围分区(按日期)
CREATE TABLE sales (
    sale_id      NUMBER(10),
    sale_date    DATE NOT NULL,
    customer_id  NUMBER(10),
    amount       NUMBER(12,2)
)
PARTITION BY RANGE (sale_date) (
    PARTITION p_2023_q1 VALUES LESS THAN (DATE '2023-04-01'),
    PARTITION p_2023_q2 VALUES LESS THAN (DATE '2023-07-01'),
    PARTITION p_2023_q3 VALUES LESS THAN (DATE '2023-10-01'),
    PARTITION p_2023_q4 VALUES LESS THAN (DATE '2024-01-01'),
    PARTITION p_2024_q1 VALUES LESS THAN (DATE '2024-04-01'),
    PARTITION p_2024_q2 VALUES LESS THAN (DATE '2024-07-01'),
    PARTITION p_future VALUES LESS THAN (MAXVALUE)
);

-- 列表分区(按地区)
CREATE TABLE customers (
    customer_id   NUMBER(10),
    customer_name VARCHAR2(100),
    region        VARCHAR2(20) NOT NULL,
    city          VARCHAR2(50)
)
PARTITION BY LIST (region) (
    PARTITION p_beijing VALUES ('北京'),
    PARTITION p_shanghai VALUES ('上海'),
    PARTITION p_guangzhou VALUES ('广州', '深圳'),
    PARTITION p_other VALUES (DEFAULT)
);

-- 哈希分区(均匀分布)
CREATE TABLE transactions (
    transaction_id NUMBER(20),
    account_id     NUMBER(10),
    amount         NUMBER(12,2),
    trans_date     DATE
)
PARTITION BY HASH (account_id) (
    PARTITION p_01,
    PARTITION p_02,
    PARTITION p_03,
    PARTITION p_04
);

-- 组合分区:范围 + 列表
CREATE TABLE sales_by_region (
    sale_id     NUMBER(10),
    sale_date   DATE,
    region      VARCHAR2(20),
    city        VARCHAR2(50),
    amount      NUMBER(12,2)
)
PARTITION BY RANGE (sale_date) 
SUBPARTITION BY LIST (region) (
    PARTITION p_2024 VALUES LESS THAN (DATE '2025-01-01') (
        SUBPARTITION p_2024_east VALUES ('北京', '上海'),
        SUBPARTITION p_2024_west VALUES ('西安', '成都'),
        SUBPARTITION p_2024_other VALUES (DEFAULT)
    )
);

4.5.3 分区维护操作

-- 添加分区
ALTER TABLE sales ADD PARTITION p_2024_q3 
VALUES LESS THAN (DATE '2024-10-01');

-- 拆分分区
ALTER TABLE sales SPLIT PARTITION p_future 
AT (DATE '2024-07-01') 
INTO (PARTITION p_2024_q2, PARTITION p_future);

-- 合并分区
ALTER TABLE sales MERGE PARTITIONS p_2024_q1, p_2024_q2 
INTO PARTITION p_2024_h1;

-- 删除分区
ALTER TABLE sales DROP PARTITION p_2023_q1;

-- 截断分区
ALTER TABLE sales TRUNCATE PARTITION p_2023_q1;

-- 重命名分区
ALTER TABLE sales RENAME PARTITION p_2024_q1 TO p_2024_1q;

-- 查询分区信息
SELECT partition_name, high_value, num_rows
FROM user_tab_partitions
WHERE table_name = 'SALES'
ORDER BY partition_position;

-- 查询子分区
SELECT partition_name, subpartition_name, high_value
FROM user_tab_subpartitions
WHERE table_name = 'SALES_BY_REGION';

4.6 索引管理

4.6.1 索引类型

类型 说明 适用场景
B-Tree 默认索引,平衡树结构 主键、唯一索引、范围查询
Bitmap 位图压缩存储 低基数列(性别、状态)
Function-based 函数/表达式索引 计算列查询
Domain 应用自定义索引 空间、文本搜索
Hash Hash 分区索引 等值连接优化

4.6.2 创建索引

-- B-Tree 索引
CREATE INDEX idx_emp_dept ON employees(department_id);
CREATE UNIQUE INDEX idx_emp_email ON employees(email);

-- 复合索引(列顺序很重要)
CREATE INDEX idx_emp_dept_job ON employees(department_id, job_id);

-- Bitmap 索引(低基数列)
CREATE BITMAP INDEX idx_emp_gender ON employees(gender);
CREATE BITMAP INDEX idx_emp_status ON employees(status);

-- 函数索引
CREATE INDEX idx_emp_upper_name ON employees(UPPER(last_name));
CREATE INDEX idx_emp_sal_annual ON employees(salary * 12);

-- 位图连接索引
CREATE BITMAP INDEX idx_sales_prod 
ON sales(product_name) FROM sales, products 
WHERE sales.product_id = products.product_id;

-- 本地索引(分区表)
CREATE INDEX idx_sales_date ON sales(sale_date) LOCAL;

-- 全局索引
CREATE INDEX idx_orders_date ON orders(order_date) GLOBAL;

4.6.3 索引维护

-- 重建索引
ALTER INDEX idx_emp_dept REBUILD;
ALTER INDEX idx_emp_dept REBUILD ONLINE;  -- 在线重建,不阻塞 DML

-- 合并索引(释放空白空间)
ALTER INDEX idx_emp_dept COALESCE;

-- 监控索引使用
ALTER INDEX idx_emp_dept MONITORING USAGE;

-- 查看使用情况
SELECT * FROM v$object_usage WHERE index_name = 'IDX_EMP_DEPT';

-- 删除不可用索引
DROP INDEX idx_emp_dept;

-- 查看索引信息
SELECT index_name, index_type, uniqueness, status, num_rows
FROM user_indexes
WHERE table_name = 'EMPLOYEES';

SELECT index_name, column_name, column_position
FROM user_ind_columns
WHERE table_name = 'EMPLOYEES';

4.7 序列

4.7.1 序列管理

-- 创建序列
CREATE SEQUENCE seq_employee_id
START WITH 1000
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9999999999
NOCACHE          -- 每次生成 20 个预分配(NOCACHE 更安全)
CYCLE            -- 达到最大值后循环
ORDER;           -- 保证顺序

-- 使用序列
INSERT INTO employees (employee_id, first_name, last_name)
VALUES (seq_employee_id.NEXTVAL, 'John', 'Doe');

-- 获取当前值
SELECT seq_employee_id.CURRVAL FROM dual;

-- 修改序列
ALTER SEQUENCE seq_employee_id
INCREMENT BY 10
MAXVALUE 99999999999;

-- 删除序列
DROP SEQUENCE seq_employee_id;

4.8 同义词

-- 创建私有同义词
CREATE SYNONYM emp FOR hr.employees;
SELECT * FROM emp;

-- 创建公共同义词(所有用户可用)
CREATE PUBLIC SYNONYM departments FOR hr.departments;

-- 删除同义词
DROP SYNONYM emp;
DROP PUBLIC SYNONYM departments;

4.9 本章小结

✅ 掌握数据库启动/关闭的多种模式
✅ 表空间类型:永久、临时、UNDO
✅ 分区表:RANGE、LIST、HASH、组合分区
✅ 约束类型:主键、唯一、外键、检查约束
✅ 索引类型:B-Tree、Bitmap、函数索引
✅ 序列和同义词的创建与使用

📖 下章预告:索引原理与应用

下一步:学习 第五章:索引原理与应用