对标题感到抱歉,想不出更好的写作方式。
这是我的问题...... 我的数据库中有2个表[图纸]和[修订];
[Drawings] 1-----* [Revisions]
ProjectId(pk) ProjectId(pk)(fk)
DrawingNo(pk) DrawingNo(pk)(fk)
RevisionNo(pk)
LatestRevision
在[ProjectId]和[DrawingNo]中参考[图纸]的[修订版]中有一个外键。 我需要实现一种强制方法,即图纸最新版本号等于修订表中相应的修订号:
... WHERE [Drawings].[LatestRevision] NOT IN (
SELECT [RevisionNo]
FROM [Revisions]
WHERE [Drawings].[ProjectId] = [Revisions].[ProjectId]
AND [Drawings].[DrawingNo] = [Revisions].[DrawingNo])
如何将这样的东西放入外键?
我需要这个才能在sql server 2008 express上工作。
提前感谢您的帮助!
架构:
TABLE Drawings
( ProjectId varchar,
DrawingNo varchar,
LatestRevisions varchar,
...other columns
PRIMARY KEY(ProjectId, DrawingNo)
)
TABLE Revisions
( ProjectId varchar,
DrawingNo varchar,
RevisionNo varchar,
...other columns
PRIMARY KEY(ProjectId, DrawingNo, RevisionNo)
FOREIGN KEY(ProjectId, DrawingNo) REFERENCES (Drawings(ProjectId, DrawingNo))
)
绘图'A'可以有修订版'1',绘图'B'可以有不同的修订版'1', 修订号本身并不是唯一的
答案 0 :(得分:0)
我将采用以下架构:
TABLE drawings
( projectid integer,
drawingno integer,
latestRevision integer,
primary key (projectid, drawingno)
)
TABLE revisions
( revisionno integer primary key,
projectid integer,
drawingno integer,
foreign key (projectid, drawingno)
references (drawings (projectid, drawingno))
)
在这种情况下,我会发出:
ALTER TABLE drawings
ADD FOREIGN KEY (latestRevision)
REFERENCES (revisions(revisionNo))
这意味着每个revisions.revisionNo
都是唯一的,列drawings.latestRevision
是引用revisions
表的主键的外键,即revisionNo
。< / p>
如果您的架构有任何更改,请告诉我。
此外,仅当外键引用另一个表的主键时才会强制执行该外键。如果revisions.revisionno
不是主键或者在此列上禁用了主键约束,则ALTER TABLE .. ADD FOREIGN KEY
语句必然会返回错误。
答案 1 :(得分:0)
以下结构用您的描述替换您的表和外观,除了它在幕后维护而不是显式外键。我不知道您希望在Revisions
支持哪些操作,目前我只支持INSERT
:
create table dbo._Drawings (
ProjectId int not null,
DrawingId int not null,
constraint PK_Drawings PRIMARY KEY (ProjectID,DrawingID)
)
go
create table dbo._Revisions (
ProjectID int not null,
DrawingID int not null,
RevisionNo int not null,
_PreviousRevision as CASE WHEN RevisionNo > 1 THEN RevisionNo - 1 END persisted,
_NextRevision int null,
constraint PK_Revisions PRIMARY KEY (ProjectID,DrawingID,RevisionNo),
constraint FK_Revisions_Drawings FOREIGN KEY (ProjectID,DrawingID)
references _Drawings (ProjectID,DrawingID),
constraint CK_RevisionNos CHECK (RevisionNo >= 1),
constraint UK_Revisions_Previous UNIQUE (ProjectID,DrawingID,_PreviousRevision),
constraint UK_Revisions_Next UNIQUE (ProjectID,DrawingID,_NextRevision),
constraint FK_Revisions_Previous FOREIGN KEY (ProjectID,DrawingID,_PreviousRevision)
references _Revisions (ProjectID,DrawingID,RevisionNo),
constraint FK_Revisions_Next FOREIGN KEY (ProjectID,DrawingID,_NextRevision)
references _Revisions (ProjectID,DrawingID,RevisionNo)
)
以上两个表是&#34;支持商店&#34;对于数据。 _Revisions
表确保修订序列从1开始严格单调递增。每行保留一个外键到其前一个和后一个修订版,除了第一个和最后一个,NULL
替换它们(但是唯一约束确保每个ProjectID
,DrawingID
组合只存在一个。
create view dbo.Drawings
with schemabinding
as
select
d.ProjectID,
d.DrawingID,
r.RevisionNo as LatestRevision
from
dbo._Drawings d
left join
dbo._Revisions r
on
d.ProjectId = r.ProjectID and
d.DrawingId = r.DrawingID and
r._NextRevision is null
上面的视图模仿了您对Drawings
表的要求,并将用于任何实际的数据访问。如果您想强制执行每个绘图必须至少有一个修订的不变量,您可以将left join
切换为inner join
并将其设为indexed view。您需要添加一个触发器来支持INSERT
,其方式与下面Revisions
的方式非常相似,后者会填充两个表格。
create view dbo.Revisions
with schemabinding
as
select
ProjectID,
DrawingID,
RevisionNo
from
dbo._Revisions
此视图会产生Revisions
与查询一样简单的印象
create trigger T_Revisions_I
on dbo.Revisions
instead of insert
as
;with SplitData as (
select ProjectID,DrawingID,RevisionNo,RevisionNo-1 as Prev, Seq
from inserted cross join (select 1 union all select 2) t(Seq)
)
merge into dbo._Revisions r
using SplitData s
on
r.ProjectID = s.ProjectID and
r.DrawingID = s.DrawingID and
(
(s.Seq = 1 and r.RevisionNo = s.Prev) or
(s.Seq = 2 and r.RevisionNo = s.RevisionNo)
)
when matched and s.Seq = 1
then update set _NextRevision = s.RevisionNo
when not matched and s.Seq = 2
then insert (ProjectID,DrawingID,RevisionNo) values (s.ProjectID,s.DrawingID,s.RevisionNo)
;
最后,此触发器负责以上面创建的约束所需的方式维护_Revisions
结构。诀窍是我们使用MERGE
语句,以便在插入新行的同时,我们还更新上一行,以使其_NextRevision
列不再为空引用我们正在插入的行。
可以添加更多触发器以支持更高级的使用。