SQL 基础与数据类型

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

第三章:SQL 基础与数据类型

文档信息
  • 适用版本:Oracle 12c / 18c / 19c / 21c
  • 阅读时间:约 45 分钟
  • 前置知识:第一章内容

3.1 SQL 概述

3.1.1 SQL 语句分类

分类 语句 说明
DDL CREATE, ALTER, DROP, TRUNCATE 数据定义语言
DML SELECT, INSERT, UPDATE, DELETE 数据操作语言
DCL GRANT, REVOKE 数据控制语言
TCL COMMIT, ROLLBACK, SAVEPOINT 事务控制语言
-- DDL 示例
CREATE TABLE employees (
    emp_id NUMBER(10),
    name VARCHAR2(100)
);

-- DML 示例
INSERT INTO employees VALUES (1, '张三');
COMMIT;

-- TCL 示例
SAVEPOINT sp1;
DELETE FROM employees WHERE emp_id = 1;
ROLLBACK TO sp1;

3.1.2 Oracle 与 MySQL 语法差异

功能 Oracle MySQL
字符串引号 单引号 ' 单引号 ' 或双引号 "
字符串拼接 ||CONCAT() CONCAT()+
别名引号 双引号 " 反引号 ` 或双引号
分页查询 OFFSET ... ROWS FETCH NEXT LIMIT ... OFFSET
空值处理 NVL(), COALESCE() IFNULL(), COALESCE()
当前时间 SYSDATE, SYSTIMESTAMP NOW(), CURDATE()

3.2 数据类型

3.2.1 数值类型

类型 范围 说明
NUMBER(p,s) 1~38 位精度 通用数值类型
FLOAT 变长 浮点数(Oracle 遗留)
BINARY_FLOAT 32位 IEEE 754 单精度
BINARY_DOUBLE 64位 IEEE 754 双精度
-- 数值类型示例
CREATE TABLE numeric_demo (
    int_col     NUMBER(10),        -- 整数,10 位
    dec_col     NUMBER(10,2),      -- 小数,总 10 位,小数 2 位
    float_col   FLOAT(53),         -- 浮点数
    percent     NUMBER(5,2)        -- 百分比:99.99
);

INSERT INTO numeric_demo VALUES (1234567890, 12345.67, 3.14159, 99.99);

3.2.2 字符类型

类型 最大长度 说明
CHAR(n) 2000 字节 固定长度,不足补空格
VARCHAR2(n) 4000 字节 可变长度(推荐)
NCHAR(n) 2000 字节 Unicode 固定长度
NVARCHAR2(n) 4000 字节 Unicode 可变长度
CLOB 128TB 字符大对象
LONG 2GB 旧版本兼容(不推荐)
-- 字符类型示例
CREATE TABLE char_demo (
    fixed_code  CHAR(10),           -- 固定 10 字符
    name        VARCHAR2(100),     -- 可变长度姓名
    bio         CLOB               -- 简历等长文本
);

-- 插入示例
INSERT INTO char_demo VALUES ('EMP', '张三', 'Oracle DBA,10年经验...');

3.2.3 日期时间类型

类型 范围 说明
DATE 公元前 4712 ~ 公元 9999 日期+时间(秒精度)
TIMESTAMP(p) - 日期+时间(微秒精度)
TIMESTAMP WITH TIME ZONE - 带时区
TIMESTAMP WITH LOCAL TIME ZONE - 本地时区
INTERVAL YEAR TO MONTH - 年月间隔
INTERVAL DAY TO SECOND - 天时分秒间隔
-- 日期时间示例
CREATE TABLE datetime_demo (
    create_date DATE,                              -- DATE 类型
    create_time TIMESTAMP(6),                      -- 毫秒精度
    create_tz   TIMESTAMP WITH TIME ZONE,         -- 带时区
    work_period INTERVAL YEAR(2) TO MONTH,        -- 工作年限
    break_time  INTERVAL DAY(3) TO SECOND(2)      -- 休息时长
);

-- 插入日期
INSERT INTO datetime_demo VALUES (
    SYSDATE,
    SYSTIMESTAMP,
    CURRENT_TIMESTAMP,
    INTERVAL '5-3' YEAR TO MONTH,      -- 5年3个月
    INTERVAL '3 02:30:15' DAY TO SECOND   -- 3天2小时30分15秒
);

