How to maintain referential integrity of an object graph when a node is deleted

database-designreferential-integrity

In a relational database, if a node in an object graph is deleted, how can the object graph's referential integrity be maintained?

For example:

A product is deleted, how is the invoice containing the order which had a reference to the product kept relevant, in that the order may no longer be relevant. Moreover, how is the order kept relevant?

Best Answer

Typically what you'd do in this scenario is, instead of deleting the products, just set a bit (or use an int type field if there could be more than 2 options) to denote that it is "deleted", or inactive.

create table Product
(
    Id int identity(1, 1) not null,
    Name varchar(100) not null,
    Description varchar(1000) null,
    IsActive bit not null default 1
)
go

Then, instead of calling a DELETE on that table for a product you'll no longer support, just do this:

create procedure DeleteProduct
    @ProdId int
as

    update Product
    set IsActive = 0
    where Id = @ProdId

go

That way you don't cascade delete your orders records, or make them completely useless by setting their foreign key references to NULL or DEFAULT.

That is a pretty specific use-case that you brought up in your question, which is why I geared the first part of my answer off of that. But the beauty of Referential Integrity is that this is handled by the RDBMS with direction of the database designer/developer. Typically, you'd choose exactly how you want that foreign key to be handled when the referenced primary key entry is deleted or updated.

You didn't specify an RDBMS in your question, and I can't speak for the specifics of other RDBMSes, but for SQL Server you can choose the following:

  • ON DELETE NO ACTION : this will prevent the referenced primary key record from being deleted because it has a foreign key referenced (probably a good safetey net for your specific scenario question)
  • ON DELETE CASCADE : this will delete the foreign key referencing record when the primary key referenced record is deleted
  • ON DELETE SET NULL : sets the foreign key value to NULL when the referenced primary key record is deleted
  • ON DELETE SET DEFAULT : similar to ON DELETE SET NULL, except instead of setting the referencing column to NULL, it'll set it to the DEFAULT value for that field