样本表:
- 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
。但是由于该函数返回不确定的值,因此无法在计算列上创建唯一约束
任何帮助/想法都将不胜感激。
答案 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
,在检查是否存在重复项之后,将返回0
或1
:
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
现在在CHECK
(dbo.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);
这应该可以实现。