0

对不起标题,想不出更好的写法。

这是我的问题...我的数据库 [Drawings] 和 [Revisions] 中有 2 个表;

[Drawings] 1-----* [Revisions]
 ProjectId(pk)      ProjectId(pk)(fk)
 DrawingNo(pk)      DrawingNo(pk)(fk)
                    RevisionNo(pk)
 LatestRevision

在 [ProjectId] 和 [DrawingNo] 上引用 [drawings] 的 [revisions] 中有一个外键。我需要实施一种强制图纸最新修订号等于修订表中相应修订号的方法:

... 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',修订号本身不是唯一的

4

2 回答 2

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

以上两个表是数据的“后备存储”。该_Revisions表确保修订序列从 1 严格单调递增。每一行维护一个外键到其紧邻的先前和后续修订,除了第一个和最后一个,NULLs 替代(但唯一约束确保每个都只存在一个每个ProjectIDDrawingID组合。

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到 aninner join并将其设为indexed view。您需要添加一个触发器来支持INSERTs,其方式与下面的 for 大致相同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列不再为空并引用我们正在插入的行。

可以添加更多触发器以支持更高级的使用。

于 2013-10-25T14:32:58.633 回答
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))

这意味着 everyrevisions.revisionNo是唯一的,并且该列drawings.latestRevision是引用revisionstable 主键的外键,即revisionNo.

如果您的架构有任何更改,请告诉我。

此外,外键仅在引用另一个表的主键时才被强制执行。如果revisions.revisionno不是主键或者如果主键约束在该列上被禁用,则该ALTER TABLE .. ADD FOREIGN KEY语句必然会返回错误。

于 2013-10-25T11:52:17.127 回答