SQL 服务器:对来自两个不同表的列施加唯一性的方法

SQL Server: Ways to impose Uniqueness on columns from two different tables

示例 tables:

  • dbo.TransactionHeader (HeaderID, BillID, FileID) -- HeaderID is the PK here
  • dbo.TransactionGroup (FileID, SurityID) -- All these make a composite PK

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

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

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

Options tried: 尝试创建计算列并尝试使用函数获取基于 FileIDSurityID。但是不能在计算列上创建唯一约束,因为函数 returns 是一个非确定性值

任何help/ideas将不胜感激。

您可以使用索引视图执行此操作。示例:

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

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

步骤:

创建一个 user defined function,它将 return 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);

这应该可以实现。