返回文章列表

文章

各个数据库中违反唯一约束的处理方式

目录
  1. 下面分别对 SQLite、MySQL、Oracle、PostgreSQL 四种数据库中如何创建唯一约束、违反唯一约束时的默认行为,以及可用的冲突处理机制和示例做说明,最后以表格形式总结对比。
  2. 1. SQLite
  3. 2. MySQL
  4. 3. Oracle
  5. 4. PostgreSQL
  6. 对比汇总

下面分别对 SQLite、MySQL、Oracle、PostgreSQL 四种数据库中如何创建唯一约束、违反唯一约束时的默认行为,以及可用的冲突处理机制和示例做说明,最后以表格形式总结对比。#

1. SQLite#

  • 创建唯一约束

CREATE TABLE ani_items ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, platform TEXT NOT NULL, UNIQUE(title, platform) );

```
  • 默认行为 插入重复 (title, platform) 时会报错,错误类型 SQLITE_CONSTRAINT_UNIQUE,插入失败。
  • 冲突处理语法
    • 忽略冲突

INSERT OR IGNORE INTO ani_items (...) VALUES (...);

	```
- **标准 UPSERT**
	```sql

INSERT INTO ani_items (...) VALUES (...) ON CONFLICT(title, platform) DO NOTHING;

	```
- **冲突时更新**
	```sql

INSERT INTO ani_items (...) VALUES (...) ON CONFLICT(title, platform) DO UPDATE SET update_count = excluded.update_count, update_time = excluded.update_time;

	```

2. MySQL#

  • 创建唯一约束

CREATE TABLE ani_items ( id INT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(255) NOT NULL, platform VARCHAR(255) NOT NULL, UNIQUE KEY unique_title_platform (title, platform) ) ENGINE=InnoDB;

```
  • 默认行为 插入重复键时会报 ERROR 1062 (23000): Duplicate entry ... for key 'unique_title_platform',插入失败并(若在事务中)回滚。
  • 冲突处理语法
    • 忽略冲突

INSERT IGNORE INTO ani_items (...) VALUES (...);

	```
- **替换行**
	```sql

REPLACE INTO ani_items (...) VALUES (...);

	```
- **UPSERT**
	```sql

INSERT INTO ani_items (...) VALUES (...) ON DUPLICATE KEY UPDATE update_count = VALUES(update_count), update_time = VALUES(update_time);

	```

3. Oracle#

  • 创建唯一约束

CREATE TABLE ani_items ( id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, title VARCHAR2(255) NOT NULL, platform VARCHAR2(255) NOT NULL, CONSTRAINT unique_title_platform UNIQUE (title, platform) );

```
  • 默认行为 插入重复键时会抛出 ORA-00001: unique constraint (….) violated 异常,插入失败。
  • 冲突处理机制
    • MERGE 实现 UPSERT

MERGE INTO ani_items t USING (SELECT :title AS title, :platform AS platform, :count AS update_count FROM dual) src ON (t.title = src.title AND t.platform = src.platform) WHEN MATCHED THEN UPDATE SET t.update_count = src.update_count WHEN NOT MATCHED THEN INSERT (title, platform, update_count) VALUES (src.title, src.platform, src.update_count);

	```
- **PL/SQL 异常捕获**
	```plain text

BEGIN INSERT INTO ani_items (...) VALUES (...); EXCEPTION WHEN DUP_VAL_ON_INDEX THEN NULL; -- 忽略或改用 UPDATE END;

	```

4. PostgreSQL#

  • 创建唯一约束

CREATE TABLE ani_items ( id SERIAL PRIMARY KEY, title TEXT NOT NULL, platform TEXT NOT NULL, UNIQUE (title, platform) );

```
  • 默认行为 插入重复键时报 ERROR: duplicate key value violates unique constraint "ani_items_title_platform_key",插入失败并回滚事务。
  • 冲突处理语法
    • 忽略冲突

INSERT INTO ani_items (...) VALUES (...) ON CONFLICT (title, platform) DO NOTHING;

	```
- **UPSERT**
	```sql

INSERT INTO ani_items (...) VALUES (...) ON CONFLICT (title, platform) DO UPDATE SET update_count = EXCLUDED.update_count, update_time = EXCLUDED.update_time;

	```

对比汇总#

数据库唯一约束创建默认行为冲突时“忽略”冲突时“插入或更新”
SQLiteUNIQUE(title, platform)报错、插入失败INSERT OR IGNOREON CONFLICT … DO NOTHINGON CONFLICT … DO UPDATE SET …
MySQLUNIQUE KEY unique_title_platform (title,platform)报错、插入失败并回滚INSERT IGNOREON DUPLICATE KEY UPDATE …
OracleCONSTRAINT unique_title_platform UNIQUE (…)抛出 ORA-00001 异常PL/SQL 捕获 DUP_VAL_ON_INDEXMERGE INTO … WHEN MATCHED … WHEN NOT MATCHED
PostgreSQLUNIQUE (title, platform)报错、插入失败并回滚ON CONFLICT … DO NOTHINGON CONFLICT … DO UPDATE SET …

如需针对某种数据库的具体示例代码(例如在 Rust 中用 sqlx 或其他驱动)请告诉我!