-- 日期运算
SELECT 
    SYSDATE + 7 AS next_week,
    SYSDATE - 30 AS last_month,
    SYSDATE + NUMTODSINTERVAL(2, 'HOUR') AS two_hours_later
FROM dual;

3.2.4 LOB 类型

类型 最大长度 说明
BLOB 128TB 二进制大对象(图片、文件)
CLOB 128TB 字符大对象
NCLOB 128TB Unicode CLOB
BFILE 外部文件 存储文件指针
-- LOB 类型示例
CREATE TABLE lob_demo (
    id          NUMBER PRIMARY KEY,
    name        VARCHAR2(100),
    photo       BLOB,                  -- 员工照片
    resume      CLOB,                  -- 简历
    contract    BFILE                  -- 合同 PDF
);

-- 使用绑定变量插入 LOB
DECLARE
    v_blob BLOB;
    v_clob CLOB;
BEGIN
    INSERT INTO lob_demo (id, name, photo, resume)
    VALUES (1, '张三', EMPTY_BLOB(), EMPTY_CLOB())
    RETURNING photo, resume INTO v_blob, v_clob;
    
    -- 写入 BLOB
    DBMS_LOB.WRITE(v_blob, length('二进制数据'), 1, UTL_RAW.CAST_TO_RAW('二进制数据'));
END;
/

3.3 常用运算符

3.3.1 算术运算符

运算符 说明 示例
+ 加法 10 + 5 = 15
- 减法 10 - 5 = 5
* 乘法 10 * 5 = 50
/ 除法 10 / 5 = 2
MOD(m,n) 取模 MOD(10, 3) = 1
POWER(m,n) 幂运算 POWER(2, 3) = 8

3.3.2 比较运算符

运算符 说明
= 等于
<>, != 不等于
> 大于
< 小于
>= 大于等于
<= 小于等于
BETWEEN…AND 在范围内
IN 在列表中
LIKE 模式匹配
IS NULL 为空

3.3.3 逻辑运算符

-- AND: 所有条件都为 TRUE
SELECT * FROM employees WHERE salary > 5000 AND department = 'IT';

-- OR: 任一条件为 TRUE
SELECT * FROM employees WHERE department = 'IT' OR department = 'HR';

-- NOT: 条件取反
SELECT * FROM employees WHERE NOT (department = 'IT');

-- 组合使用
SELECT * FROM employees 
WHERE (salary > 5000 OR commission > 1000) 
AND hire_date > DATE '2020-01-01';

3.4 常用函数

3.4.1 字符函数

函数 说明 示例
CONCAT(a, b) 拼接字符串 CONCAT('Hello', 'World')
|| 字符串拼接 'Hello' || ' ' || 'World'
LENGTH() 字符串长度 LENGTH('Oracle')
UPPER/LOWER/INITCAP 大小写转换 UPPER('oracle')
TRIM/LTRIM/RTRIM 去除空格 TRIM(' hello ')
SUBSTR() 截取字符串 SUBSTR('Oracle', 2, 3)
INSTR() 查找子串位置 INSTR('HelloWorld', 'World')
REPLACE() 替换字符串 REPLACE('Hello', 'l', 'x')
LPAD/RPAD 填充字符串 LPAD('5', 5, '0')
REGEXP_REPLACE() 正则替换 正则表达式替换
-- 字符函数示例
SELECT 
    CONCAT('Mr.', name) AS full_name,     -- 拼接
    LENGTH(name) AS name_len,             -- 长度
    UPPER(name) AS name_upper,            -- 大写
    SUBSTR(name, 1, 1) || '***' AS masked -- 脱敏
FROM employees;

-- 字符串截取详解
SELECT 
    SUBSTR('Oracle Database', 1, 6)     AS from_start,   -- Oracle
    SUBSTR('Oracle Database', -8)       AS from_end,     -- Database
    SUBSTR('Oracle Database', 8, 4)     AS middle,       -- Data
    INSTR('Oracle Database', 'a')       AS first_pos,    -- 4
    INSTR('Oracle Database', 'a', 5)    AS next_pos      -- 7
FROM dual;

3.4.2 数值函数

