如何在SQLite及Prisma中使用ON CONFLICT REPLACE等冲突处理策略?
在SQLite中用ON CONFLICT REPLACE做插入,以及Prisma里的实现方法
一、原生SQLite里的ON CONFLICT REPLACE用法
要用上ON CONFLICT策略,前提是你的表得有唯一约束——比如主键、唯一索引,只有当插入的数据违反这些约束时,才会触发REPLACE/IGNORE这类逻辑。
举个例子,先建个带唯一约束的表:
CREATE TABLE users ( id INTEGER PRIMARY KEY, name TEXT, email TEXT UNIQUE );
用INSERT OR REPLACE
这是SQLite的简化写法,直接在INSERT后面加OR REPLACE,只要插入的数据触发唯一冲突,就会替换掉已有的记录:
INSERT OR REPLACE INTO users (id, name, email) VALUES (1, 'Alice', 'alice@example.com');
标准ON CONFLICT语法
如果你想指定针对某个特定约束触发REPLACE,比如只对id冲突时处理,就用这种写法:
INSERT INTO users (id, name, email) VALUES (1, 'Alice Updated', 'alice_new@example.com') ON CONFLICT(id) DO REPLACE;
要是想针对email这个唯一约束,把括号里的id换成email就行。
IGNORE策略的用法
和REPLACE类似,要么用简化写法:
INSERT OR IGNORE INTO users (id, name, email) VALUES (1, 'Charlie', 'charlie@example.com');
要么用标准语法:
INSERT INTO users (id, name, email) VALUES (1, 'Charlie', 'charlie@example.com') ON CONFLICT DO IGNORE;
二、Prisma里实现SQLite的冲突处理策略
Prisma是靠模型里定义的唯一约束来识别冲突的,不同场景有不同的实现方式:
1. 单条记录的冲突替换(类似REPLACE)
用Prisma的upsert方法就行,它会先尝试根据where条件找记录,找到就执行update,找不到就执行create。
先定义模型(要加唯一约束):
model User { id Int @id @default(autoincrement()) name String? email String @unique // 这个唯一约束是触发冲突的关键 }
然后写代码:
const user = await prisma.user.upsert({ where: { email: 'alice@example.com' }, // 用email作为冲突判断条件 update: { name: 'Alice Updated' }, // 冲突时更新name字段 create: { name: 'Alice', email: 'alice@example.com' }, // 不存在时创建 });
如果想要完全复刻SQLite的REPLACE(删除旧记录再插入新的),就在update里把所有字段都写上,实现全量覆盖。
2. 批量插入忽略重复(IGNORE策略)
用createMany加skipDuplicates参数就行,开启后违反唯一约束的记录会直接被跳过:
const result = await prisma.user.createMany({ data: [ { name: 'Alice', email: 'alice@example.com' }, { name: 'Bob', email: 'bob@example.com' }, ], skipDuplicates: true, // 开启忽略重复 });
3. 批量插入替换重复(REPLACE策略)
Prisma目前没有直接支持批量REPLACE的createMany参数,不过可以两种方式解决:
- 循环调用
upsert:适合数据量不大的情况,每条记录单独处理冲突。 - 用Prisma的原生SQL执行:直接写SQLite的
INSERT OR REPLACE语句,效率更高:
await prisma.$executeRaw` INSERT OR REPLACE INTO User (id, name, email) VALUES (1, 'Alice Updated', 'alice@example.com'), (2, 'Bob Updated', 'bob@example.com'); `;
内容的提问来源于stack exchange,提问作者Ivan Morgillo
相关产品推荐
相关产品推荐

