MySQL、Oracle与SQLServer三大数据库语法全方位区别分析
前言
这三大数据库是开发 / 运维最常用的,核心 SQL92/99 标准语法通用(select/from/where/group by/join/order by 等),差异集中在 函数、分页、字符串处理、日期操作、自增主键、语法细节、函数别名、空值处理 等高频开发场景,也是面试 / 项目迁移的高频考点,我按「开发常用分类」整理,条理清晰,方便查阅和复制,优先级从上到下,都是工作最常用的差异点。
一、【最常用】分页查询(开发 TOP1 高频差异,必记)
分页是业务开发中使用频率最高的语法差异,三者写法完全不同,无通用方案,必须单独记忆!
MySQL
特有语法,使用 limit [起始索引], [条数] ,起始索引从 0 开始,极其简洁
-- 查询第11-20条数据(索引从0,跳过前10条,查10条) SELECT * FROM table_name LIMIT 10,10; -- 查询前10条数据(简写) SELECT * FROM table_name LIMIT 10;
Oracle
没有 limit 关键字,两种主流写法,Oracle 12c+ 支持新写法,低版本用子查询 + rownum(必须记)
-- 方式1:Oracle 12c及以上 推荐(简洁,类似MySQL),offset=起始行,fetch next=条数
SELECT * FROM table_name OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;
-- 方式2:所有Oracle版本兼容(最常用),rownum是伪列,行号从1开始,必须套子查询
SELECT * FROM (
SELECT t.*, ROWNUM rn FROM table_name t WHERE ROWNUM <=20
) WHERE rn >=11; -- 查询11-20条SQLServer
两种写法,低版本用top+子查询,2012 及以上版本支持offset/fetch(和 Oracle 12c 一致)
-- 方式1:SQLServer2012+ 推荐,语法和Oracle 12c完全相同 SELECT * FROM table_name OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY; -- 方式2:所有版本兼容,TOP关键字(只能查前N条,分页需子查询) SELECT TOP 10 * FROM table_name; -- 查询前10条
二、字符串处理(高频,拼接 / 长度 / 替换 / 截取,全部差异)
字符串拼接 【开发必用】
这是最基础的高频差异,三者完全不同,90% 的语法报错都来自这里
MySQL
支持两种:CONCAT(str1,str2,...) 函数 或 ||(需开启配置),推荐 CONCAT 函数
SELECT CONCAT('姓名:',NAME,',年龄:',AGE) AS info FROM table_name;Oracle
仅支持 || 拼接符,不支持 + 号;也支持 CONCAT 函数,但 Oracle 的 CONCAT只支持 2 个参数(多拼接必须嵌套 / 用 ||)
-- 推荐(最常用,无参数限制)
SELECT '姓名:' || NAME || ',年龄:' || AGE AS info FROM table_name;
-- 函数写法(仅2个参数)
SELECT CONCAT('姓名:',NAME) AS info FROM table_name;SQLServer
两种方式:+ 拼接符(最常用)、CONCAT(str1,str2,...) 函数(SQLServer2012+)
-- 推荐,简洁高效
SELECT '姓名:'+ NAME + ',年龄:'+ CAST(AGE AS VARCHAR) AS info FROM table_name;
-- 函数写法(自动转换类型,无需CAST)
SELECT CONCAT('姓名:',NAME,',年龄:',AGE) AS info FROM table_name;注意:SQLServer 中,字符串和数字拼接必须用
CAST/convert转类型,否则报错;MySQL/Oracle 自动转换。
其他高频字符串函数(通用名 + 差异写法)
| 功能 | MySQL | Oracle | SQLServer | 说明 |
| 字符串长度 | LENGTH(str) | LENGTH(str) | LEN(str) | 均返回字符长度 |
| 转大写 | UPPER(str) | UPPER(str) | UPPER(str) | 完全通用 |
| 转小写 | LOWER(str) | LOWER(str) | LOWER(str) | 完全通用 |
| 去除首尾空格 | TRIM(str) | TRIM(str) | LTRIM(RTRIM(str)) | SQLServer 无 TRIM,需嵌套 |
| 字符串截取 | SUBSTR(str,start,len) | SUBSTR(str,start,len) | SUBSTRING(str,start,len) | 通用,start 都从 1 开始 |
| 字符串替换 | REPLACE(str,a,b) | REPLACE(str,a,b) | REPLACE(str,a,b) | 完全通用 |
三、日期 & 时间 操作(开发 TOP2 高频差异,函数完全不同)
日期是三大数据库差异最大的模块,函数名 / 语法完全不一样,无通用方案,高频考点 + 开发必记,按「常用操作」整理,最实用!
获取【当前系统时间】【重中之重】
MySQL
NOW() -- 推荐,返回 年月日 时分秒 (yyyy-MM-dd HH:mm:ss) SYSDATE() -- 系统当前时间,同NOW() CURDATE() -- 只返回 年月日 (yyyy-MM-dd) CURTIME() -- 只返回 时分秒 (HH:mm:ss)
Oracle
SYSDATE -- 推荐,返回 年月日 时分秒 (yyyy-MM-dd HH:mm:ss) 无括号! SYSTIMESTAMP -- 带毫秒的时间戳 TRUNC(SYSDATE) -- 只返回 年月日 (yyyy-MM-dd),截取日期部分
SQLServer
GETDATE() -- 推荐,返回 年月日 时分秒 (yyyy-MM-dd HH:mm:ss) CURRENT_TIMESTAMP -- 同GETDATE(),符合SQL标准 CAST(GETDATE() AS DATE) -- 只返回 年月日
日期格式化(转指定格式字符串,开发必用)
MySQL
DATE_FORMAT(日期字段, 格式符) ,格式符用 %Y/%m/%d/%H/%i/%s
SELECT DATE_FORMAT(NOW(),'%Y-%m-%d %H:%i:%s') AS now_time; -- 2026-01-13 16:30:59 SELECT DATE_FORMAT(NOW(),'%Y-%m-%d') AS now_date; -- 2026-01-13
Oracle
两种函数,TO_CHAR(日期,格式符) 最常用,格式符用 YYYY/MM/DD/HH24/MI/SS
SELECT TO_CHAR(SYSDATE,'YYYY-MM-DD HH24:MI:SS') AS now_time FROM DUAL; -- 24小时制 SELECT TO_CHAR(SYSDATE,'YYYY-MM-DD') AS now_date FROM DUAL;
注意:Oracle 的小时必须写
HH24,否则是 12 小时制;必须加FROM DUAL伪表。
SQLServer
CONVERT(数据类型, 日期, 格式码) ,格式码是固定数字(记住常用的即可)
SELECT CONVERT(VARCHAR(20),GETDATE(),120) AS now_time; -- 2026-01-13 16:30:59 最常用 SELECT CONVERT(VARCHAR(10),GETDATE(),23) AS now_date; -- 2026-01-13 纯日期
日期加减(增减年 / 月 / 日 / 时)
MySQL
DATE_ADD(日期, INTERVAL 数值 单位) 或 直接用 日期 + INTERVAL
SELECT DATE_ADD(NOW(),INTERVAL 1 DAY) -- 当前时间+1天 SELECT NOW() - INTERVAL 1 MONTH -- 当前时间-1个月
Oracle
直接用 +/- 运算,日期是数值类型,1=1 天,1/24=1 小时
SELECT SYSDATE + 1 FROM DUAL; -- +1天 SELECT SYSDATE - 1/24 FROM DUAL;-- -1小时 SELECT ADD_MONTHS(SYSDATE, 1) FROM DUAL; -- 加1个月(专用函数)
SQLServer
DATEADD(单位, 数值, 日期) 函数,最规范
SELECT DATEADD(DAY,1,GETDATE()) -- +1天 SELECT DATEADD(MONTH,-1,GETDATE()) -- -1个月
主键自增(建表必备,语法完全不同)
业务表必备的主键自增,三大数据库实现方式完全不同,建表时必用,面试高频题
MySQL
建表时直接给字段加 AUTO_INCREMENT 属性,只支持主键自增,最简洁
CREATE TABLE t_user(
id INT PRIMARY KEY AUTO_INCREMENT, -- 自增主键,插入时无需赋值
name VARCHAR(20) NOT NULL
);
-- 插入时无需写id字段
INSERT INTO t_user(name) VALUES('张三');Oracle
Oracle 11g 及以下 无自增关键字,必须通过【序列 + 触发器】实现自增;Oracle 12c+ 新增自增语法 GENERATED AS IDENTITY,兼容 MySQL 写法
-- Oracle12c+ 推荐写法(简洁) CREATE TABLE t_user( id INT PRIMARY KEY GENERATED AS IDENTITY, name VARCHAR2(20) NOT NULL ); -- Oracle11g及以下 传统写法(序列+触发器),必须创建两个对象 CREATE SEQUENCE seq_user_id START WITH 1 INCREMENT BY 1; -- 创建序列 -- 再创建触发器,插入时自动赋值主键 CREATE TRIGGER tri_user_id BEFORE INSERT ON t_user FOR EACH ROW BEGIN SELECT seq_user_id.NEXTVAL INTO :NEW.id FROM DUAL; END;
SQLServer
建表时给字段加 IDENTITY(起始值,步长) 属性,语法和 MySQL 类似,叫法不同
CREATE TABLE t_user(
id INT PRIMARY KEY IDENTITY(1,1), -- 自增主键,1开始,每次+1
name VARCHAR(20) NOT NULL
);
-- 插入时无需写id字段
INSERT INTO t_user(name) VALUES('张三');空值(NULL)处理(高频坑点,语法不同)
开发中最容易踩坑的点:NULL 参与运算 / 判断时,结果永远是 NULL;三大数据库都有专用函数,函数名不同,必记
核心规则
NULL != '' 、NULL != 0,NULL 表示「无值」,不是空字符串 / 0;判断是否为 NULL 必须用 IS NULL/IS NOT NULL,不能用 = NULL/<> NULL(所有数据库通用)
空值替换函数(开发必用:NULL 替换为指定默认值)
MySQL
IFNULL(字段/表达式, 默认值)
-- 如果age为NULL,显示为0 SELECT IFNULL(age,0) AS age FROM t_user;
Oracle
NVL(字段/表达式, 默认值) ,Oracle 特有,无 IFNULL 函数
-- 如果age为NULL,显示为0 SELECT NVL(age,0) AS age FROM t_user;
SQLServer
ISNULL(字段/表达式, 默认值) ,和 MySQL 的 IFNULL 功能完全一样,只是函数名不同
-- 如果age为NULL,显示为0 SELECT ISNULL(age,0) AS age FROM t_user;
总结
到此这篇关于MySQL、Oracle与SQLServer三大数据库语法全方位区别分析的文章就介绍到这了,更多相关MySQL、Oracle与SQLServer数据库语法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
MySQL数据库char与varchar的区别分析及使用建议
本文主要介绍了mysql中VARCHAR与CHAR字符型数据的差异以及这两种字符型数据在项目中的使用建议,真心不错。值得一看。小编有种受益匪浅的感觉。2014-09-09
如何通过sql查找所有父节点和所有子节点(以mysql为例)
这篇文章主要给大家介绍了关于如何通过sql查找所有父节点和所有子节点,本文以mysql为例,项目中遇到一个需求,要求查处菜单节点的所有节点,这里给大家总结下,需要的朋友可以参考下2023-08-08


最新评论