我有一张名为" Accounts
" composite primary key
包含2列:Account_key
和Account_Start_date
,数据类型为int
,另一个非关键列为Accountnumber(bigint).
Account_key应该有一个或多个Accountnumber(bigint)
而不是相反意味着 1或许多帐号只能有1个Account_key 。
如果您尝试插入相同的Account_key和相同的Account_Start_date,那么primary key constraint
当然会停止这一点,因为它们是主键。
但是,如果您插入现有的Account_key与不同的现有Account_Start_date,那么您可以根据需要插入随机的Accountnumber,而不会抱怨任何约束,突然您在Account_key和Accountnumber之间有多对多的关系,我们不想那样。
我试过很多约束而没有任何运气。我只是不知道我在这里做错了所以请继续帮我解决这个问题,谢谢! (注意:我不认为更改复合主键是一个选项,因为我们将松开缓慢变化的维度日期功能)
还有另一个表(案例),其中1' Account_Key'只能与1' AccountNumber'相关联意思是1..1关系,除了它们之间应该有1..1之间的关系外,其他所有事情都是相同的。
独特的索引至少对我不起作用,只要考虑我是否想要更改Accounts
表或者设置一个触发器甚至是一个索引,这样它就会成为' Account_Key'之间的1..1关系。和' AccountNumber',?
答案 0 :(得分:1)
如果这是OLTP表,解决方案是将数据正确地规范化为两个表,但这是一个DW表,因此将它全部放在一个表中是有意义的。
在这种情况下,您应该添加FOR
/ AFTER
触发器ON INSERT, UPDATE
,对inserted
伪表进行查询。查询可以是一个简单的COUNT(DISTINCT Account_Key)
,加入主表(仅过滤添加/更新的AccountNumber
值),在GROUP BY
上执行AccountNumber
和然后HAVING COUNT(DISTINCT Account_Key) > 1
。在IF EXISTS
中包装该查询,如果返回一行,则执行ROLLBACK
取消DML操作,RAISERROR
发送有关操作被取消的原因的错误消息,然后是RETURN
。
CREATE TRIGGER dbo.TR_TableName_PreventDuplicateAccountNumbers
ON dbo.TableName
AFTER INSERT, UPDATE
AS
SET NOCOUNT ON;
IF (EXISTS(
SELECT COUNT(DISTINCT tab.Account_Key)
FROM dbo.TableName tab
INNER JOIN INSERTED ins
ON ins.AccountNumber = tab.AccountNumber
GROUP BY tab.AccountNumber
HAVING COUNT(DISTINCT tab.Account_Key) > 1
))
BEGIN
ROLLBACK;
RAISERROR(N'AccountNumber cannot be associated with more than 1 Account_Key', 16, 1);
RETURN;
END;
对于"其他" Account_Key
和AccountNumber
之间的关系为1:1的表,您可以尝试执行以下操作:
DECLARE @Found BIT = 0;
;WITH cte AS
(
SELECT DISTINCT tab.Account_Key, tab.AccountNumber
FROM dbo.TableName tab
INNER JOIN INSERTED ins
ON ins.Account_Key = tab.Account_Key
OR ins.AccountNumber = tab.AccountNumber
), counts AS
(
SELECT c.[Account_Key],
c.[AccountNumber],
ROW_NUMBER() OVER (PARTITION BY c.[Account_Key
ORDER BY c.[Account_Key, c.[AccountNumber]) AS [KeyCount],
ROW_NUMBER() OVER (PARTITION BY c.[AccountNumber]
ORDER BY c.[AccountNumber], c.[Account_Key) AS [NumberCount]
FROM cte c
)
SELECT @Found = 1
FROM counts
WHERE [KeyCount] > 1
OR [NumberCount] > 1;
IF (@Found = 1)
BEGIN
ROLLBACK;
RAISERROR(N'AccountNumber cannot be associated with more than 1 Account_Key', 16, 1);
RETURN;
END;
答案 1 :(得分:0)
如果我理解正确,你想要:
如果这是正确的,您可以使用调用UDF的CHECK CONSTRAINT
来实现此目的。
编辑:
CHECK CONSTRAINT的伪逻辑可以是:
IF EXISTS anotherRow
WHERE theOtherAccountNumber = thisAccountNumber
AND theOtherAccountKey <> thisAccountKey
THEN False (do not allow this row to be inserted)
ELSE True (allow the insertion)
我会将此逻辑放在一个返回true或false的UDF中,以使CHECK约束更简单。
答案 2 :(得分:0)
使用Account_Key和Account_Number列创建一个额外的表AccountKeyNumbers(名称是您选择的当然)。
将Account_Number设为主键。
请注意,您无法两次添加Account_Number,因此无法将其链接到此表中的两个不同的Account_Keys。
现在,您在Account_Number和Account_Key上添加了一个额外的唯一约束。在此表中,您可以输入所有帐号及其对应的密钥。
最后,在Accounts表上,在Account_Key和Account_Number列上定义一个外键,引用AccountKeyNumbers表中的唯一约束。
您现在已确保只能将有效的键/数字组合插入到帐户中,并且没有两个帐户键可以具有相同的编号。我们需要额外的唯一约束,它不会影响AccountKeyNumbers表的数据完整性,只是为了创建一个外键,它必须指向主键或唯一约束。