Oracle新老SQL写法对比

Oracle 的"老写法"本质上是 ANSI SQL:1989 / SQL-92 之前 的风格,在金融、电信、银行系统里非常常见。下面按类型 + 示例 + 现代等价写法 + 踩坑点给你系统梳理一遍,和你刚才那条 SQL 属于同一个"时代产物"。


一、隐式连接(Implicit JOIN)✅ 你刚遇到的

老写法

sql 复制代码
SELECT *
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO;

新写法

sql 复制代码
SELECT *
FROM EMP E
JOIN DEPT D ON E.DEPTNO = D.DEPTNO;

📌 本质 :逗号 = CROSS JOIN,WHERE = 过滤条件

📌 风险:少写一个条件就变笛卡尔积


二、(+) 外连接(Oracle 独有)

这是 Oracle 最著名的"老古董"。

左外连接(老)

sql 复制代码
SELECT E.ENAME, D.DNAME
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO(+);

左外连接(新)

sql 复制代码
SELECT E.ENAME, D.DNAME
FROM EMP E
LEFT JOIN DEPT D ON E.DEPTNO = D.DEPTNO;

右外连接(老)

sql 复制代码
SELECT E.ENAME, D.DNAME
FROM EMP E, DEPT D
WHERE E.DEPTNO(+) = D.DEPTNO;

规则口诀(非常重要)

(+) 写在"补空的一边"

❌ 不支持:

  • 全外连接 FULL OUTER JOIN
  • 多个 OR 条件
  • 自连接 + (+)

✅ Oracle 官方建议:12c 以后尽量不用 (+)


三、DECODE 替代 CASE(老牌条件表达式)

老写法

sql 复制代码
SELECT
  DECODE(SEX,
    '1', '男',
    '2', '女',
    '未知'
  ) AS SEX_DESC
FROM EMP;

新写法

sql 复制代码
SELECT
  CASE SEX
    WHEN '1' THEN '男'
    WHEN '2' THEN '女'
    ELSE '未知'
  END AS SEX_DESC
FROM EMP;

📌 DECODE 是 Oracle 私有函数

📌 CASE 是 ANSI 标准,可读性强


四、NVL vs COALESCE

老写法

sql 复制代码
SELECT NVL(COMM, 0) FROM EMP;

新写法

sql 复制代码
SELECT COALESCE(COMM, 0) FROM EMP;
对比项 NVL COALESCE
标准 Oracle 私有 ANSI SQL
参数个数 2 个 ≥2 个
短路求值

📌 COALESCE 更安全,尤其跨数据库


五、SYSDATE + 数字 = 日期运算(老习惯)

老写法

sql 复制代码
SELECT SYSDATE + 1 FROM DUAL;      -- 明天
SELECT SYSDATE - 1/24 FROM DUAL;  -- 一小时前

新写法(更语义化)

sql 复制代码
SELECT SYSDATE + INTERVAL '1' DAY FROM DUAL;
SELECT SYSDATE - INTERVAL '1' HOUR FROM DUAL;

📌 老写法在金融计息、账期计算中极常见

📌 新写法可读性更好,但性能没差别


六、ROWNUM 分页(经典老写法)

老写法

sql 复制代码
SELECT *
FROM (
  SELECT A.*, ROWNUM RN
  FROM (
    SELECT * FROM EMP ORDER BY HIREDATE DESC
  ) A
  WHERE ROWNUM <= 20
)
WHERE RN > 10;

新写法(12c+)

sql 复制代码
SELECT *
FROM EMP
ORDER BY HIREDATE DESC
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;

📌 ROWNUM 是 Oracle 特有

📌 OFFSET / FETCH 是 ANSI SQL


七、SELECT COUNT(*) INTO V_CNT FROM ... WHERE ROWNUM=1

老写法(判断是否存在)

sql 复制代码
SELECT COUNT(*)
INTO V_CNT
FROM EMP
WHERE DEPTNO = 10
  AND ROWNUM = 1;

新写法

sql 复制代码
SELECT 1
INTO V_FLAG
FROM EMP
WHERE DEPTNO = 10
FETCH FIRST 1 ROWS ONLY;

📌 老写法是为了性能优化(找到一条就停)


八、EXISTS 里的 SELECT 1(老习惯)

老写法

sql 复制代码
SELECT *
FROM EMP E
WHERE EXISTS (
  SELECT 1
  FROM DEPT D
  WHERE D.DEPTNO = E.DEPTNO
);

说明

  • SELECT 1 是历史习惯
  • Oracle 实际不关心 SELECT 列表
  • SELECT NULL 也一样

📌 这是"老派写法",不是错误


九、|| 字符串拼接(Oracle 传统)

老写法

sql 复制代码
SELECT 'A' || 'B' FROM DUAL;

新写法(ANSI)

sql 复制代码
SELECT CONCAT('A', 'B') FROM DUAL;

📌 || 是 Oracle / PostgreSQL 风格

📌 CONCAT 在 MySQL / SQL Server 中更通用


十、HINT 写在注释里(Oracle 特色)

老写法

sql 复制代码
SELECT /*+ INDEX(E EMP_IDX) */
  *
FROM EMP E;

📌 注释不是注释,是优化器指令

📌 这种"伪装成注释的语法"是 Oracle 独有


十一、你这条 SQL 里还藏着的"老味儿"

结合你刚才的 SQL,其实还有这些老特征:

特征 老/新
逗号 + WHERE 关联
LAG 窗口函数
多层子查询
GROUP BY 长字段拼接
无 WITH(CTE)
无 JOIN ON

十二、总结一张对照表(速查)

场景 老写法 新写法
内连接 , + WHERE JOIN ... ON
外连接 (+) LEFT/RIGHT JOIN
条件分支 DECODE CASE
空值处理 NVL COALESCE
分页 ROWNUM OFFSET/FETCH
存在判断 COUNT(*)+ROWNUM=1 EXISTS + FETCH

十三、给你的实战建议(很实用)

  1. 读老代码:必须会老写法
  2. 写新代码:优先用 ANSI SQL
  3. 重构老 SQL
    • 先不改逻辑
    • 只把 , + WHEREJOIN ON
  4. 性能别乱动:老 SQL 很多"反直觉写法"是为性能服务的

相关推荐
金融小白数据分析之路8 小时前
绍兴市镇街echarts 制作
前端·数据库·echarts
桐薇全肯定8 小时前
MySQL学生成绩管理系统实战操作
java·数据库·sql
hellojike8 小时前
free-stockdb本地金融数据库核心设计
数据库·金融
井川廊咏8 小时前
初探性能优化——2个月到4小时的性能提升
jvm·数据库·性能优化
这个DBA有点耶8 小时前
热点行更新:秒杀场景下一条UPDATE语句的锁等待与性能优化
数据库·sql·mysql·性能优化·database·dba
在水一缸8 小时前
深入浅出:Node.js 下一代 ORM 架构设计与实战解析
数据库·微服务·云原生·node.js·orm·架构设计
爱喝水的鱼丶9 小时前
SAP-ABAP:SELECT查询性能优化基础——索引匹配、条件顺序与缓冲机制利用技巧
数据库·性能优化·select·sap·abap·开发交流·交流学习
zhoupenghui1689 小时前
ClickHouse merge引擎详解以及应用
数据库·clickhouse·merge·mergetree
@insist1239 小时前
信息系统管理工程师-任务、标准、EDM 过程与关键域
java·大数据·数据库
qq_366086229 小时前
关于接口路径中中文值解码问题
java·开发语言·数据库