作为长期使用两种数据库的开发者,我发现SQL Server和MySQL在基础语法上存在诸多差异。这些差异看似细微,但在实际开发中却可能造成不小的困扰。下面我将从日常开发最常用的几个方面,详细对比两种数据库的语法区别。
SQL Server中使用IDENTITY属性实现自增:
sql复制CREATE TABLE stu (
id INT IDENTITY(1,1) PRIMARY KEY, -- 从1开始,每次递增1
name NVARCHAR(100) NOT NULL
);
而MySQL则使用AUTO_INCREMENT关键字:
sql复制CREATE TABLE stu (
id INT AUTO_INCREMENT PRIMARY KEY, -- 默认从1开始递增
name VARCHAR(100) NOT NULL
);
注意:SQL Server的IDENTITY可以指定起始值和步长(如IDENTITY(100,2)表示从100开始,每次加2),这在某些特殊业务场景下非常有用。
SQL Server使用GETDATE()函数:
sql复制SELECT GETDATE(); -- 返回当前日期时间
MySQL则使用NOW()或SYSDATE():
sql复制SELECT NOW(); -- 返回当前日期时间
SELECT CURRENT_TIMESTAMP; -- 标准SQL语法,两种数据库都支持
实际开发中需要注意,GETDATE()在SQL Server中是确定性函数(在单个语句中多次调用返回相同值),而MySQL的SYSDATE()每次调用都会获取实时时间。
SQL Server使用系统存储过程:
sql复制EXEC sp_help 'Student'; -- 显示表结构、索引等信息
MySQL使用DESCRIBE或SHOW语句:
sql复制DESCRIBE Student; -- 简写为DESC
SHOW CREATE TABLE Student; -- 显示完整的建表语句
SQL Server使用sp_rename存储过程:
sql复制EXEC sp_rename 'Course', 'course'; -- 注意单引号的使用
MySQL使用RENAME TABLE语句:
sql复制RENAME TABLE Course TO course; -- 标准SQL语法
提示:SQL Server的sp_rename也可以用于重命名列名,而MySQL需要使用ALTER TABLE CHANGE COLUMN语法。
SQL Server和MySQL在添加字段语法上基本一致:
sql复制-- SQL Server
ALTER TABLE stu ADD phone VARCHAR(15);
-- MySQL
ALTER TABLE stu ADD phone VARCHAR(15);
但MySQL支持在添加字段时指定位置:
sql复制ALTER TABLE stu ADD phone VARCHAR(15) AFTER name; -- 将phone字段放在name字段后
分页查询是业务系统中最常用的功能之一,两种数据库的实现方式差异较大。
SQL Server 2012+版本引入了OFFSET-FETCH语法:
sql复制SELECT * FROM 表名
ORDER BY 主键或其他索引列
OFFSET ((@pageIndex-1)*@pageSize) ROWS
FETCH NEXT @pageSize ROWS ONLY;
示例:
sql复制SELECT * FROM stu
ORDER BY id
OFFSET 2 ROWS
FETCH NEXT 4 ROWS ONLY;
这种语法直观易读,执行效率也较高,是SQL Server中推荐的分页方式。
在旧版本SQL Server中,常用TOP嵌套查询实现分页:
sql复制SELECT TOP @pageSize * FROM 表名 WHERE 主键>=
(SELECT MAX(主键)
FROM (
SELECT TOP ((@pageIndex-1)*@pageSize+1) 主键
FROM 表名
ORDER BY 主键 ASC
) temp_max_ids)
ORDER BY 主键;
示例:
sql复制SELECT TOP 6 *
FROM stu WHERE id>=(
SELECT MAX(id) FROM (
SELECT TOP 7 id FROM stu ORDER BY id ASC
) temp_max_ids
)
ORDER BY id;
这种方式逻辑复杂,性能也较差,仅在不支持OFFSET-FETCH的旧版本中使用。
MySQL使用LIMIT子句实现分页,语法简洁:
sql复制SELECT * FROM 表名
ORDER BY 主键
LIMIT 起始位置, 记录数;
-- 或
LIMIT 记录数 OFFSET 起始位置;
示例(获取第3页,每页4条):
sql复制SELECT * FROM stu
ORDER BY id
LIMIT 8, 4; -- 从第8条记录开始(0-based),取4条
-- 等价于
SELECT * FROM stu
ORDER BY id
LIMIT 4 OFFSET 8;
重要提示:MySQL的LIMIT性能通常优于SQL Server的传统分页方式,特别是在大数据量场景下。
SQL Server常用:
MySQL常用:
注意:SQL Server的NVARCHAR和MySQL的UTF8编码字段都支持Unicode字符,但存储方式不同。
SQL Server特有:
MySQL特有:
示例(计算3天后的日期):
sql复制-- SQL Server
SELECT DATEADD(DAY, 3, GETDATE());
-- MySQL
SELECT DATE_ADD(NOW(), INTERVAL 3 DAY);
SQL Server默认使用READ COMMITTED,支持:
MySQL默认使用REPEATABLE READ,支持:
SQL Server使用WITH提示:
sql复制SELECT * FROM table WITH (NOLOCK); -- 脏读
SELECT * FROM table WITH (UPDLOCK); -- 更新锁
MySQL使用特殊语法:
sql复制SELECT * FROM table LOCK IN SHARE MODE; -- 共享锁
SELECT * FROM table FOR UPDATE; -- 排他锁
SQL Server存储过程:
sql复制CREATE PROCEDURE proc_name
@param1 INT,
@param2 VARCHAR(50)
AS
BEGIN
-- 过程体
END
MySQL存储过程:
sql复制CREATE PROCEDURE proc_name(
IN param1 INT,
IN param2 VARCHAR(50)
)
BEGIN
-- 过程体
END
SQL Server:
sql复制DECLARE @var INT;
SET @var = 1;
-- 或
SELECT @var = column FROM table;
MySQL:
sql复制DECLARE var INT DEFAULT 0;
SET var = 1;
-- 或
SELECT column INTO var FROM table;
SQL Server:
MySQL(InnoDB):
SQL Server:
sql复制SET SHOWPLAN_TEXT ON; -- 文本执行计划
SET SHOWPLAN_XML ON; -- XML执行计划
-- 或使用图形化执行计划
MySQL:
sql复制EXPLAIN SELECT * FROM table; -- 基本执行计划
EXPLAIN FORMAT=JSON SELECT * FROM table; -- 详细JSON格式
当需要从SQL Server迁移到MySQL或反之时,需要注意:
我在实际项目迁移中,通常会先使用专门的迁移工具(如MySQL Workbench的迁移向导)进行初步转换,然后手动检查和调整上述关键差异点。