多对多关系下,单条SQL插入自增表A后关联插入中间表AB的方法
当然可以搞定!不同数据库有各自的小技巧来实现这种“插入表A后立刻拿它的自增ID插关联表AB”的操作,完全不需要拆成两条独立的SQL命令。下面给你整理了几种主流数据库的具体实现方式:
主流数据库的单条SQL实现方案
1. SQL Server
在SQL Server里,咱们可以用OUTPUT子句直接捕获刚插入的自增ID,然后无缝插入AB表。两种写法供你选:
第一种是用变量暂存ID:
DECLARE @NewAId INT; INSERT INTO A (Name) OUTPUT inserted.Id INTO @NewAId VALUES (@name); INSERT INTO AB (A_Id, B_Id) VALUES (@NewAId, @b_Id);
第二种更紧凑,直接用INSERT...SELECT联动:
INSERT INTO AB (A_Id, B_Id) SELECT inserted.Id, @b_Id FROM ( INSERT INTO A (Name) OUTPUT inserted.Id VALUES (@name) ) AS inserted;
说明:OUTPUT inserted.Id会返回刚插入A表的自增ID,全程是原子性操作,保证两个插入要么都成功要么都失败。
2. MySQL
MySQL用672515函数就能拿到当前会话里最后一次自增插入生成的ID,直接在同一条批处理里执行两个插入即可:
START TRANSACTION; INSERT INTO A (Name) VALUES (@name); INSERT INTO AB (A_Id, B_Id) VALUES (672515, @b_Id); COMMIT;
说明:672515是会话级别的,不会被其他会话的插入操作干扰,安全性拉满。
3. PostgreSQL
PostgreSQL的RETURNING子句配合CTE(公共表表达式)可以实现非常简洁的联动插入:
WITH InsertedA AS ( INSERT INTO A (Name) VALUES (@name) RETURNING Id ) INSERT INTO AB (A_Id, B_Id) SELECT Id, @b_Id FROM InsertedA;
说明:CTE会临时存储插入A表的结果,直接从中取ID插入AB,全程是一个原子操作,不用额外事务包裹。
4. Oracle
Oracle 12c及以上支持IDENTITY自增列,用RETURNING子句就能搞定:
DECLARE v_new_a_id NUMBER; BEGIN INSERT INTO A (Name) VALUES (@name) RETURNING Id INTO v_new_a_id; INSERT INTO AB (A_Id, B_Id) VALUES (v_new_a_id, @b_Id); COMMIT; END; /
如果是用序列+触发器实现自增的老版本Oracle,就先拿序列的下一个值插入A,再用当前值插AB:
INSERT INTO A (Id, Name) VALUES (A_SEQ.NEXTVAL, @name); INSERT INTO AB (A_Id, B_Id) VALUES (A_SEQ.CURRVAL, @b_Id);
这些方案都能保证操作的原子性,不会出现“插入A成功但插入AB失败”的尴尬情况,完全满足你的需求。
内容的提问来源于stack exchange,提问作者Tschareck
相关产品推荐
相关产品推荐

