几个表中的1个的外键

时间:2016-03-23 10:19:30

标签: sql sql-server

我有两个表(OrderFreshGoods和OrderUtensils)然后我有一个AuditTrail表。 AuditTrail表与OrderFreshGoods表相关,但我想更改它,以便Audit必须与OrderFreshGoods或OrderUtensils记录相关。我已经看到很多解决方案,其中Audit表说有两个外键(OrderIDFresh,OrderIDUtensils,并且它是可选的,必须填充其中一个)。请注意,我不想要那个解决方案。我希望Audit表有1个外键(OrderID),它必须与OrderFreshGoods.OrderID或OrderUtensils.OrderID相关。

此外,我的两个订单表没有共同的字段,并且在系统周围的大量查询中使用,因此我不想要两种类型订单的父表。

有人可以帮忙吗?我的sql脚本如下,注释应该有助于解释我的测试...

--Setup tables
create table OrderFreshGoods (OrderID int not null primary key, sellBy date, name varchar(20))
go
create table OrderUtensils (OrderID int not null primary key, requiresOver18CheckForKnives bit, colour varchar(20), title varchar(20))
go
create table AuditTrail (AuditId int not null primary key, OrderID int, timeOfEvent date, eventDescription varchar(100))
go

--Base data
insert into OrderFreshGoods values (7, DATEADD(dd, 3, getdate()), 'Organic milk')
insert into OrderUtensils values (8, 0, 'Red', 'Garlic crusher')

--Test data!!!!!!!!!!!!!!
--This should work
insert into AuditTrail values (15, 7, getdate(), 'Logging order for Organic Milk from Corkys Coffee shop.')
--This should work
insert into AuditTrail values (16, 8, getdate(), 'Logging order for a Red Garlic Crusher from Perrys Pizza Place.')
--This should not be allowed
insert into AuditTrail values (17, 9, getdate(), 'Wrongly adding an audit entry before the order, please stop me now!')
--This should not be allowed
insert into AuditTrail values (18, null, getdate(), 'Oh dear, bad code has caused the OrderId to be lost, please stop me now!')

2 个答案:

答案 0 :(得分:1)

你想要的是不可能的,因为你描述它,它违背了关系数据库的前提。

如果遗漏实际的外键,那么您可以随意填充AuditTrail.OrderId 但是你丢失了参照完整性检查,所以你的第三个insert into AuditTrail语句不会失败。然后可以通过应用执行引用检查的插入触发器来修复。但它仍然不会阻止Orders被删除,导致伪关系再次变坏。

另一个也许更好的选择是在两个Order表中添加AuditId字段,并根据需要填写。

答案 1 :(得分:0)

如果你想使用永远正确的关系,那么我可以看到下一个解决方案:

  1. 创建另一个表xxxx,如:

    create table xxxx(id int identity(1,1) primary key)

  2. 将所有可审核表格中的外键添加到xxxx(id)

  3. 在xxxx中创建新记录,同时将记录添加到可审计表中(触发器可以很方便)(您可以在xxxx中包含更多信息)
  4. 将审计表中的外键添加到xxxx(id)
  5. 通过这种方式,您只能在审计表中插入指向xxxx的记录 - 这些记录始终与实际订单相关(并且当某些订单被删除时也不会消失)。