函数 说明 示例
ABS() 绝对值 ABS(-10)
ROUND(n, d) 四舍五入 ROUND(3.14159, 3)
TRUNC(n, d) 截断 TRUNC(3.14159, 3)
CEIL/CEILING 向上取整 CEIL(3.1)
FLOOR 向下取整 FLOOR(3.9)
MOD() 取模 MOD(10, 3)
SQRT() 平方根 SQRT(16)
POWER() 幂运算 POWER(2, 10)
LOG() 对数 LOG(10, 100)
LN/EXP 自然对数/指数 EXP(1)

3.4.3 日期函数

函数 说明 示例
SYSDATE 当前日期时间 服务器当前时间
CURRENT_DATE 当前日期 会话时区日期
ADD_MONTHS() 日期加月 ADD_MONTHS(SYSDATE, 6)
MONTHS_BETWEEN() 月份差 MONTHS_BETWEEN(d1, d2)
LAST_DAY() 月末日期 LAST_DAY(SYSDATE)
NEXT_DAY() 下个星期几 NEXT_DAY(SYSDATE, 'MONDAY')
EXTRACT() 提取年/月/日 EXTRACT(YEAR FROM SYSDATE)
TRUNC() 日期截断 TRUNC(SYSDATE, 'MM')
TO_CHAR() 日期转字符串 TO_CHAR(SYSDATE, 'YYYY-MM-DD')
TO_DATE() 字符串转日期 TO_DATE('2024-01-01', 'YYYY-MM-DD')
-- 日期函数示例
SELECT 
    SYSDATE,                                          -- 2024-01-15 10:30:00
    ADD_MONTHS(SYSDATE, 3),                          -- 3 个月后
    ADD_MONTHS(SYSDATE, -6),                         -- 6 个月前
    MONTHS_BETWEEN('2024-12-31', '2024-01-01'),     -- 月份差
    LAST_DAY(SYSDATE),                               -- 月末
    NEXT_DAY(SYSDATE, 'FRIDAY'),                     -- 下个周五
    EXTRACT(YEAR FROM SYSDATE),                      -- 年份
    TRUNC(SYSDATE, 'IW'),                            -- 本周一
    TRUNC(SYSDATE, 'YYYY')                           -- 年初
FROM dual;

-- 日期格式化
SELECT 
    TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') AS datetime1,
    TO_CHAR(SYSDATE, 'YYYY"年"MM"月"DD"日"') AS datetime2,
    TO_CHAR(SYSDATE, 'DAY') AS weekday,
    TO_CHAR(SYSDATE, 'Q') AS quarter
FROM dual;

3.4.4 转换函数

函数 说明 示例
TO_CHAR() 转为字符串 TO_CHAR(1234.56, '9999.99')
TO_NUMBER() 转为数字 TO_NUMBER('1234')
TO_DATE() 转为日期 TO_DATE('2024-01-01', 'YYYY-MM-DD')
TO_TIMESTAMP() 转为时间戳 带时区的时间戳
CAST() 类型转换 CAST('123' AS NUMBER)
NVL(expr1, expr2) 空值替换 NVL(null, 'N/A')
NVL2(expr, val1, val2) 条件空值 非空返 val1,空返 val2
COALESCE() 返回首个非空 COALESCE(a, b, c, 'default')
-- 转换函数示例
SELECT 
    -- 数字格式化
    TO_CHAR(1234567.89, '999,999,999.99') AS formatted_num,
    
    -- 数字转字符串
    TO_CHAR(1234) || ' items',
    
    -- 空值处理
    NVL(commission, 0) AS commission,
    NVL2(commission, '有提成', '无提成') AS commission_status,
    COALESCE(phone, email, '无联系方式') AS contact
FROM employees;

-- 日期格式模型
| 格式 | 说明 | 示例 |
|------|------|------|
| YYYY | 4位年份 | 2024 |
| MM | 2位月份 | 01-12 |
| DD | 2位日期 | 01-31 |
| HH24 | 24小时制 | 00-23 |
| HH12 | 12小时制 | 01-12 |
| MI | 分钟 | 00-59 |
| SS |  | 00-59 |
| DAY | 星期几名称 | MONDAY |
| MONTH | 月份名称 | JANUARY |
| Q | 季度 | 1-4 |
| WW | 年中第几周 | 1-53 |

3.4.5 聚合函数

