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

相关推荐
自由的裙子1 小时前
How-To: Using the N* Stack, part 4
java·jvm·oracle
努力努力再努力wz2 小时前
【高性能网络库与HTTP Server系列】:基于主从 Reactor 模型实现高性能 C++ 网络库与 HTTP Server
开发语言·网络·数据结构·数据库·c++·网络协议·http
HackTwoHub2 小时前
某单位 CMS 完整渗透链、SQL 注入→后台拿权→绕过宝塔 Waf 上线 shell
数据库·人工智能·sql·安全·网络安全·系统安全·安全架构
Elastic 中国社区官方博客2 小时前
使用 Elasticsearch 作为 Grafana 的直接替代 Prometheus 后端
大数据·数据库·sql·elasticsearch·搜索引擎·grafana·prometheus
杨婷1232 小时前
2026 企业微信会话存档服务商选型指南:一维助手方案深度解析
大数据·数据库·企业微信
霸道流氓气质3 小时前
Kiro 配置 MySQL MCP Server 通用教程
数据库·mysql·adb·mcp·kiro
2601_963771373 小时前
Optimizing Logistics and Transportation Sites on WordPress
前端·数据库·windows·php
AC赳赳老秦3 小时前
采购专员自动化:OpenClaw 自动比价、生成询价单、跟踪供应商报价进度实战指南
开发语言·数据库·人工智能·python·自动化·github·openclaw