使用Npgsql的PostgreSQL主数据详细事务处理
假设我有这些桌子:使用Npgsql的PostgreSQL主数据详细事务处理,sql,postgresql,npgsql,Sql,Postgresql,Npgsql,假设我有这些桌子: CREATE TABLE master master_id serial, master_desc character varying CREATE TABLE details details_masterrefid int, details_desc character varying CONSTRAINT master_detail_fkey(details_masterrefid) REFERENCES master(master_id) MATCH SIMPLE
CREATE TABLE master
master_id serial,
master_desc character varying
CREATE TABLE details
details_masterrefid int,
details_desc character varying
CONSTRAINT master_detail_fkey(details_masterrefid)
REFERENCES master(master_id) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION
然后我在C#中有一个代码,它基本上会首先将头插入主表,然后循环遍历细节并将其插入细节表
通过这样做,我必须先插入到主表,然后提交事务,如果事务成功,则获取ID并使用它在细节表中插入。现在,问题是,如果细节中出现了错误,并且插入没有成功,我想回滚插入到主表上的数据。但既然已经承诺了,我就不能收回。要么全是,要么什么都不是。主表和明细表
我能想到的唯一解决方案是允许详细信息中的外键字段为空,然后如果一切都成功,则将外键字段更新为其各自的值。有没有关于如何做得更好的建议?我不知道这是否是一个有效的解决方案。您可以使用单语句
CTE
:
WITH ins1 AS (
INSERT INTO master (cols...)
VALUES (..) -- insert into master
RETURNING master_id -- get generated id
)
INSERT INTO details (...)
SELECT master_id, ... -- insert into child table
FROM ins1;
另一种方法是使用单个事务包装所有内容:
BEGIN TRAN
INSERT INTO master ...
INSERT INTO child ...
COMMIT;
这样,您将获得全部或无行为。您可以使用单个语句
CTE
:
WITH ins1 AS (
INSERT INTO master (cols...)
VALUES (..) -- insert into master
RETURNING master_id -- get generated id
)
INSERT INTO details (...)
SELECT master_id, ... -- insert into child table
FROM ins1;
另一种方法是使用单个事务包装所有内容:
BEGIN TRAN
INSERT INTO master ...
INSERT INTO child ...
COMMIT;
这样,您将获得要么全有,要么全无的行为。是否有什么东西阻止您在一个事务中包装两个表上的所有插入内容?问题是,我不能。由于外键问题,在详细信息中插入数据时将发生错误。由于标头的ID尚未提交。是否有什么东西阻止您在一个事务中包装两个表上的所有插入?问题是,我不能。由于外键问题,在详细信息中插入数据时将发生错误。因为标头的ID还没有提交。正如我所说的。我正在使用NPGSQL。因此,控制事务是在C#@Bigboss中完成的,所以请使用第一种方法。正如我所说的一个声明(全部或全部)。我正在使用NPGSQL。因此,控制事务是在C#@Bigboss中完成的,所以请使用第一种方法。一个语句(全部或无)