知识库✳

教程与手册

全部教程
  1. 01Oracle 函数手册
  2. 02性能优化手册
  3. 03Linux Shell
  4. 04Oracle 学习与演练
  5. 05网络基础学习
  6. 06数据治理与管理
返回个人网站
甲Oracle 学习教程从 SQL 到 PL/SQL 与运维
首页课程目录搜索演练场
知识库

已完成 0 / 22 章

模块一 · 入门与准备

  • 01Oracle 数据库体系结构
  • 02环境安装与连接方式
  • 03SQL*Plus 与常用工具

模块二 · SQL 查询基础

  • 04SELECT 查询基础
  • 05过滤与排序
  • 06单行函数
  • 07多表连接
  • 08分组聚合与 HAVING
  • 09子查询

模块三 · 数据与对象

  • 10DML 与事务控制
  • 11表与数据类型
  • 12约束
  • 13索引与执行计划
  • 14视图、序列与同义词

模块四 · PL/SQL 编程

  • 15PL/SQL 块与变量
  • 16流程控制与游标
  • 17存储过程与函数
  • 18触发器
  • 19异常处理

模块五 · 运维与进阶

  • 20用户与权限管理
  • 21表空间与存储管理
  • 22备份与恢复
❖

Oracle 学习教程

返回个人网站知识库

示例代码基于 Oracle AI Database 26ai / 23ai,查询示例使用官方 HR 示例方案。

以 Next.js 16 · Tailwind CSS v4 · HeroUI v3 装帧

06
  1. 首页
  2. 课程目录
  3. 单行函数

第 6 章◆入门◆建议 50 分钟◆模块二 · SQL 查询基础

单行函数

字符、数字、日期、转换与通用函数:这些是写报表和做数据清洗的日常工具。

学完这一章,你应该能

  • 熟练使用常用字符与数字函数
  • 掌握日期运算与日期截断
  • 理解显式转换与隐式转换的风险
  • 会写 CASE 与 DECODE 做条件分支

6.1字符函数

  • SUBSTR 的起始位置从 1 开始;起始位置为负数表示从右边数
  • INSTR 找不到时返回 0,不是 NULL
  • LENGTH 支持 VARCHAR2 与 CLOB/NCLOB,返回字符数;LENGTHC/LENGTH2/LENGTH4 才不支持 CLOB/NCLOB
  • CONCAT 只能接两个参数,拼接多个用 ||
最常用的字符函数
SELECT last_name,
       UPPER(last_name)                  AS upper_demo,
       LOWER(last_name)                  AS lower_demo,
       INITCAP('hello oracle')           AS initcap_demo,
       SUBSTR(last_name, 1, 3)           AS sub_demo,
       LENGTH(last_name)                 AS len_demo,
       INSTR(last_name, 'a')             AS pos_demo,
       LPAD(salary, 10, '*')             AS lpad_demo,
       TRIM('  spaces  ')                AS trim_demo,
       REPLACE(job_id, '_', '-')         AS replace_demo
FROM   employees
WHERE  employee_id <= 104;
在你的专用沙箱里执行打开演练场

6.2数字函数

四舍五入、截断与取余
SELECT ROUND(45.926, 2)   AS rounded,     -- 45.93
       TRUNC(45.926, 2)   AS truncated,   -- 45.92  直接截断,不进位
       MOD(1600, 300)     AS remainder,   -- 100
       CEIL(45.1)         AS ceiled,      -- 46
       FLOOR(45.9)        AS floored,     -- 45
       ABS(-10)           AS absolute
FROM   dual;
在你的专用沙箱里执行打开演练场

提示 财务计算要注意 ROUND 与 TRUNC 的区别,以及 NUMBER 类型的精度声明(如 NUMBER(10,2)),二者叠加容易产生对不上账的问题。

6.3日期函数

Oracle 的 DATE 类型同时包含日期和时间(精确到秒)。日期可以直接做加减运算:加 1 就是加一天。这个特性让很多计算变得简洁,但也容易写出「加 1 以为是加 1 个月」的错误。

日期运算与截断
SELECT SYSDATE                            AS now,
       SYSDATE + 1                        AS tomorrow,
       SYSDATE + 1/24                     AS next_hour,      -- 1/24 天 = 1 小时
       MONTHS_BETWEEN(SYSDATE, DATE '2024-01-01') AS months_diff,
       ADD_MONTHS(SYSDATE, 3)             AS plus_3_months,
       NEXT_DAY(SYSDATE, 'MONDAY')         AS next_monday,   -- 须匹配 NLS_DATE_LANGUAGE
       LAST_DAY(SYSDATE)                  AS month_end,
       TRUNC(SYSDATE, 'MM')               AS month_start,    -- 截断到月初,报表常用
       TRUNC(SYSDATE, 'YYYY')             AS year_start,
       EXTRACT(YEAR FROM SYSDATE)         AS cur_year
