2013-10-29 5 views
5

Ho una tabella che descrive una relazione multi-to-one, diciamo tra immagini e album. Voglio essere in grado di selezionare una sola foto per album come copertina. In questo momento, la tabella è così:Come applicare "unicità" alla colonna booleana (un po 'come i pulsanti di opzione)?

AlbumID int primary key, 
PictureID int, 
IsCover bool 

Supponendo che io non voglio cambiare lo schema globale (una soluzione potrebbe essere quella di spostare il "è cover di" relazione a un altro tavolo, la definizione di un one to-one, ma è preferibile non modificare le query già implementate aggiungendo un'altra tabella), esiste un modo per far rispettare tutte le voci con lo stesso ID album BUT ONE che IsCover è impostato su false?

Sto cercando soluzioni lato server. Sto lavorando con Microsoft SQL Server 2012. Il vincolo UNIQUE non può essere applicato qui, altrimenti potrei avere solo una copertina e una non copertina per ogni album. Ho già implementato un controllo nella mia applicazione, ma mi piacerebbe davvero avere un ulteriore livello di sicurezza.

Grazie in anticipo.

+2

Cosa succede ad usare un trigger dopo l'aggiornamento/dopo inserto che controlla se la nuova voce dovrebbe essere l'elemento di copertura e poi segna tutti gli altri voci pertinenti come false? –

+1

Utilizzando il vincolo CHECK puoi applicare le regole che desideri sul tavolo. Creare una funzione che esegue il controllo effettivo e utilizzarla in un vincolo. –

+0

Grazie a tutti e due! Tuttavia, sto cercando di scoprire se c'è qualcosa di simile al vincolo univoco, per mantenere le cose il più semplice possibile. – Simone

risposta

4

probabilmente unico indice filtrato è la cosa che può aiutare:

create table AlbumPics (
    AlbumID int not NULL, 
    PictureID int not NULL, 
    IsCover bit not NULL, 
    primary key clustered (AlbumID, PictureID) 
) 

create unique index UX_AlbumPics_CoverPic 
    on AlbumPics (AlbumID) where IsCover = 1 

-- insert 3 pics for album 1, one of them is cover pic 
insert into AlbumPics values 
(1, 1, 0), (1, 2, 1), (1, 3, 0) 

-- try to insert one more cover for album 1 - will fail 
insert into AlbumPics values 
(1, 4, 1) 
+1

+1, ma ricorda che gli "indici filtrati" sono SQL Server 2008 e successivi. http://technet.microsoft.com/en-us/library/cc280372.aspx –

+0

Grazie a i-one, questa è esattamente la soluzione che stavo cercando! Ancora una cosa: come posso assicurarmi che ci sia sempre una cover per un album? Il codice qui sopra si accerta che ce ne sia solo uno, ma non ce ne può essere nessuno. – Simone

+1

@Simone, a parte l'aggiunta della colonna 'CoverPictureID int not NULL' al tavolo' Albums', non sono sicuro che ci sia un modo affidabile per far sì che ogni album abbia una copertura. Se non riesci a modificare lo schema del tavolo 'Albums', penso, proverei piuttosto a garantirlo sul recupero dei dati, come selezionare l'immagine speciale" Nessuna copertina ", quando non c'è copertura per un album, o semplicemente omettendo tale" album di dati sporchi ". –