【问题标题】:SQL Server: Ways to impose Uniqueness on columns from two different tablesSQL Server:对来自两个不同表的列施加唯一性的方法
【发布时间】:2018-10-04 20:29:04
【问题描述】:

示例表:

  • dbo.TransactionHeader(HeaderID, BillID, FileID) -- HeaderID是这里的PK
  • dbo.TransactionGroup (FileID, SurityID) -- 所有这些组成一个复合 PK

我想对表 dbo.TransactionHeader 中的 BillID 和另一个表 dbo.TransactionGroup 中的另一列 (SurityID) 施加唯一性。 SurityIDdbo.TransactionHeader 表中不可用。

我想在 dbo.TransactionHeader 表上添加唯一性,以不插入任何具有 (BillID, SurityID) 组合的重复项。

我不能在dbo.TransactionHeader 中添加一个新的物理列(比如SurityID),因为它是一个包含大量数据的旧数据库,这将是一个很大的变化。

Options tried: 尝试创建计算列并尝试使用函数来获取基于FileIDSurityID。但无法在计算列上创建唯一约束,因为函数返回一个不确定的值

任何帮助/想法将不胜感激。

【问题讨论】:

  • 您能否发布您编写的查询,以便我们更好地了解您正在寻找的结果集?如果您声称无法添加新列,这是否意味着您正在寻求 JOIN 查询或其他方面的帮助?
  • 你不能用声明性约束来做到这一点——那些不能跨越表。您可能要做的就是在dbo.TransactionHeader 上编写一个INSERT 触发器,以检查这种有问题的组合是否已经存在——如果存在,则拒绝插入操作
  • @PausePause:这与数据检索无关。我试图在现有系统上施加唯一性,同时将数据插入到具有一些设计考虑的表 dbo.TransactionHeader 中,这样它就不会影响/消除更改将数据插入到该表中的其他进程的需要。跨度>
  • @marc_s:触发器起作用了。谢谢。

标签: sql-server database-design unique-constraint


【解决方案1】:

您可以使用索引视图来做到这一点。示例:

CREATE VIEW dbo.v1 WITH SCHEMABINDING AS
SELECT H.HeaderID, H.BillID, H.FileId, G.SurityID
FROM dbo.TransactionHeader H
JOIN dbo.TransactionGroup G
ON H.FileID = G.FileID;
GO

CREATE UNIQUE CLUSTERED INDEX v1idx ON dbo.v1 (BillID, SurityID) ;

【讨论】:

    【解决方案2】:

    经过更多研究,发现我们也可以使用CHECK约束来实现这一点。

    步骤:

    创建一个user defined function,在检查是否存在重复后,将返回01,如下所示:

    CREATE FUNCTION [dbo].[udf_TransactionHeader_Bill_ID_Surity_ID](@File_ID INT,@Bill_ID VARCHAR(10))
    RETURNS BIT
    AS
    BEGIN
    
        IF(SELECT COUNT(*) FROM [dbo].[TransactionHeader] AS th
                WHERE th.Bill_ID = @Bill_ID) > 0
                BEGIN            
                DECLARE @Surity_ID SMALLINT = (SELECT Surity_ID FROM [dbo].[TransactionGroup] WHERE File_ID = @File_ID)
    
                IF (SELECT COUNT(*)
                    FROM [dbo].[TransactionHeader] AS th 
                    INNER JOIN [dbo].[TransactionGroup] AS tg ON tg.File_ID = th.File_ID 
                    WHERE th.Bill_ID = @Bill_ID
                    AND  tg.Surity_ID = @Surity_ID) > 1
                    BEGIN
                        RETURN 1
                    END
              END
    RETURN 0
    END
    GO
    

    现在在dbo.TransactionHeader(Bill_ID) 上添加CHECK 约束

    列并将上述函数嵌入到CHECK约束表达式中,如下所示:

    ALTER TABLE [dbo].[TransactionHeader]  WITH NOCHECK
    ADD CONSTRAINT CK_TransactionHeader_Bill_ID 
    CHECK (dbo.udf_TransactionHeader_Bill_ID_Surity_ID(SurityID,Bill_ID) = 0);
    

    这应该可以实现。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-11
      • 2015-03-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多