SQL Server:如果其中一列的值等于某个值,我该如何防止记录被删除
让我们说,我在两个表(例如OrderHeaders
和OrderDetails
)之间有一个直接的主从关系关系。如果我想要允许在删除主记录的同时删除详细记录,则可以设置两个级联之间关系的删除操作。SQL Server:如果其中一列的值等于某个值,我该如何防止记录被删除
这很好,表格基本上独立于数据库中的其他任何东西。但是,如果我们在某个时间点将订单变成发票,那么很明显,您不会想要删除订单或其相关详细信息。
在我对应的OrderHeaders
表中,我添加了一个简单的布尔列(Posted
),如果订单已转换为发票,则该列设置为true。
如果Posted
的值等于true,那么在SQL中对OrderHeaders
表执行规则以防止删除记录的正确方法是什么?
如果事实上有更好的方法来处理这种特殊情况,那么我完全乐于接受建议,学习新东西总是很好的。
非常感谢
大教堂
有没有条件CASCADE。要处理条件删除,只需定义一个手动删除子行的触发器即可。 (请参阅SQL Server using triggers and geting rid of ON DELETE CASCADE)
我很担心这可能是这种情况。就我个人而言,我不喜欢级联删除,因为它很容易做到你后悔的事情。因此,在这种情况下,我最好的方法可能是根据发布的值过滤UI中的记录,并相应地启用或禁用删除按钮。 –
您是如何创建发票的?我可以告诉你,例如,SAP只需将订单标题和所有详细信息复制到发票和发票详细信息中,以便您可以对订单执行任何操作,但发票保持不变。就我个人而言,我认为这不是一个好的解决方案,因为它基本上保留了两次相同的数据(实际上,如果我没有记错的话,它在sap中最糟糕 - 数据被重复2,3,4甚至5次) 。
一个相当简单的解决方案是使用不是级联删除的外键将发票添加到订单详细信息表中。这样,当您创建发票时,可以将其链接到订单详细信息。一旦记录不能从订单明细表中删除,它的父记录就不能从订单表中删除。
我做了一个简单的演示上rextester向你展示我的意思 - 在这里是完整的例子(如果rextester不可用):
CREATE TABLE OrderHeader
(
id int identity(1,1) primary key,
createDate datetime
);
CREATE TABLE Invoice
(
id int identity(1,1) primary key,
createDate datetime,
OrderId int foreign key references OrderHeader(id)
);
CREATE TABLE OrderDetails
(
id int identity(1,1) primary key,
orderId int foreign key references OrderHeader(id) on delete cascade,
itemId int,
invoiceId int NULL foreign key references Invoice(id)
);
INSERT INTO OrderHeader (createDate) VALUES (DATEADD(DAY, -1, GETDATE())), (GETDATE());
INSERT INTO OrderDetails (orderId, itemId) VALUES (1, 1), (2, 2);
BEGIN TRANSACTION
INSERT INTO Invoice (createDate, OrderId) VALUES (GETDATE(), 1) ;
UPDATE OrderDetails
SET invoiceId = scope_identity()
WHERE OrderId = 1;
COMMIT TRANSACTION
SELECT 'Headers', * FROM OrderHeader;
SELECT 'Details', * FROM OrderDetails;
SELECT 'Invoice', * FROM Invoice;
DELETE FROM OrderHeader WHERE Id = 2;
SELECT 'Headers', * FROM OrderHeader;
SELECT 'Details', * FROM OrderDetails;
SELECT 'Invoice', * FROM Invoice;
DELETE FROM OrderHeader WHERE Id = 1;
如果我的理解是正确的,要删除从OrderHeaders中有删除时的详细信息,但是应该基于另一个表中的张贴标志进行条件操作? – Sujith
订单转换为发票时是否存储其他内容?如果是这样,那么可能没有FK到OrderHeaders而不是Posted列,并且让FK不能级联? –
@Sujith The Posted字段位于OrderHeaders表中。 –