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

时间:2018-10-04 20:29:05

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

样本表:

  
      
  • dbo.TransactionHeader(HeaderID,BillID,FileID)-HeaderID是此处的PK
  •   
  • dbo.TransactionGroup(文件ID,SurityID)-所有这些都构成一个复合PK
  •   

我想在表BillID的{​​{1}}和另一个表dbo.TransactionHeader的另一列(SurityID)上施加唯一性。 dbo.TransactionGroup在表SurityID中不可用。

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

我无法在BillID, SurityID中添加新的物理列(例如SurityID)作为其具有大量数据的旧数据库,这将是一个很大的改变。

dbo.TransactionHeader 尝试创建计算列,并尝试使用函数基于Options tried:获取SurityID。但是由于该函数返回不确定的值,因此无法在计算列上创建唯一约束

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

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:0)

经过更多研究,发现我们还可以使用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

现在在CHECKdbo.TransactionHeader)上添加Bill_ID约束

将上述函数列并嵌入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);

这应该可以实现。