3

考虑这个示例模式:

Customer ( int CustomerId pk, .... )

Employee ( int EmployeeId pk,
           int CustomerId references Customer.CustomerId, .... )

WorkItem ( int WorkItemId pk,
           int CustomerId references Customer.CustomerId,
           null int EmployeeId references Employee.EmployeeId, .... )

基本上,三个表:

  • 具有主键和一些附加列的客户表
  • 一个员工表有一个主键,一个外键约束引用客户表的主键,代表客户的一个员工。
  • 工作项表,其中存储为客户完成的工作,以及有关为其执行工作的特定员工的信息。

我的问题是。在添加新工作项时,我如何在数据库级别测试员工是否实际上与客户相关联。

例如,如果 Scott(员工)在 Microsoft(客户)工作,而 Jeff(员工)在 StackOverflow(客户)工作,我如何防止有人将工作项添加到数据库中,客户 = Microsoft,员工 = Jeff,哪个没有意义?

我可以使用检查约束或外键来完成它,还是需要一个触发器来手动测试它?

应该提到我使用的是 SQL Server 2008。

更新:我应该添加 WorkItem.EmployeeId 可以为空。

谢谢,埃吉尔。

4

6 回答 6

3

复合列(CustomerId,EmployeeId)上的外键不起作用吗?

ALTER TABLE WorkItem
ADD CONSTRAINT FK_Customer_Employee FOREIGN KEY (CustomerId, EmployeeId)
    REFERENCES Employee (CustomerId, EmployeeId);
于 2009-01-31T14:09:43.517 回答
2

您可以通过创建一个跨越这些表并强制各个表的集体约束的视图“WITH SCHEMABINDING”来做到这一点。

于 2009-01-31T14:50:13.623 回答
1

为什么您希望employeeId 为null int WorkItem?也许您应该添加另一个表以避免这种特殊的奇怪情况。据我所知,最简单的做法是在 workItem 中添加对employeeid 的唯一约束,如果您想要的话,甚至可能在customerId 上添加唯一约束。

添加跨越多个表的约束的更一般的方法是定义一个应该始终为空的视图,并添加它为空的约束。

于 2009-01-31T14:33:34.093 回答
1

你想在这里建模什么?

  1. 您是一家承包机构或类似机构,并且您有一堆(在一段时间内)分配给客户的承包商。

  2. 您实际上是在存储有关其他公司员工的信息(例如,您可能正在提供外包工资单服务)。

Employee在情况 (1) 中,您的表格似乎有问题。特别是当 Scott 与 MS 的合同到期并且他与其他人签约时,您无法保留历史数据,因为您需要更改CustomerId. 这也使所有WorkItems 无效。相反,您应该有第四个表,例如,CustomerEmployee用于存储它。然后WorkItem应该引用该表。

在情况 (2) 中,您在 Employee 上的主键实际上应该是CustomerId, EmployeeId。两个客户可以有相同的员工 ID 号。然后 Kieron 的外键将起作用。

于 2009-01-31T15:06:03.607 回答
1

我最近传到类似的情况,考虑架构: Table company (id_cia PK) Table product_group (id_cia FK to company, id_group PK) Table products (id_group FK to product_group, id_product PK, id_used_by_the_client null)

规则:数据库必须为公司的每个产品只允许一个 id_used_by_the_client,但该字段可以为空。例子:

插入公司 (1) = 允许

插入公司 (2) = 允许

插入 product_group (1, 1) = 允许

插入 product_group (1,2) = 允许

插入 product_group (2,3) = 允许

插入产品值 (1, 1, null) = 允许

插入产品值 (1, 2, null) = 允许

插入产品值 (1, 3, 1) = 允许

插入产品值 (1, 4, 1) = 不允许,在属于公司 1 的组 1 中已经存在 id_used_by_the_client = 1。

插入产品值 (2, 4, 1) = 不允许,在属于公司 1 的组 2 中已经存在 id_used_by_the_client = 1。

插入产品值 (3, 4, 1) = 允许,在属于公司 2 的组 3 中没有 id_used_by_the_client = 1。

我决定使用触发器来控制这种完整性。

于 2011-10-14T16:30:14.227 回答
0

任何一个:

  • 将 EmployeeID 列设为 Employee 的主键(也可能是自动 ID),并将 EmployeeID 作为外键存储在 WorkItem 记录中,而不是将 Employee 和 Customer ID 存储在 WorkItem 中。您可以通过 Employee 表加入 Customer 表来检索 WorkItem 的 Customer 详细信息。

或者:

  • 使 WorkItem 的 EmployeeID 和 CustomerID 列成为 Employee 的复合外键。

我个人赞成第一种方法。

于 2009-01-31T14:31:26.390 回答