Oracle 命令速查
DDL / 函数 / 分析函数 / PL/SQL
DDL / 函数 / 分析函数 / PL/SQL
写 CREATE TABLE 时总记不清 VARCHAR 的最大长度、DECIMAL 的精度声明,或者分析函数中 PARTITION BY 与 ORDER BY 的执行顺序。这个速查表把 Oracle 常用的 DDL 语法、内置函数和分析函数按类别列出来,每条附带一个可运行的示例。数据全部预置在页面中,不向任何服务器发送请求,离线环境也能查。
DBA 老张在凌晨两点接到业务通知,下月订单表预计增长 5000 万行,需要当天确定分区策略。是范围分区按月份切、还是列表分区按区域切、或是哈希分区均匀打散?他打开速查页,在「DDL 分区」区段找到各分区的建表语法与适用说明,对比后选定「范围-哈希复合分区」,当场拼出建表 DDL,赶在晨会前提交了方案。
运营总监需要从 120 个门店的周销售额中,提取「每个区域销售额前三的门店」用于发放奖金。用自关联子查询写出来的 SQL 又长又慢,跑一次要 8 分钟。他在分析函数区找到 RANK() 与 DENSE_RANK() 的语法示例,5 分钟内写完带 PARTITION BY region 的 SQL,执行时间降到 12 秒,数据直接导出给财务。
测试组小刘拿到一批生产环境脱敏后的手机号,要求将中间四位替换为星号,且保留前三位和后四位的原始值。他记得 Oracle 有 LPAD、RPAD 和 SUBSTR,但组合起来总报错。在函数区找到字符串函数的完整参数列表与返回值说明,对照着写出 `SELECT SUBSTR(phone,1,3) || '****' || SUBSTR(phone,8,4)`,一次通过 Code Review。
金融风控分析师需要统计过去 7 天每个用户「每日累计交易金额」以及「与前一天相比的环比增长率」。用普通 GROUP BY 只能拿到每日汇总,算不出累计值。他在分析函数区找到 SUM() OVER (ORDER BY day ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) 的写法,配合 LAG() 函数,一条 SQL 输出了 30 天滚动窗口与环比,省去了在 Excel 里手动拉公式的 2 小时。
开发小王在给一个 300 万行的日志表建索引,字段是 timestamp 类型。他纠结是用 B-tree 还是位图索引,以及是否要加函数索引把时间转成日期。在 DDL 索引区看到「位图索引适合低基数列(如性别、状态)」的说明,且函数索引的创建语法与限制一目了然。他决定对 timestamp 字段建普通 B-tree 索引,对状态字段建位图索引,第二天查询性能提升 70%。
| 输入 | 输出 | 说明 |
|---|---|---|
| CREATE TABLE employees (id NUMBER, name VARCHAR2(100), hire_date DATE); | CREATE TABLE employees ( id NUMBER, name VARCHAR2(100), hire_date DATE ); -- 表已创建。 | 常规:最基础的 DDL 建表语句,验证工具能否正确解析并格式化输出。 |
| SELECT ROUND(123.4567, 2) FROM DUAL; | 123.46 | 常规:常用数值函数 ROUND,验证四舍五入逻辑(第三位 6 进位)。 |
| SELECT DENSE_RANK() OVER (ORDER BY salary DESC) AS rank FROM employees; | DENSE_RANK() 返回结果集中各行的排名,排名连续且不跳过(如 1,2,2,3)。 示例输出: RANK ---- 1 2 2 3 | 常规:分析函数 DENSE_RANK 典型用法,验证工具是否提供结果说明而非仅语法。 |
| CREATE TABLE t (id NUMBER(0)); | CREATE TABLE t ( id NUMBER(0) ); -- 表已创建。但 NUMBER(0) 只能存储 0,实际业务中极少使用。 | 边界:精度为 0 的 NUMBER 类型,工具应提示其业务含义限制。 |
| SELECT TRUNC(99.9999, 0) FROM DUAL; | 99 | 边界:TRUNC 函数截断而非四舍五入,验证与 ROUND 的区别。99.9999 截断后为 99。 |
| SELECT FIRST_VALUE(salary) OVER (ORDER BY hire_date) FROM employees; | FIRST_VALUE 返回窗口内第一行的 salary 值。 示例输出(假设 hire_date 最早为 2020-01-01,salary=5000): FIRST_VALUE ----------- 5000 | 边界:分析函数 FIRST_VALUE 在窗口未指定 ROWS/RANGE 时的默认行为(全窗口),验证工具是否说明默认窗口范围。 |
| ALTER TABLE t ADD (col1 NUMBER, col2 NUMBER); | ALTER TABLE t ADD ( col1 NUMBER, col2 NUMBER ); -- 表已修改。注意:ALTER TABLE 添加多列时,列定义需用括号包裹并用逗号分隔。 | 易错:ALTER TABLE ADD 多列的正确语法(括号 + 逗号),新手常误写成 ADD col1 NUMBER, col2 NUMBER(漏括号)。 |
| SELECT NVL(NULL, '默认值') FROM DUAL; | 默认值 | 易错:NVL 函数处理 NULL 值,但第二个参数类型必须与第一个兼容。若类型不匹配会报错,工具应输出结果并提示类型要求。 |
1.DDL 中 VARCHAR2 未指定长度
CREATE TABLE t (name VARCHAR2);CREATE TABLE t (name VARCHAR2(100));Oracle 的 VARCHAR2 必须指定长度(字节或字符),否则报 ORA-00906:缺失左括号。这是 SQL 标准与 Oracle 实现的差异。
2.分析函数 OVER() 内 ORDER BY 与 PARTITION BY 顺序颠倒
SELECT ROW_NUMBER() OVER (ORDER BY dept_id PARTITION BY dept_id) FROM emp;SELECT ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY salary DESC) FROM emp;Oracle 语法要求 PARTITION BY 必须在 ORDER BY 之前,否则报 ORA-00933:SQL 命令未正确结束。这是解析器顺序依赖。
3.TO_DATE 格式串与输入字符串不匹配
TO_DATE('2024-01-15', 'YYYY/MM/DD')TO_DATE('2024-01-15', 'YYYY-MM-DD')TO_DATE 的格式掩码必须精确匹配输入分隔符。'-' 与 '/' 不匹配会报 ORA-01861:文字与格式字符串不匹配。
4.NVL 与 NVL2 参数混淆
NVL2(expr, 'is_null_value')NVL2(expr, 'not_null', 'is_null')NVL2 需要三个参数:expr、非空返回值、空返回值。只传两个参数报 ORA-00909:参数个数无效。
5.DECODE 函数中相等比较误用 '=' 而非逗号
DECODE(status = 'A', 'Active', 'Inactive')DECODE(status, 'A', 'Active', 'Inactive')DECODE 使用逗号分隔参数对,不是等号表达式。写等号会报 ORA-00920:无效的关系运算符。
6.分析函数 LAG/LEAD 的偏移量参数类型错误
LAG(salary, '2') OVER (ORDER BY hire_date)LAG(salary, 2) OVER (ORDER BY hire_date)偏移量必须是数值型,字符串 '2' 会隐式转换失败或报 ORA-01722:无效数字。
7.ALTER TABLE MODIFY 列名后漏写数据类型关键字
ALTER TABLE emp MODIFY salary(10,2);ALTER TABLE emp MODIFY salary NUMBER(10,2);MODIFY 子句必须完整写出新数据类型(NUMBER/VARCHAR2/等),仅写精度括号会被解析为语法错误。
8.TRUNC 函数对 DATE 类型省略 fmt 参数导致时间被截断
SELECT TRUNC(SYSDATE) FROM dual; -- 期望保留时分秒SELECT SYSDATE FROM dual;TRUNC(date) 默认将时间部分截断到午夜 00:00:00。若需保留时间,不应使用 TRUNC。这是函数语义而非错误。
9.MERGE 语句中 ON 条件使用不等号导致全表扫描
MERGE INTO t1 USING t2 ON (t1.id <> t2.id) WHEN MATCHED THEN UPDATE SET ...MERGE INTO t1 USING t2 ON (t1.id = t2.id) WHEN NOT MATCHED THEN INSERT ...MERGE 的 ON 子句设计为等值匹配。使用不等号会使每行都匹配,导致全表更新而非按需操作。
RANK() OVER (PARTITION BY col1 ORDER BY col2 DESC) AS rk
col1分区列,分组依据col2排序列,决定顺序rk排名序号,从1开始递增表 sales 有 dept='IT' 的 3 行:emp='A', amount=500;emp='B', amount=800;emp='C', amount=500。执行 RANK() OVER (PARTITION BY dept ORDER BY amount DESC) 后:B 得 rk=1,A 和 C 并列 rk=2(因 amount 相同,下一名跳过 rk=3)。
可以。本工具的 DDL 语法(CREATE TABLE、ALTER TABLE 等)使用标准 Oracle SQL 写法,与 PL/SQL Developer、SQL*Plus 等客户端兼容。但需要注意两点:一是如果你的表空间名、字段名用了中文,建议用双引号括起来;二是约束名(如 PK_EMP)需要保证在当前 schema 下唯一,否则会报 ORA-02260 错误。直接复制前建议先选中执行,不要全选粘贴。
最常见的原因是格式模型大小写混用。Oracle 中 TO_CHAR 的格式模型是大小写敏感的:'YYYY' 输出四位年份,'RRRR' 也是四位但规则不同;'MM' 是月份数字,'MON' 是英文月份缩写(如 JAN),'Month' 是带首字母大写的全名(如 January)。另外,如果日期字段本身包含时间,但只用 TO_CHAR(date, 'YYYY-MM-DD') 会截断时间,不会报错但结果只有日期部分。建议对照本工具「日期转换」小节里的常用模板来写。
核心区别:GROUP BY 会压缩行,每个分组只返回一行;而 PARTITION BY 不压缩行,每一行都保留,同时计算出聚合值。例如,统计每个部门的平均工资:用 GROUP BY 只能得到部门 + 平均工资两列,看不到每个员工的具体工资;用 ROUND(AVG(salary)) OVER(PARTITION BY dept_id) 则每一行都显示该员工所属部门的平均工资,方便做“比部门平均高多少”的计算。实际使用时,如果既要明细行又要聚合值,只能用分析函数。
是的,本工具完全在浏览器本地运行,没有任何数据上传或后端请求。所有 SQL 语法、示例、说明都打包在页面静态资源中,打开一次后即使断网也能正常使用(前提是浏览器没有清缓存)。适合内网开发环境。如果公司网络限制严格,建议提前在能上网的机器上打开一次,让浏览器缓存完整页面,之后在内网直接访问同一 URL 即可。
本工具的定位是「速查」而非「官方文档」,每个函数只列出最常用的 1-2 种调用形式和典型场景。如果你需要完整的参数列表(例如 LEAD 的 offset 默认值、IGNORE NULLS 子句等),建议结合 Oracle 官方文档(Database SQL Language Reference)或使用 SQL*Plus 的 DESCRIBE 命令查看。速查表更适合你已经知道函数名、但记不清写法时快速确认,不适合零基础从头学。
ORA-30926(无法在源表中获得一组稳定的行)通常是因为 MERGE 的 ON 条件在源表(USING 部分)中匹配到多行,导致目标表的一行对应源表多行,Oracle 不知道用哪行来更新。解决办法:确保 USING 子查询中每个 ON 字段组合是唯一的,或者用 ROW_NUMBER() 分析函数先对源数据去重(例如只取最新一条)。本工具的 MERGE 示例默认使用主键作为 ON 条件,就是为了避免此问题。
功能上,COALESCE 是 NVL 的超集——NVL 只能处理两个参数(expr1, expr2),如果 expr1 为 NULL 则返回 expr2;COALESCE 可以传多个参数,返回第一个非 NULL 值。性能方面,在 Oracle 中两者底层实现几乎一样,没有明显差异。建议优先用 COALESCE,因为更灵活(后续增加备选值不用改函数名),而且 ANSI 标准,迁移到其他数据库时改动更少。如果确定只需要两个参数,用 NVL 也可以,代码更短。
本工具覆盖的语法以 Oracle 11g R2 和 12c 的主流特性为主,但部分 12c 新增功能(如 TOP-N 查询的 FETCH FIRST 子句、IDENTITY 列、WITH FUNCTION 等)没有包含在内,因为 11g 环境无法使用。如果你在使用 11g,建议避开 FETCH FIRST(改用 ROWNUM 或 ROW_NUMBER())、LATERAL 派生表等 12c 特性。工具页面的每个示例都标注了适用版本的最低要求,可以留意看。
隐私保证所有计算与处理均在你的浏览器本地完成,输入数据不会上传服务器,也不会保存或共享。