2010-07-08 2 views
0

Si j'ai deux tables, dites:SQL Server/TSQL Mise à jour d'une table avec une contrainte unique

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

et

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

avec une contrainte unique sur (ClientID, IsPrimaryAddress), comment pouvez-vous ce jour ces tables à partir d'une collection dans le code (pas une seule instruction SQL) sans violer la contrainte?

Merci ...

+3

À quoi ressemble votre collection? Comment allez-vous le transférer à SQL? Un problème avec cette contrainte est que vous ne pourrez avoir que 2 adresses par client (une primaire, une non). – Oded

+0

N'essayez simplement pas d'insérer quoi que ce soit qui viole la contrainte?!?!? Je ne comprends pas vraiment votre question, j'ai peur ... qu'est-ce que vous avez besoin de mettre à jour sur ces tables? –

Répondre

2

Il est probablement une erreur d'avoir une contrainte unique à travers (ClientID, IsPrimaryAddress), à moins que vous voulez vous assurer qu'un client ne peut pas avoir plus de deux adresses (une primaire, un autre) À chaque fois que vous essayez d'ajouter d'autres adresses non principales, vous violez la contrainte d'intégrité.

1

Comme d'autres l'ont déjà mentionné, le problème semble ici provenir d'une contrainte unique trop restrictive. Vraisemblablement, cela vous cause des difficultés lorsque vous avez deux adresses pour un client et que vous voulez échanger sur lequel est le primaire. Dans ce cas, vous devez d'abord mettre à jour l'adresse principale pour qu'elle ne soit pas principale et échouer immédiatement car deux adresses non principales pour le même client violent la contrainte. Le problème, par conséquent, serait résolu en appliquant uniquement la contrainte unique sur ClientID lorsque l'adresse est primaire. Tels conditional unique constraints ont été discutés sur débordement de pile avant.

Si vous utilisez Oracle, alors vous pouvez être intelligent et faire quelque chose comme ceci:

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

Mais je suppose que vous utilisez sql-server ou autre chose, vous serez forcé de faire quelque chose comme ceci:

façon
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); 

Soit, la contrainte résultant permettra autant d'adresses non primaires que vous le souhaitez pour chaque client, mais appliquera une seule adresse principale. Cela devrait vous permettre de mettre facilement à jour les adresses, à condition de toujours écrire la nouvelle adresse principale en dernier.

Questions connexes