【问题标题】:MS SQL Server cross table constraintMS SQL Server 跨表约束
【发布时间】:2013-05-01 15:45:25
【问题描述】:

我有三张桌子:

1) 应用程序(AppId、名称)
2) 屏幕(ScreenId、名称)
3)关系(AppId,ScreenId)

现在我想对相关表应用一些限制: 同一个屏幕可以分配给多个应用程序,但不能有两个同名的屏幕分配给同一个应用程序。

我知道我可以将 Screen.Name 添加到关系表中,然后在 AppId 和 Screen.Name 上创建 PK,但我不想要这样的解决方案,因为 Screen.Name 可能会发生变化。

我必须有哪些额外的选项来实现这种限制?

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案1】:

    您可以基于Relation 和Screen 表创建indexed view,并在其中应用唯一约束。

    create view DRI_UniqueScreens
    with SCHEMABINDING
    as
        select r.AppId,s.Name
        from
           [Schema].Relation r
             inner join
           [Schema].Screen s
             on
                r.ScreenId = s.ScreenId
    GO
    CREATE UNIQUE CLUSTERED INDEX IX_DRI_UniqueScreens
        on DRI_UniqueScreens (AppId,Name)
    

    【讨论】:

    • 我想知道是否有这样的事情。 :) 比触发器好得多。 :)
    • 这个方法是否会在更改屏幕名称时“验证”数据,还是只会在访问视图时检查数据?
    • @AlexDn - 是的,这将在基础表中进行更改时强制执行约束。如果您转到我链接到的页面,您会注意到索引视图有很多限制。大多数这些限制存在因为它们允许以有效的方式对基表中的每个事务进行所需的维护活动。
    • @AlexDn - 另外,您可能已经注意到我将视图命名为 DRI_x。这是(我自己的)约定,表明此视图是出于声明性引用完整性的原因而存在的,并且(可能)不打算让任何人实际从中查询。如果您处于进行审计的环境中,这会有所帮助 - “这种观点的意义何在?没有任何查询。也许我们应该删除它?”
    • 我喜欢索引视图,但感觉就像我只有大约 20% 的时间想要使用它们才能满足所有许多限制;剩下的 80% 我不得不求助于触发器......
    【解决方案2】:

    这不是一个很好的解决方案,但您可以将触发器添加到屏幕和关系表中,以检查您修改的内容是否符合您的条件,如果不符合则回滚。

    CREATE TRIGGER trgScreen ON Screen FOR INSERT, UPDATE
    AS
    BEGIN
        IF EXISTS (SELECT r.AppID, s.Name FROM Screen s
                   INNER JOIN Relation r ON s.ScreenID = r.ScreenID
                   GROUP BY r.AppID, s.Name
                   HAVING count(*) > 1)
            ROLLBACK TRANSACTION
    END
    
    CREATE TRIGGER trgRelation ON Relation FOR INSERT, UPDATE
    AS
    BEGIN
        IF EXISTS (SELECT r.AppID, s.Name FROM Screen s
                   INNER JOIN Relation r ON s.ScreenID = r.ScreenID
                   GROUP BY r.AppID, s.Name
                   HAVING count(*) > 1)
            ROLLBACK TRANSACTION
    END
    

    【讨论】:

    • 是的,触发器会起作用,但我会尽量避免触发器。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-17
    • 2011-04-19
    • 1970-01-01
    • 2012-05-07
    相关资源
    最近更新 更多