Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
跨多个表的SQL外键_Sql_Sql Server_Foreign Keys - Fatal编程技术网

跨多个表的SQL外键

跨多个表的SQL外键,sql,sql-server,foreign-keys,Sql,Sql Server,Foreign Keys,我是模特儿。检查表单是任意的,本质上是字段列表 CREATE TABLE InspectionForms ( InspectionFormId INT PRIMARY KEY, InspectionFormName NVARCHAR(64), ... (CreatorId, TimeCreated, etc.) ); CREATE TABLE InspectionFormFields ( InspectionFormId INT FOREIGN KEY REFE

我是模特儿。检查表单是任意的,本质上是字段列表

CREATE TABLE InspectionForms
(
    InspectionFormId INT PRIMARY KEY,
    InspectionFormName NVARCHAR(64),

    ... (CreatorId, TimeCreated, etc.)
);
CREATE TABLE InspectionFormFields
(
    InspectionFormId INT FOREIGN KEY REFERENCES InspectionForms,
    InspectionFormFieldId INT,
    FieldName NVARCHAR(64),
    PRIMARY KEY(InspectionFormId, InspectionFormFieldId)
);
因此,使用名为
浴室
的检查表单,以及
厕所
淋浴
地板
的字段,我们的值如下所示:

InspectionForms
---------------
0    Bathroom


InspectionFormFields
--------------------
0    0    Toilet
0    1    Shower
0    2    Floor
CREATE TABLE InspectionValues
(
    InspectionId INT FOREIGN KEY REFERENCES Inspections,
    InspectionFormId INT FOREIGN KEY REFERENCES InspectionForms,
    InspectionFormFieldId INT,
    Rating TINYINT NOT NULL,
    PRIMARY KEY(InspectionId, InspectionFormId, InspectionFormFieldId),
    FOREIGN KEY(InspectionFormId, InspectionFormFieldId) REFERENCES InspectionFormFields
);
然后是实际完成的检查:

CREATE TABLE Inspections
(
    InspectionId INT PRIMARY KEY,
    InspectionFormId INT FOREIGN KEY REFERENCES InspectionForms,

    ... (InspectorId, TimeOfInspection, etc.)
);

CREATE TABLE InspectionValues
(
    InspectionId INT FOREIGN KEY REFERENCES Inspections,
    InspectionFormFieldId INT,
    Rating TINYINT NOT NULL,
    PRIMARY KEY(InspectionId, InspectionFormFieldId)
);
以下是一些示例值:

Inspections
-----------
0    0    ...


InspectionValues
----------------
0    0    5    (Inspection 0 scored a 5 in the Toilet)
0    1    3    (Inspection 0 scored a 3 in the Shower)
0    2    4    (Inspection 0 scored a 4 in the Floor)
关键是:我希望
检查值
有一个
外键
引用
检查表单字段
。但是它没有
InspectionFormId
列。我可以想出两种理论上的解决方案,但我不知道如何实现这两种方案

解决方案1:我可以简单地将
检查表单
列从
检查
移动到
检查值
,然后添加外键。这将使我们的桌子看起来像这样:

InspectionForms
---------------
0    Bathroom


InspectionFormFields
--------------------
0    0    Toilet
0    1    Shower
0    2    Floor
CREATE TABLE InspectionValues
(
    InspectionId INT FOREIGN KEY REFERENCES Inspections,
    InspectionFormId INT FOREIGN KEY REFERENCES InspectionForms,
    InspectionFormFieldId INT,
    Rating TINYINT NOT NULL,
    PRIMARY KEY(InspectionId, InspectionFormId, InspectionFormFieldId),
    FOREIGN KEY(InspectionFormId, InspectionFormFieldId) REFERENCES InspectionFormFields
);
如果我这样做,我想以某种方式强制所有具有给定
InspectionId
inspectionvalue
共享
InspectionFormId
的公共值(即,我不希望
检查
跨越多个
InspectionForms
)。一种简单有效的方法是确保每次更新时,此查询不会返回任何行:

SELECT InspectionId
FROM InspectionValues a
GROUP BY InspectionId
HAVING MIN(InspectionFormId) < MAX(InspectionFormId);

我使用的是SQL Server 2014,不需要支持任何其他版本的SQL。在这里正确的做法是什么?

您应该在检查表中保留检查表单ID(而不是按照您的建议移动它)。由于InspectionId是主键,因此每个InspectionId不能只有一个inspectionformid

CREATE TABLE Inspections
(
InspectionId INT PRIMARY KEY,
InspectionFormId INT FOREIGN KEY REFERENCES InspectionForms,
);
然后将inspectionformid添加到inspectionvalues表中:

CREATE TABLE InspectionValues
(
InspectionId INT FOREIGN KEY REFERENCES Inspections,
InspectionFormId INT,
InspectionFormFieldId INT,
Rating TINYINT NOT NULL,
PRIMARY KEY(InspectionId, InspectionFormId, InspectionFormFieldId),
FOREIGN KEY(InspectionFormId, InspectionFormFieldId) 
       REFERENCES InspectionFormFields(InspectionFormId, InspectionFormFieldId)
))


在上面的解决方案1中,InspectionValues有两个包含InspectionFormId的外键,但您只需要如上所示的多列键。

是什么强制要求
检查
检查值
表中的
检查Formid
列共享值,给定一个通用的
检查ID
?现在,您甚至不需要检查表。然而,若您添加一个字段,如TimeOfInspection或Inspector,那个么您将需要该表。在任何情况下,为了回答您的问题,插入数据的应用程序都需要确保inspectionid在Inspections表和InspectionValues表之间匹配。@TimCooke:在
检查中
可以添加唯一的(inspectionid,InspectionFormId)
。然后从
InspectionValues
Inspections
的引用将采用
外键(InspectionId,InspectionFormId)引用Inspections(InspectionId,InspectionFormId)
@AndiryM:这正是我要找的!非常感谢@AndriyM检查ID是检查的主键,因此在(检查ID,检查FormID)上添加唯一键是多余的,不必要的