主流数据库语言语法对比

  以下是​五大数据库(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 支持索引,处理更快

二、DDL 语句详解(建表/修改)

1. 创建表示例

-- 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;

2. 修改表结构

操作 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'; 无法直接重命名

三、DML 操作高级对比

1. 插入数据:返回自增值

-- 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

2. 更新/删除:条件控制与限制

-- 更新前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';

四、查询语法核心差异

1. 分页查询实现

-- 取第 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;

2. 日期函数实战

-- 计算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

3. 高级查询特性

-- 递归查询 (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;

五、关键功能差异对比

1. 正则表达式

-- 查找以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扩展)

2. 索引类型

数据库 支持索引类型
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模式提升并发

你可能感兴趣的:(数据库)