FROM   dual;

NEXT_DAY 的第二个参数必须是「当前会话日期语言」下的星期名。默认 NLS_DATE_LANGUAGE=AMERICAN 时写 'MONDAY';若要用 '星期一',需先执行 ALTER SESSION SET NLS_DATE_LANGUAGE='SIMPLIFIED CHINESE',否则报 ORA-01846(not a valid day of the week)。

在你的专用沙箱里执行打开演练场
统计员工在职年限
SELECT employee_id,
       last_name,
       hire_date,
       TRUNC(MONTHS_BETWEEN(SYSDATE, hire_date) / 12) AS years_of_service
FROM   employees
WHERE  hire_date < DATE '2005-01-01'
ORDER  BY years_of_service DESC;
在你的专用沙箱里执行打开演练场

6.4转换函数与隐式转换的坑

  • 隐式转换依赖会话的 NLS 设置,换环境就可能报 ORA-01861
  • 对日期列用 TO_CHAR 后再比较,会导致索引失效(函数作用于列)
  • 正确写法:WHERE hire_date >= TO_DATE('2024-01-01','YYYY-MM-DD')
  • 日期格式模型区分大小写:MM 是月,mi 是分钟,HH24 才是 24 小时制
显式转换
SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS')  AS formatted_date,
       TO_CHAR(1234567.891, '999,999,999.99')       AS formatted_num,
       TO_CHAR(1234.5, 'L99,999.00')                AS currency,
       TO_DATE('2024-03-15', 'YYYY-MM-DD')          AS parsed_date,
       TO_NUMBER('1,234.56', '9,999.99')            AS parsed_num
FROM   dual;
在你的专用沙箱里执行打开演练场

提示 看到 WHERE 里对列使用了函数,就该警惕性能问题。这会在「索引与执行计划」一章展开。

6.5条件分支:CASE 与 DECODE

  • CASE 是 ANSI 标准,能做范围判断,可读性更好,推荐优先使用
  • DECODE 只能等值匹配,但写法紧凑,老代码里很常见
  • CASE 也可以用在 ORDER BY 里实现自定义排序
按工资分档
SELECT employee_id,
       salary,
       CASE
         WHEN salary < 5000  THEN '偏低'
         WHEN salary < 10000 THEN '中等'
         WHEN salary < 20000 THEN '较高'
         ELSE '很高'
       END AS salary_band,
       -- DECODE 是 Oracle 特有写法,只能做等值判断
       DECODE(department_id, 50, 'Shipping', 60, 'IT', 90, 'Executive', '其他') AS dept_label
FROM   employees
ORDER  BY salary DESC;
在你的专用沙箱里执行打开演练场

练习

3 题 · 先自己写,再展开对照

参考答案

B 能用索引,A 不能。

A 把函数作用在索引列上,优化器无法直接用索引定位,只能全表扫描
(除非专门建了 TO_CHAR(hire_date, 'YYYY') 的函数索引)。

B 是范围条件,可以直接走索引范围扫描。这是「列上不要用函数」的典型例子。

自评要点

  • 识别出函数作用于索引列
  • 给出范围条件的正确替代写法
  • 知道函数索引是另一条出路

参考答案

SELECT TO_CHAR(
         TO_DATE('2024-03-15', 'YYYY-MM-DD'),
         'YYYY"年"MM"月"DD"日"'
       ) AS formatted
FROM   dual;
在你的专用沙箱里执行打开演练场

自评要点

  • TO_DATE 需要显式格式模型
  • 中文字符要用双引号包起来才能作为字面量出现在格式模型里

参考答案

SELECT employee_id,
       salary,
       CASE
         WHEN salary < 5000  THEN '偏低'
         WHEN salary < 10000 THEN '中等'
         WHEN salary < 20000 THEN '较高'
         ELSE '很高'
       END AS salary_band
FROM   employees
ORDER  BY salary DESC;
在你的专用沙箱里执行打开演练场

自评要点

  • CASE 按顺序判断,命中即返回
  • 别忘了 ELSE 兜底,否则不匹配时返回 NULL
← 上一章

过滤与排序

下一章 →

多表连接