必须先获取父表自增主键再插入子表,mysql用last_insert_id()(同会话连续执行),sql server用scope_identity()(作用域安全),postgresql用returning子句(一步返回),且外键类型须严格匹配主键类型。

在开发中插入父子表数据时,必须先拿到父表自增主键值才能写入子表外键字段,否则会因外键约束报错或数据不一致。
MySQL中用LAST_INSERT_ID()获取刚生成的主键
这一步操作起来很简单,直接在同一个事务里执行插入后调用函数即可。
第一步:开启事务 → 执行父表INSERT → 立即调用LAST_INSERT_ID()获取ID值。
第二步:将该ID赋值给子表外键字段,再执行子表INSERT。
注意:LAST_INSERT_ID()是会话级的,【必须在同一次数据库连接中连续执行】,跨连接或中间夹了其他INSERT会导致取值错误。
SQL Server中用SCOPE_IDENTITY()安全取值
它比IDENTITY()和@@IDENTITY更可靠,只返回当前作用域(比如当前存储过程或批处理)内最后生成的标识值。
方法一:在T-SQL批处理中使用
BEGIN TRANSACTION;
INSERT INTO Orders (OrderDate, CustomerID) VALUES (GETDATE(), 1001);
DECLARE @NewOrderID INT = SCOPE_IDENTITY();
INSERT INTO OrderItems (OrderID, ProductID, Quantity) VALUES (@NewOrderID, 205, 3);
COMMIT;
方法二:在存储过程中封装逻辑
CREATE PROC InsertOrderWithItems
@CustomerID INT,
@ProductID INT,
@Quantity INT
AS
BEGIN
INSERT INTO Orders (OrderDate, CustomerID) VALUES (GETDATE(), @CustomerID);
INSERT INTO OrderItems (OrderID, ProductID, Quantity)
VALUES (SCOPE_IDENTITY(), @ProductID, @Quantity);
END
PostgreSQL中用RETURNING子句一步到位
这是最简洁的方式,INSERT语句直接返回指定列,无需额外查询。
执行父表插入时加上RETURNING id:
INSERT INTO projects (name, status) VALUES ('新项目', 'active') RETURNING id;
数据库立刻返回刚插入行的id值,应用层可直接捕获并用于后续子表插入。
若需批量插入并获取多个ID,RETURNING也支持,但【不能与ON CONFLICT DO NOTHING合用】,否则可能返回空结果集。
外键字段类型必须严格匹配主键类型
MySQL中父表主键是BIGINT AUTO_INCREMENT,子表外键就必须声明为BIGINT UNSIGNED(如果主键无符号)。
SQL Server中父表用INT IDENTITY,子表外键就不能用SMALLINT,否则ALTER TABLE添加外键时会报错“数据类型不匹配”。
PostgreSQL中SERIAL主键本质是INTEGER,对应外键必须也是INTEGER,哪怕你用int4别名也不行——类型名必须完全一致。











