一次仅在一个子记录中将位字段限制为真

Posted

技术标签:

【中文标题】一次仅在一个子记录中将位字段限制为真【英文标题】:Restrict a bit field to true in only one child record at a time 【发布时间】:2020-01-30 06:30:47 【问题描述】:

我有一个Person 表,每个人的记录都属于Company 表中的父记录。

一个Person 被指定为其父Company 的“组织者”。最初,我通过从Company 表中识别Person 记录的递归引用来处理这个问题,它是“组织者” - 但是我用来构建我的应用程序层的软件崩溃了 - 它无法处理递归引用.

我改变了策略,并在Person 表中添加了一个位字段来识别此人是否是“组织者”,但需要确保只有一个一个每个 Company 记录的“组织者”。如果我在 Person 表上使用 AFTER UPDATE 触发器,Person 上的更新会触发 Person 上的更新 - 显然我想避免递归触发器。

我如何确保只有一个Person 为其父级Company 标记为“组织者”?

+-----------+---------+---------+-----------+                             +-----------+---------+---------+-----------+
| FirstName | Surname | Company | Organizer |                             | FirstName | Surname | Company | Organizer |
+-----------+---------+---------+-----------+                             +-----------+---------+---------+-----------+
| John      | Smith   |       1 | True      |                             | John      | Smith   |       1 | True      |
| Mike      | Jones   |       1 | NULL      |                             | Mike      | Jones   |       1 | NULL      |
| Fred      | Green   |       1 | NULL      |                             | Fred      | Green   |       1 | NULL      |
| James     | McMahon |       2 | NULL      |                             | James     | McMahon |       2 | NULL      |
| Philip    | Stills  |       2 | NULL      | Making Philip organizer ==> | Philip    | Stills  |       2 | True      |
| Hector    | Berlioz |       2 | True      | 'triggers' this change  ==> | Hector    | Berlioz |       2 | NULL      |
+-----------+---------+---------+-----------+                             +-----------+---------+---------+-----------+

【问题讨论】:

带有 where 子句的唯一索引?例如,create unique index ix_your_index_name on Person (Company, Organizer) where Organizer is not null 可能不是您想要的,但您是否考虑过在 Company 表中指定一个 Organizer 字段?这样,您可以在那里存储谁是组织者的信息,并在必要时通过连接获取它。此外,您的 person 表是否有唯一的标识符号(类似于 ID?)如果没有,它应该有。 已经提到的唯一索引或带有 udf 的约束,例如:ALTER TABLE [dbo].[Person] WITH CHECK ADD CONSTRAINT [chkUniqueOrganizer] CHECK (([dbo].[CheckUniqueOrganizer](Company)=0)) @Magisch 是的,每个表都有一个 ID,只是为了示例的简单性没有包含它。您的建议正是我最初所做的,但我的客户端软件无法处理递归引用 - 这基本上会使公司成为它自己的子记录之一的子记录。在 SQL Server 中很好,但在应用层中不行。 @user1711390 我不太明白......也许如果你在答案中充实了这个想法? 【参考方案1】:

所以看到这里没有人给出答案,我将发布我最终所做的:

创建了一个名为 Organizer 的单独表,只有两个字段:

CREATE TABLE Organizer (
    Company int NOT NULL UNIQUE,
    Person int NOT NULL,
    CONSTRAINT FK_Organizer_Company FOREIGN KEY (Company) REFERENCES Company(ID) ON DELETE CASCADE,
    CONSTRAINT FK_Organizer_Person FOREIGN KEY (Person) REFERENCES Person(ID) ON DELETE CASCADE,
    CONSTRAINT PK_Organizer_ID PRIMARY KEY (Company, Person)
);
通过使 Company 字段独一无二,我只能为任何公司拥有一个组织者。 ON DELETE CASCADE 阻止我得到不存在的公司或个人的孤立组织者记录。 不记得为什么我在这两个字段中都设置了PRIMARY KEY。似乎不痛。

然后只需检查现有的Organizer 记录并更新它是否存在,或者如果不存在则插入一个。我在应用程序层这样做了,尽管我可以轻松地创建一个存储过程,该过程采用 Company.IDPerson.ID 参数,使用前者检查 Organizer 记录,并相应地更新表。甚至可以检查 Person 是否真的属于该公司,并相应地向应用程序层返回一个值。

【讨论】:

以上是关于一次仅在一个子记录中将位字段限制为真的主要内容,如果未能解决你的问题,请参考以下文章

超出速率限制 - 仅在一台计算机上使用

仅在 MySQL / MariaDB 中将命令限制为过程

如何仅在所有平台的离子中将应用程序限制为纵向模式?

仅在我的 iOS 应用程序中将 tesseract 字符限制为 a-z 和数字

在 Spring 中将自动增量 @Id 限制为 6 位

在 Swift 中将用户输入限制为有效的十进制数