SQLite vs MySQL:核心SQL语法差异全面解析
在日常开发中,SQLite 和 MySQL 是我们最常接触的两个关系型数据库。一个轻量便捷,嵌入应用;一个功能强大,服务网络。尽管它们都使用 SQL 作为查询语言,但由于架构和目标不同,其 SQL 语法存在许多关键差异。这些差异常常导致在迁移或切换数据库时出现意想不到的错误。
本文旨在系统梳理两者在 SQL 语法上的核心区别,助你避坑排雷,轻松驾驭这两种数据库。
一、核心概述:设计哲学决定语法差异
- SQLite: 追求轻量、简单和嵌入式。它的 SQL 语法更接近标准 SQL,但功能相对精简。其动态类型系统非常“宽容”,会尝试自动进行类型转换,容错性强。
- MySQL: 作为功能丰富的客户端-服务器数据库,支持高并发和网络访问。其 SQL 语法拥有大量扩展和特性,但也引入了一些非标准语法。其静态类型系统更“严格”,要求数据与定义的类型更匹配。
二、详细语法差异对比
1. 数据类型:动态 vs 静态
这是最根本的差异,直接影响了数据存储的灵活性。
特性 | SQLite | MySQL |
---|---|---|
核心理念 | 动态类型 (Manifest Typing) | 静态类型 (Static Typing) |
机制 | 声明的数据类型仅是“建议”。你可以将任何类型的数据存入任何列(INTEGER PRIMARY KEY 除外)。 | 列严格定义为某种类型,存入不兼容类型的数据会报错或进行严格转换(取决于 SQL_MODE )。 |
示例 | CREATE TABLE t (id INTEGER, name TEXT); INSERT INTO t VALUES ('hello', 123); -- 成功! | CREATE TABLE t (id INT, name VARCHAR(100)); INSERT INTO t VALUES ('hello', 123); -- 在严格模式下会失败! |
布尔值 | 无原生布尔类型,通常用 INTEGER (0 和 1) 表示。 | 有 BOOLEAN 或 BOOL 类型(是 TINYINT(1) 的别名)。 |
日期时间 | 无原生类型,通常用 TEXT , INTEGER , 或 REAL 存储,靠内置函数解析。 | 有丰富的原生类型:DATE , TIME , DATETIME , TIMESTAMP , YEAR 。 |
2. 自增主键 (AUTOINCREMENT)
定义自增主键的语法略有不同。
-- SQLite
CREATE TABLE user (id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT
);-- MySQL
CREATE TABLE user (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(100)
);
注意:关键字 AUTOINCREMENT
和 AUTO_INCREMENT
的拼写差异。
3. 分页查询:LIMIT 和 OFFSET 的“坑”
两者都支持 LIMIT
和 OFFSET
,但兼容语法是最大的陷阱之一。
目标:获取第 21 到 30 条记录(即跳过20条,取10条)。
-- 方式一:标准语法 (两者都支持,强烈推荐!)
SELECT * FROM table_name LIMIT 10 OFFSET 20;-- 方式二:兼容语法 (注意区别!)
-- SQLite 理解为此写法:LIMIT <offset>, <count>
SELECT * FROM table_name LIMIT 20, 10;-- MySQL 理解为此写法:LIMIT <offset>, <count>
-- (但参数顺序与 SQLite 的兼容语法相同,含义却不同)
SELECT * FROM table_name LIMIT 20, 10;
结论:为避免混淆,请始终坚持使用 LIMIT <count> OFFSET <offset>
语法,这在两者中都能正确工作且意图明确。
4. 字符串连接
连接字符串的方式完全不同。
-- SQLite: 使用 || 运算符
SELECT 'Hello ' || 'World' AS greeting;-- MySQL: 使用 CONCAT() 函数
SELECT CONCAT('Hello ', 'World') AS greeting;
注意:在 MySQL 中,+
运算符仅用于数字加法。尝试 SELECT 'a' + 'b';
通常会得到 0
。
5. 获取当前时间
获取系统当前日期时间的函数不同。
-- SQLite: 使用 date(), time(), datetime() 函数与 'now' 参数
SELECT datetime('now'); -- 2024-09-18 06:30:55-- MySQL: 使用特定的函数
SELECT NOW(); -- 2024-09-18 06:30:55
SELECT CURDATE(); -- 2024-09-18
6. 条件判断
-- IFNULL() 函数在两者中用法一致
SELECT IFNULL(NULL, 'Default Value');-- 更复杂的条件判断
-- SQLite: 没有 IF() 函数,必须使用 CASE WHEN
SELECT CASE WHEN score >= 60 THEN 'Pass'ELSE 'Fail'END AS result;-- MySQL: 可以使用 IF() 函数,语法更简洁
SELECT IF(score >= 60, 'Pass', 'Fail') AS result;
7. DDL 语句:ALTER TABLE 支持度
SQLite 对修改表结构的支持非常有限。
- SQLite:仅支持
ADD COLUMN
和RENAME TABLE
。早期版本不支持DROP COLUMN
、RENAME COLUMN
(新版已支持)和ALTER COLUMN
。要复杂修改,通常需要创建新表并迁移数据。 - MySQL:支持完整的 DDL,包括
ADD COLUMN
,DROP COLUMN
,CHANGE COLUMN
,MODIFY COLUMN
等,功能强大。
8. 外键约束
- SQLite:虽然支持外键,但为了向后兼容,默认是关闭的。必须在每次数据库连接后执行一条命令来开启:
PRAGMA foreign_keys = ON;
- MySQL:对于 InnoDB 等存储引擎,外键支持是内置的。其启用与否由系统变量
foreign_key_checks
控制,通常默认是开启的。
三、其他重要差异
特性 | SQLite | MySQL |
---|---|---|
存储过程/函数 | 不支持 | 支持,是其强大功能之一 |
权限系统 | 无,通过文件系统权限控制 | 拥有复杂的用户和权限管理系统 |
网络访问 | 无,直接读写磁盘文件 | 通过网络协议访问 |
四、总结与选择建议
特性 | SQLite | MySQL |
---|---|---|
适用场景 | 移动应用(App)、嵌入式设备、桌面软件、小型工具、数据分析脚本、本地缓存。 | 中大型Web应用、高并发系统、分布式部署、需要复杂业务逻辑和高级数据库特性的项目。 |
迁移建议 | 1. 检查数据类型:确保数据兼容性。 2. 修改自增关键字: AUTOINCREMENT -> AUTO_INCREMENT 。3. 统一分页语法:使用 LIMIT ... OFFSET ... 。4. 替换函数:如 datetime('now') -> NOW() ,` |
选择指南:
- 如果你的项目是本地化、轻量级、需要零配置的(如手机App、单机软件),SQLite 是绝佳选择。
- 如果你的项目是面向网络、多用户、高并发的(如Web网站、SaaS服务),MySQL 及其同类(如PostgreSQL)是更专业的选择。