2010-10-22 10 views
5

Ho una tabella, similevincolo UNIQUE controllato da una colonna di bit

FieldsOnForms(
FieldID int (FK_Fields) 
FormID int (FK_Forms) 
isDeleted bit 
) 

La coppia (FieldID, FormID) dovrebbe essere unico, ma solo se la riga non viene eliminata (isDeleted = 0).

È possibile definire un tale vincolo in SQLServer 2008? (senza utilizzare i trigger)

P.S. L'impostazione (FieldID, FormID, isDeleted) per essere univoci aggiunge la possibilità di contrassegnare una riga come eliminata, ma mi piacerebbe avere la possibilità di impostare n righe (per FieldID, FormID) a isDeleted = 1, e di avere solo una con isDeleted = 0

risposta

12

si può avere un unico indice di, utilizzando 2.008 filtered indexes funzionalità di SQL Server, oppure è possibile applicare un indice univoco su una vista (indice filtrato poveri, lavora contro le versioni precedenti), ma non si può avere un vincolo UNICO come quello che hai descritto.

Un esempio di indice filtrato:

CREATE UNIQUE NONCLUSTERED INDEX IX_FieldsOnForms_NonDeletedUnique ON FieldsOnForms (FieldID,FormID) WHERE isDeleted=0 
+0

+1 risposta migliore ... – gbn

+0

Anche se ho qualche errore, a causa del campo di bit (la conversione di una colonna nel tipo di dati di una costante non è supportata per gli indici filtrati), questo sembra essere il soluzione che stavo cercando. – jaraics

+0

@jaraics - Ho appena creato la tabella nella tua domanda, e poi l'indice nella mia risposta, ed è stata creata senza errori. Inoltre, se si verificano disallineamenti di tipo di dati, in genere è preferibile CAST (o CONVERT) la costante al tipo di colonna, piuttosto che il contrario. Non sono sicuro se ciò risolverà il tuo problema. –

1

No, unico mezzo veramente unico nel suo genere. Dovrai spostare i tuoi record eliminati su un'altra tabella o modificare IsDeleted in qualcosa che può essere univoco in tutti i record cancellati (ad esempio un timestamp). Entrambe le soluzioni richiederanno un lavoro aggiuntivo nell'applicazione, in una stored procedure o in un trigger.

2

È possibile modificare la colonna IsDeleted in DeletedDate e impostarla a DATETIME con l'ora esatta in cui la riga è stata cancellata logicamente. In alternativa, è possibile aggiungere una colonna DeletedDate e quindi creare una colonna calcolata su IsDeleted rispetto a quella in modo da avere ancora quella colonna disponibile se viene utilizzata nel codice. Ovviamente, inserire un indice univoco su DeletedDate (oltre a FieldID e FormId) anziché alla colonna IsDeleted. Ciò consentirebbe esattamente una colonna NULL.

Albin ha pubblicato una soluzione simile a questa, ma poi l'ha cancellata. Non sono sicuro del perché, ma se lo reinserisce, il suo era qui prima del mio. :)

+0

Questo sembra essere un buon alternaive per i precedenti server SQL. – jaraics

Problemi correlati