当插入引用其他两个表的第三个表时,如何检查两个表之间的约束?

发布于 2024-07-12 05:02:37 字数 819 浏览 6 评论 0原文

考虑这个示例架构:

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 可以为 null。

谢谢,埃吉尔。

Consider this example schema:

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, .... )

Basically, three tables:

  • A customer table with a primary key and some additional columns
  • A employee table with a primary key, a foreign key constraint reference to the customer tables primary key, representing an employee of the customer.
  • A work item table, which stores work done for the customer, and also info about the specific employee who the work was performed for.

My question is. How do I, on a database level, test if an employee is actually associated with a customer, when adding new work items.

If for example Scott (employee) works at Microsoft (customer), and Jeff (employee) works at StackOverflow (customer), how do I prevent somebody from adding a work item into the database, with customer = Microsoft, and employee = Jeff, which do not make sense?

Can I do it with check constraints or foreign keys or do I need a trigger to test for it manually?

Should mention that I use SQL Server 2008.

UPDATE: I should add that WorkItem.EmployeeId can be null.

Thanks, Egil.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

七颜 2024-07-19 05:02:37

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

ALTER TABLE WorkItem
ADD CONSTRAINT FK_Customer_Employee FOREIGN KEY (CustomerId, EmployeeId)
    REFERENCES Employee (CustomerId, EmployeeId);

Wouldn't a foreign key on a composite column (CustomerId, EmployeeId) work?

ALTER TABLE WorkItem
ADD CONSTRAINT FK_Customer_Employee FOREIGN KEY (CustomerId, EmployeeId)
    REFERENCES Employee (CustomerId, EmployeeId);
櫻之舞 2024-07-19 05:02:37

您可以通过创建一个视图“WITH SCHEMABINDING”来实现此目的,该视图跨越这些表并强制执行各个表的集体约束。

You might be able to do this by creating a view "WITH SCHEMABINDING" that spans those tables and enforces the collective constraints of the individual tables.

装纯掩盖桑 2024-07-19 05:02:37

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

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

Why do you want employeeId to be null int WorkItem? Maybe you should add another table to avoid that particular oddity. From what I can see the easiest thing to do is to add a unique constraint on employeeid in workItem, and maybe even unique on customerId if that is what you want.

A more general way to add constraints spanning many tables is to define a view that should always be empty, and add the constraint that it is empty.

娜些时光,永不杰束 2024-07-19 05:02:37

你想在这里建模什么?

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

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

    您实际上正在存储有关

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

在情况 (2) 中,Employee 的主键实际上应该是 CustomerIdEmployeeId。 两个客户可以拥有相同的员工 ID 号。 然后 Kieron 的外键就可以工作了。

What are you trying to model here?

  1. You're a contracting agency or the like, and you have a bunch of contractors who are (for some period of time) assigned to a customer.

  2. You're actually storing information about other company's employees (maybe you're providing outsources payroll services, for example).

In case (1), it looks like you have a problem with the Employee table. In particular, when Scott's contract with MS is up and he gets contracted to someone else, you can't keep the historical data, because you need to change the CustomerId. Which also invalidates all the WorkItems. Instead, you should have a fourth table, e.g., CustomerEmployee to store that. Then WorkItem should reference that table.

In case (2), your primary key on Employee should really be CustomerId, EmployeeId. Two customers could have the same employee ID number. Then Kieron's foreign key will work.

悍妇囚夫 2024-07-19 05:02:37

我最近遇到了类似的情况,考虑一下架构:
表company (id_cia PK) 表product_group (id_cia FK to company, id_group PK) 表products (id_group FK to Product_group, id_product PK, id_used_by_the_client null)

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

插入公司 (1) = 允许

插入公司 (2) = 允许

插入产品组 (1, 1) = 允许

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

插入产品组 (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。

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

I recently pass to a similar situation, consider the schema:
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)

Rule: The database must allow only one id_used_by_the_client for each product of a company but this filed can be null. Example:

Insert into company (1) = allowed

Insert into company (2) = allowed

Insert into product_group (1, 1) = allowed

Insert into product_group (1,2) = allowed

Insert into product_group (2,3) = allowed

Insert into products values (1, 1, null) = allowed

Insert into products values (1, 2, null) = allowed

Insert into products values (1, 3, 1) = allowed

Insert into products values (1, 4, 1) = not allowed, in the group 1 that belongs to company 1 already exists an id_used_by_the_client = 1.

Insert into products values (2, 4, 1) = not allowed, in the group 2 that belongs to company 1 already exists an id_used_by_the_client = 1.

Insert into products values (3, 4, 1) = allowed, in the group 3 that belongs to company 2 there is no id_used_by_the_client = 1.

I decided to use a trigger to control this integrity.

随风而去 2024-07-19 05:02:37

或者:

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

或者:

  • 将 WorkItem 的 EmployeeID 和 CustomerID 列设置为 Employee 的复合外键。

我个人赞成第一种方法。

Either:

  • make the EmployeeID column the Primary Key of Employee (and possibly an auto-id) and store the EmployeeID in the WorkItem record as a foreign key, instead of storing the Employee and Customer IDs in WorkItem. You can retrieve a WorkItem's Customer details by joining to the Customer table via the Employee table.

Or:

  • make the WorkItem's EmployeeID and CustomerID columns a composite foreign key to Employee.

I favour the first approach, personally.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文