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 很多"反直觉写法"是为性能服务的

相关推荐
小诗懂技术2 小时前
【sqlite3数据库】一站式学会 增删改查 以及数据库c接口编程
数据库·sqlite
风123456789~2 小时前
【架构专栏】第6章 数据库设计基础知识 4/4
数据库·架构
IvorySQL3 小时前
代价比较的变革——PostgreSQL执行计划干预增强深度解析
数据库·postgresql·ffmpeg
SL-staff3 小时前
离散制造企业如何应对频繁插单?智能排产系统带来新思路
大数据·数据库·人工智能·技术教程·智能排产·jvs-aps·排产系统
码云数智-园园3 小时前
Oracle 锁等待、会话阻塞故障复盘:生产事故排查步骤
数据库·oracle
哈__4 小时前
从 MySQL 到在线表格:NocoDB 自托管部署、数据导入与远程访问
数据库·mysql
倔强的石头1065 小时前
高可用与无感扩容——分布式时序数据库选型指南
数据库·分布式·时序数据库
袋鼠云数栈13 小时前
实时湖仓如何真正做到“数据够新”?
大数据·数据库·人工智能·数据治理
ACP广源盛1392462567313 小时前
M6/M5 Pro Mac mini 端侧 AI 落地@ACP#YLB3116 中端多盘存储扩展在 AI 服务中的机会与应用场景
大数据·网络·数据库·人工智能·嵌入式硬件·macos
ACP广源盛1392462567314 小时前
M6/M5 Pro Mac mini 端侧 AI 新形态@ACP#GSV5800 Serdes 长距离视频传输在 AI 服务中的机会与落地场景
大数据·网络·数据库·人工智能·嵌入式硬件·macos·音视频