函数 说明 忽略 NULL
COUNT() 计数 COUNT(*) 包含 NULL
SUM() 求和
AVG() 平均值
MAX() 最大值
MIN() 最小值
LISTAGG() 字符串聚合 可配置
-- 聚合函数示例
SELECT 
    COUNT(*) AS total_count,               -- 总行数
    COUNT(DISTINCT department) AS dept_cnt, -- 部门数
    SUM(salary) AS total_salary,            -- 工资总和
    AVG(salary) AS avg_salary,              -- 平均工资
    MAX(salary) AS max_salary,              -- 最高工资
    MIN(salary) AS min_salary               -- 最低工资
FROM employees;

-- LISTAGG 字符串聚合(Oracle 11g+)
SELECT 
    department,
    LISTAGG(last_name, ',') WITHIN GROUP (ORDER BY hire_date) AS employees
FROM employees
GROUP BY department;

-- 结果示例:
-- DEPARTMENT | EMPLOYEES
-- -----------+--------------------
-- IT         | Smith,Jones,Lee
-- HR         | Brown,Wilson

3.4.6 分析函数(窗口函数)

-- 分析函数示例
SELECT 
    employee_id,
    department_id,
    salary,
    -- 部门内排名
    RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS dept_rank,
    -- 部门内工资占比
    ROUND(salary / SUM(salary) OVER (PARTITION BY department_id) * 100, 2) AS dept_pct,
    -- 累计求和
    SUM(salary) OVER (ORDER BY employee_id ROWS UNBOUNDED PRECEDING) AS cumulative_sum,
    -- 移动平均(最近3个月)
    AVG(salary) OVER (ORDER BY hire_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg
FROM employees
ORDER BY department_id, salary DESC;

3.5 分页查询

3.5.1 Oracle 12c 之前的分页

-- 分页查询(使用 ROWNUM)
SELECT * FROM (
    SELECT a.*, ROWNUM rn FROM (
        SELECT employee_id, first_name, salary
        FROM employees
        ORDER BY salary DESC
    ) a WHERE ROWNUM <= 20
) WHERE rn > 10;

-- 解释:
-- 1. 内层:完整查询 + 排序
-- 2. 中层:ROWNUM 限制行数(必须在外层包装)
-- 3. 外层:过滤起始行

3.5.2 Oracle 12c+ 的分页

-- Oracle 12c+ 简化语法
SELECT employee_id, first_name, salary
FROM employees
ORDER BY salary DESC
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;

-- FETCH 子句选项
OFFSET n ROWS                  -- 跳过前 n 行
FETCH FIRST n ROWS ONLY        -- 取前 n 行
FETCH FIRST n ROWS WITH TIES   -- 包括并列的最后几行
FETCH FIRST n PERCENT ROWS ONLY -- 取前 n%

3.6 层级查询

3.6.1 CONNECT BY 递归查询

-- 组织架构层级查询
SELECT 
    LEVEL,                          -- 层级
    employee_id,
    first_name || ' ' || last_name AS name,
    manager_id,
    PRIIOR first_name || ' ' || PRIOR last_name AS manager_name
FROM employees
START WITH manager_id IS NULL      -- 从 CEO 开始
CONNECT BY PRIOR employee_id = manager_id;  -- 递归条件

-- 格式化显示层级
SELECT 
    LPAD(' ', 2 * (LEVEL - 1)) || first_name AS org_chart
FROM employees
START WITH manager_id IS NULL
CONNECT BY PRIOR employee_id = manager_id;

-- SYS_CONNECT_BY_PATH 路径
SELECT 
    SYS_CONNECT_BY_PATH(first_name, '/') AS path
FROM employees
START WITH manager_id IS NULL
CONNECT BY PRIOR employee_id = manager_id;

-- 查找叶子节点和根节点
SELECT *
FROM employees
WHERE LEVEL > 1
CONNECT BY PRIOR employee_id = manager_id
START WITH employee_id = 100
AND LEVEL <= 3;

3.7 本章小结

✅ SQL 分为 DDL、DML、DCL、TCL 四大类
✅ 掌握数值、字符、日期、Lob 等核心数据类型
✅ 熟练使用各种运算符和表达式
✅ 记住常用函数:字符串、数值、日期、转换函数
✅ 理解分析函数(窗口函数)的强大功能
✅ 掌握 Oracle 分页查询和层级查询

📖 下章预告:数据库与表操作

下一步:学习 第四章:数据库与表操作