根据另一个表中的数据约束数据库表条目

时间:2019-04-21 13:22:02

标签: sql-server database

我有两个相关的数据库表:

CREATE TABLE [dbo].[TopicKeyword] 
(
    [Id]      SMALLINT     NOT NULL,
    [Keyword] VARCHAR(100) NOT NULL,
    [Volume]  INT          NOT NULL,
    [PageId]  SMALLINT     NOT NULL,

    CONSTRAINT [PK_TopicKeyword] PRIMARY KEY CLUSTERED ([Id] ASC)
);


CREATE TABLE [dbo].[TopicCluster] 
(
    [KeywordId] SMALLINT NOT NULL,

    CONSTRAINT [PK_TopicCluster] PRIMARY KEY CLUSTERED ([KeywordId] ASC),

    CONSTRAINT [FK_TopicCluster_TopicKeyword] 
        FOREIGN KEY ([KeywordId]) REFERENCES [dbo].[TopicKeyword] ([Id])
);

如您所见,使用TopicCluster的{​​{1}}引用TopicKeyword

但是,我需要确保KeywordId表的完整性。

TopicCluster表中的PageID可以重复多次,但是TopicKeyword表中每个PageId只能有一个关键字。

例如:

主题关键字

Id,PageId

  • 1、5
  • 2、6
  • 3,5 // 5重复

TopicCluster

KeywordId

  • 1
  • 2
  • 3 //不应该被允许,因为1已经引用了PageId:5

我已经创建了一个解决方案,但是我不是SQL专家,所以我不确定在这种情况下这是否是正确的方法。再次是这些表格,这些表格经过了重新设计以包括新的约束:

TopicCluster

任何建议表示赞赏。

2 个答案:

答案 0 :(得分:0)

我清除了您的脚本:

CREATE TABLE TopicKeyword 
(
    Id      smallint     NOT NULL,
    Keyword varchar(100) NOT NULL,
    Volume  int          NOT NULL,
    PageId  smallint     NOT NULL,
    CONSTRAINT PK_TopicKeyword PRIMARY KEY (Id),
    CONSTRAINT UK_TopicKeyword UNIQUE (Id, PageId) -- to create FOREIGN KEY in TopicCluster
)
GO

CREATE TABLE TopicCluster 
(
    KeywordId smallint NOT NULL,
    PageId    smallint NOT NULL,

    CONSTRAINT PK_TopicCluster PRIMARY KEY (KeywordId), -- to exclude duplicates in KeywordId
    CONSTRAINT UK_TopicCluster_PageId UNIQUE (PageId),  -- to exclude duplicates in PageId

    CONSTRAINT FK_TopicCluster_TopicKeyword
          FOREIGN KEY (KeywordId, PageId)
          REFERENCES TopicKeyword (Id, PageId) -- to prevent pairs of KeywordId&PageId which not in TopicKeyword
)
GO

答案 1 :(得分:0)

您的DDL非常适合您的用例。

如果我有不好的说法,那就是应该仅在TopicKeyword表中出现PageId列(数据重复),您可以在需要时使用SQL JOIN语句获取PageId。

如果我猜对了,您的TopicKeyword表应该每行存储一个(关键字和页面)唯一组合,为此,我将执行以下操作:

CREATE TABLE [dbo].[TopicKeyword] 
(
    [Id]      SMALLINT     NOT NULL,
    [Keyword] VARCHAR(100) NOT NULL,
    [Volume]  INT          NOT NULL,
    [PageId]  SMALLINT     NOT NULL,
    CONSTRAINT [PK_TopicKeyword] PRIMARY KEY CLUSTERED ([Id] ASC),
    CONSTRAINT [UQ_TopicKeyword] UNIQUE NONCLUSTERED ([Keyword] ASC, [PageId] ASC)
);
GO

将使用PK作为参考,并且唯一性约束将确保每行(关键字和页面)的唯一组合。

对于第二部分,您要在群集表中存储仅与一个页面相关联的关键字,为此,我将执行以下操作:

CREATE FUNCTION FN_IsPageIdUnique
(
    @KeywordId SMALLINT
)
RETURNS BIT
AS 
BEGIN
    DECLARE @IsPageIdUnique BIT
    DECLARE @PageIdCount INT

    SELECT @PageIdCount = COUNT(k2.[PageId])
    FROM [TopicKeyword] k1
    INNER join [TopicKeyword] k2 ON k2.[PageId] = k1.[PageId]
    WHERE k1.[Id] = @KeywordId

    IF (@PageIdCount = 1)
        SET @IsPageIdUnique = 1
    ELSE
        SET @IsPageIdUnique = 0

    RETURN @IsPageIdUnique
END
GO


CREATE TABLE [dbo].[TopicCluster] 
(
    [KeywordId] SMALLINT NOT NULL,
    CONSTRAINT [PK_TopicCluster] PRIMARY KEY CLUSTERED ([KeywordId] ASC),
    CONSTRAINT [FK_TopicCluster_TopicKeyword] FOREIGN KEY ([KeywordId]) REFERENCES [dbo].[TopicKeyword] ([Id]),
    CONSTRAINT CK_TopicCluster CHECK (dbo.FN_IsPageIdUnique(KeywordId))
);
GO

检查约束将帮助您基于将使用标量函数FN_IsPageIdUnique计算的另一个表数据来增强群集数据的唯一性。