在我必须为MS Access设计的数据库中,我有一个名为“Measurements”的表,它存储某些测量参数(测量值,标准偏差等) - 每行都有一个整数ID作为其主要值键。
然后,其他表使用外键关系链接到此测量表。一些表包含两个不同的“measurementID”字段,这两个字段都链接到这一个测量表。但是,每个测量只能通过这些字段的一个链接。
如何对多个表中的多个字段强制执行唯一性约束?有办法吗?
答案 0 :(得分:3)
Microsoft ACE / Jet引擎不支持触发器,这是您通常实现此类功能的方式。
编辑:正如@onedaywhen所指出的那样,JET 4.0以后确实支持检查约束,但是在两列中实现xor类型约束并不简单。如果您使用的是Access Forms,则可以实现表单的before update事件并检查约束条件。
答案 1 :(得分:3)
这些约束确实可以使用CHECK
约束在ACE / JET中实现。
表示他们通常会使用触发器进行此类事情的人不会分别知道ACE / Jet和SQL Server中CHECK
约束之间的区别:在SQL Server中他们不能包含子查询,这意味着它们不能引用同一个表中的其他行或其他表中的值,而在ACE / Jet中则可以。
在理想(但尚未存在AFAIK)的SQL-92产品中,所描述的唯一性将使用ASSETION
来实现,处于架构级别。由于CHECK约束是表级别的,并且仅在定义它们的表为UPDATE
d或INSERT
时进行检查,因此您需要对所有引用设置适当的CHECK
约束table(同样适用于SQL Server触发器)。这是一个简单的例子:
CREATE TABLE Parent
(
parent_ID INTEGER NOT NULL IDENTITY UNIQUE,
data_col INTEGER NOT NULL
)
;
CREATE TABLE Child1
(
parent_ID INTEGER NOT NULL
REFERENCES parent (parent_ID),
data_col INTEGER NOT NULL
)
;
CREATE TABLE Child2
(
parent_ID INTEGER NOT NULL
REFERENCES parent (parent_ID),
data_col INTEGER NOT NULL
)
;
ALTER TABLE Child1 ADD
CONSTRAINT child1__no_dups_in_child2
CHECK (NOT EXISTS (
SELECT *
FROM Child1 AS C1
INNER JOIN Child2 AS C2
ON C1.parent_ID = C2.parent_ID
))
;
ALTER TABLE Child2 ADD
CONSTRAINT child2__no_dups_in_child1
CHECK (NOT EXISTS (
SELECT *
FROM Child1 AS C1
INNER JOIN Child2 AS C2
ON C1.parent_ID = C2.parent_ID
))
;
但是,我想知道你是否有子类(即可以键入由ID表示的每个实体),在这种情况下,您应该能够使用FOREIGN KEY
和行级CHECK
约束(或验证规则,如果您更熟悉MS Access接口,而不是CHECK
约束所需的SQL DLL)。逻辑将比表级CHECK
约束更容易实现,只需注意CASCADE
引用操作中的循环。这是另一个简单的例子:
CREATE TABLE Parent
(
parent_ID INTEGER NOT NULL IDENTITY,
child_type VARCHAR(4) NOT NULL,
CONSTRAINT child_type__values
CHECK (child_type IN ('Boy', 'Girl')),
UNIQUE (child_type, parent_ID)
)
;
CREATE TABLE Girls
(
parent_ID INTEGER NOT NULL,
child_type VARCHAR(4) DEFAULT 'girl' NOT NULL,
CONSTRAINT girl_child_type__must_be_girl
CHECK (child_type = 'girl'),
FOREIGN KEY (child_type, parent_ID)
REFERENCES Parent (child_type, parent_ID),
data_col INTEGER NOT NULL
)
;
CREATE TABLE Boys
(
parent_ID INTEGER NOT NULL,
child_type VARCHAR(4) DEFAULT 'boy' NOT NULL,
CONSTRAINT boy_child_type__must_be_boy
CHECK (child_type = 'boy'),
FOREIGN KEY (child_type, parent_ID)
REFERENCES Parent (child_type, parent_ID),
data_col INTEGER NOT NULL
)
;
答案 2 :(得分:0)
Mitch对Access的可能性是正确的。但是,假设你在某个地方有一个BL,那么它正在成为一个合法的业务规则。这就是我最有可能做的事情。
答案 3 :(得分:0)
鉴于您正在设计此数据库。您确定您的表结构遵循标准规范化规则。
对于表A中的一行,能够引用表测量中的两行,这取决于您正在查看的A.row字段,这听起来是一种不寻常的结构。 我觉得表Measurments中的数据确实需要分成两个或者 更多表格。
答案 4 :(得分:0)
我自己警惕触发器和检查约束,主要是因为我开发了大多数没有它们的应用程序(Access / Jet和MySQL / MyISAM)。我同意BobClegg的观点,这听起来像超类型/子类型。在这种情况下,您将使用在外键上具有唯一索引的连接表和指示它是哪种测量类型的列。 FK上的唯一索引将阻止添加第二种类型。这也意味着你的主记录中不会有空字段。当然,一个空的数字字段不是存储问题,但两个独占的字段对我来说总是看起来像设计错误。