2010-07-08 69 views
0

如果我有两个表,说:SQL服务器/ TSQL更新表具有唯一约束

Clients 
(
    ClientID int primary key, 
    ClientName varchar(50) not null 
) 

Addresses 
(
    AddressID int primary key, 
    AddressLine1 varchar(50), 
    etc.. 
    ClientID int not null, 
    IsPrimaryAddress bit not null 
) 

跨越(ClientID, IsPrimaryAddress)唯一约束,怎么能达到最新的表从代码集合(而不是一个单一的SQL语句)没有违反约束?

谢谢...

+3

你的收藏是什么样的?你如何将其转移到SQL?这种限制的一个问题是,每个客户端只能有2个地址(一个主要的,一个不是)。 – Oded 2010-07-08 08:22:12

+0

只是不要试图插入任何违反约束条件的东西?!?!?我真的不明白你的问题,恐怕......你需要在这些表上更新什么? – 2010-07-08 10:50:02

回答

2

这可能是一个错误都有一个唯一的约束跨(客户端ID,IsPrimaryAddress),除非你想确保客户可以有不超过两个地址(一个主,一个等) ,因为任何时候您尝试添加更多非主地址都会违反完整性约束。

1

正如其他人已经提到的,这里的问题似乎源于过度限制性的独特约束。据推测,当你有一个客户端的两个地址并且想要交换主要的地址时,这会导致你很困难。在这种情况下,首先将主地址更新为非主地址,并立即失败,因为同一客户端的两个非主地址违反了约束。

因此,该问题将通过仅在地址为主时在ClientID上强制实施唯一约束来解决。这样的conditional unique constraints之前已经讨论过堆栈溢出。

如果你使用的是Oracle,那么你可以聪明,做这样的事情:

CREATE UNIQUE INDEX unique_primary_addr ON Addresses (
    DECODE (IsPrimaryAddress, 1, ClientId, NULL)); 

但是,我假设你使用的是SQL服务器或别的东西,所以你将被迫做这样的事情:

CREATE FUNCTION PrimaryAddressCount(@Id INT) RETURNS INT AS 
BEGIN 
    DECLARE @ret INT; 
    SELECT @ret = COUNT(*) FROM Addresses WHERE ClientId = @Id AND IsPrimaryAddress = 1; 
    RETURN @ret; 
END; 
GO 

ALTER TABLE Addresses 
    ADD CONSTRAINT SinglePrimaryConstraint 
CHECK (IsPrimaryAddress != 1 OR dbo.PrimaryAddressCount(ClientId) = 1); 

无论哪种方式,所产生的约束将让尽可能多的非主地址,你需要为每个客户端,但将执行一个主地址。这应该使您能够轻松地更新地址,只要您始终最后写入新的主地址即可。