以下是五大数据库(MySQL、PostgreSQL、Oracle、SQL Server、SQLite)核心语法对比,涵盖 DDL、DML、查询、函数、事务等全场景,包含底层原理差异和实用示例。## 一、数据
分类 | MySQL | PostgreSQL | Oracle | SQL Server | SQLite |
---|---|---|---|---|---|
整数 | TINYINT , INT , BIGINT |
SMALLINT , INT , BIGINT |
NUMBER(10) |
TINYINT , INT , BIGINT |
INTEGER |
浮点数 | FLOAT , DOUBLE |
REAL , DOUBLE PRECISION |
BINARY_FLOAT , BINARY_DOUBLE |
FLOAT , REAL |
REAL |
字符串 | VARCHAR(255) CHAR(10) |
VARCHAR(50) TEXT |
VARCHAR2(50) CLOB |
VARCHAR(50) CHAR(10) |
TEXT |
日期时间 | DATE DATETIME(6) TIMESTAMP |
DATE TIMESTAMP TIMESTAMPTZ |
DATE (含时间)TIMESTAMP |
DATE DATETIME2 DATETIMEOFFSET |
TEXT (ISO8601)INTEGER (Unix时间) |
二进制 | BLOB |
BYTEA |
BLOB |
VARBINARY(MAX) |
BLOB |
布尔值 | TINYINT(1) /BOOL |
BOOLEAN |
无原生类型(用 NUMBER(1) ) |
BIT |
无(用 INTEGER ) |
自增主键 | AUTO_INCREMENT |
SERIAL /BIGSERIAL |
序列+触发器 | IDENTITY(1,1) |
AUTOINCREMENT |
特殊类型 | JSON |
JSONB (二进制存储) |
JSON (12c+) |
JSON (2016+) |
JSON (扩展) |
关键差异:
Oracle 的 DATE 包含日期+时间(精确到秒)
SQLite 无严格类型校验(动态类型)
PostgreSQL 的 JSONB 支持索引,处理更快
-- MySQL (含存储引擎)
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
-- PostgreSQL (含模式/继承)
CREATE TABLE public.users (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
tags VARCHAR[] -- 数组类型
) INHERITS (base_table);
-- Oracle (表空间+存储参数)
CREATE TABLE users (
id NUMBER PRIMARY KEY,
name VARCHAR2(50),
created_at TIMESTAMP DEFAULT SYSTIMESTAMP
) TABLESPACE users_tbs PCTFREE 10;
-- SQL Server (含文件组)
CREATE TABLE dbo.users (
id INT IDENTITY(1,1) PRIMARY KEY,
name NVARCHAR(50),
sys_created DATETIME2 DEFAULT GETDATE()
) ON PRIMARY TEXTIMAGE_ON users_fg;
-- SQLite (严格模式)
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL CHECK(length(name) > 0)
) STRICT;
操作 | MySQL | PostgreSQL | Oracle | SQL Server | SQLite |
---|---|---|---|---|---|
添加列 | ALTER TABLE users ADD COLUMN email VARCHAR(100); |
同左 | ALTER TABLE users ADD (email VARCHAR2(100)); |
同 MySQL | 仅支持有限操作 (需3.25+) |
删除列 | ALTER TABLE users DROP COLUMN email; |
同左 | 同左 | 同左 | ALTER TABLE users DROP COLUMN email; (3.35+) |
重命名列 | ALTER TABLE users CHANGE name fullname VARCHAR(50); |
ALTER TABLE users RENAME COLUMN name TO fullname; |
同 PostgreSQL | EXEC sp_rename 'users.name', 'fullname', 'COLUMN'; |
无法直接重命名 |
-- MySQL (单个ID)
INSERT INTO users (name) VALUES ('Alice');
SELECT LAST_INSERT_ID(); -- 返回最后插入ID
-- PostgreSQL (多行返回)
INSERT INTO users (name) VALUES ('Bob') RETURNING id, name;
-- Oracle (绑定变量)
DECLARE
new_id NUMBER;
BEGIN
INSERT INTO users (id, name) VALUES (users_seq.NEXTVAL, 'Charlie')
RETURNING id INTO new_id;
END;
-- SQL Server (OUTPUT 子句)
INSERT INTO users (name)
OUTPUT INSERTED.id, INSERTED.name
VALUES ('Dave');
-- SQLite
INSERT INTO users (name) VALUES ('Eve');
SELECT last_insert_rowid(); -- 获取最后插入ROWID
-- 更新前10条符合条件的记录
/* MySQL/SQLite */
UPDATE users SET status=1 WHERE is_active=0 LIMIT 10;
/* PostgreSQL */
UPDATE users SET status=1 WHERE ctid IN (
SELECT ctid FROM users WHERE is_active=0 LIMIT 10
);
/* Oracle */
UPDATE (
SELECT * FROM users WHERE is_active=0 AND ROWNUM <= 10
) SET status=1;
/* SQL Server */
UPDATE TOP (10) users SET status=1 WHERE is_active=0;
-- 基于连接更新 (语法差异)
/* MySQL */
UPDATE users u
JOIN profiles p ON u.id = p.user_id
SET u.last_login = NOW()
WHERE p.country = 'US';
/* Oracle/SQL Server */
UPDATE users
SET last_login = SYSDATE -- 或 GETDATE()
FROM users u
INNER JOIN profiles p ON u.id = p.user_id
WHERE p.country = 'US';
-- 取第 21-30 条数据
/* MySQL/PostgreSQL/SQLite (通用) */
SELECT * FROM users ORDER BY id LIMIT 10 OFFSET 20;
/* PostgreSQL/SQL Server (2012+) / Oracle 12c+ */
SELECT * FROM users
ORDER BY id
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;
/* Oracle (传统方式) */
SELECT * FROM (
SELECT t.*, ROWNUM rn FROM (
SELECT * FROM users ORDER BY id
) t WHERE ROWNUM <= 30
) WHERE rn > 20;
/* SQL Server (2005-2012) */
SELECT TOP 10 * FROM (
SELECT ROW_NUMBER() OVER (ORDER BY id) AS rn, *
FROM users
) AS tmp WHERE rn > 20;
-- 计算3天后的日期
SELECT NOW() + INTERVAL 3 DAY; -- MySQL
SELECT CURRENT_DATE + INTERVAL '3 days'; -- PostgreSQL
SELECT SYSDATE + 3 FROM DUAL; -- Oracle
SELECT DATEADD(DAY, 3, GETDATE()); -- SQL Server
SELECT DATE('now','+3 days'); -- SQLite
-- 格式化日期为 'YYYY年MM月DD日'
SELECT DATE_FORMAT(NOW(), '%Y年%m月%d日'); -- MySQL
SELECT TO_CHAR(NOW(), 'YYYY"年"MM"月"DD"日"'); -- PostgreSQL/Oracle
SELECT FORMAT(GETDATE(), 'yyyy年MM月dd日'); -- SQL Server
SELECT strftime('%Y年%m月%d日', 'now'); -- SQLite
-- 递归查询 (Hierarchical Data)
/* MySQL (8.0+) */
WITH RECURSIVE cte AS (...);
/* PostgreSQL/Oracle/SQL Server */
WITH cte AS (...) -- 标准递归写法,语法相似
/* SQLite (不支持标准递归) */
-- 需用临时表或程序处理
-- 窗口函数 (计算累计销量)
/* 通用语法 */
SELECT
order_date,
daily_sales,
SUM(daily_sales) OVER (ORDER BY order_date) AS running_total
FROM sales;
-- 查找以A开头的名字
SELECT * FROM users WHERE name REGEXP '^A'; -- MySQL
SELECT * FROM users WHERE name ~ '^A'; -- PostgreSQL
SELECT * FROM users WHERE REGEXP_LIKE(name, '^A'); -- Oracle
SELECT * FROM users WHERE name LIKE 'A%'; -- SQL Server(正则需PATINDEX)
SELECT * FROM users WHERE name REGEXP '^A'; -- SQLite(需加载REGEXP扩展)
数据库 | 支持索引类型 |
---|---|
MySQL | BTREE、FULLTEXT(全文搜索)、SPATIAL(空间数据)、HASH(Memory引擎专属) |
PostgreSQL | BTREE、HASH、GIN(JSON/数组)、GiST(地理/全文)、BRIN(块范围索引) |
Oracle | BTREE、位图索引、函数索引、域索引、反向键索引、全局/局部分区索引 |
SQL Server | 聚集索引、非聚集索引、列存储索引(列式数据)、空间索引、全文索引、筛选索引(条件索引) |
SQLite | 仅支持B树索引(包括唯一索引和主键索引) |
行为 | MySQL (InnoDB) | PostgreSQL | Oracle | SQL Server | SQLite |
---|---|---|---|---|---|
默认隔离级别 | REPEATABLE READ | READ COMMITTED | READ COMMITTED | READ COMMITTED | SERIALIZABLE |
行级锁 | 支持(MVCC) | 支持(MVCC) | 支持(MVCC) | 支持 | 仅库级写锁 |
死锁检测 | 自动 | 自动 | 自动 | 自动 | 无(超时返回错误) |
保存点 | SAVEPOINT sp1; |
相同 | 相同 | 相同 | 支持 |
隐式提交行为 | DDL自动提交 | DDL不提交事务 | DDL自动提交 | 部分DDL自动提交 | DDL不提交 |
关键机制详解:
1、隔离级别:
REPEATABLE READ:MySQL默认级别,通过MVCC实现快照读
READ COMMITTED:PG/Oracle/SQL Server默认,存在不可重复读问题
SERIALIZABLE:SQLite默认,完全串行化执行
2、锁机制:
MVCC(多版本并发控制):写操作不阻塞读操作
SQLite的库级写锁:同一时间只允许一个写操作
3、死锁处理:
自动检测:主流数据库均支持死锁自动检测和回滚
SQLite处理:通过busy_timeout参数设置超时(默认0)
4、DDL事务行为:
自动提交:MySQL/Oracle执行DDL会隐式提交当前事务
事务内支持:PostgreSQL/SQLite允许在事务中执行DDL
开发建议:
高并发场景使用READ COMMITTED隔离级别提升吞吐量
金融交易等敏感操作使用SERIALIZABLE保证绝对一致
避免长事务:MySQL的undo日志膨胀,Oracle的ORA-01555错误
SQLite写密集型应用考虑使用WAL模式提升并发