2011-01-26 8 views
18

Ho una colonna bit IsDefault. Solo una riga di dati all'interno della tabella può avere questa colonna di bit impostata su 1, tutti gli altri devono essere 0.Vincolo colonna bit di SQL Server, 1 riga = 1, tutti gli altri 0

Come posso far rispettare questo?

+6

Avete considerato un'architettura alternativa? Dì, avendo un riferimento da qualche altra parte che punta alla riga "predefinita". –

+1

quale versione di SQL Server si prega di? – gbn

+0

Che bella domanda! Sto solo scrivendo questo per esprimere i miei altri +99 punti di apprezzamento. –

risposta

30

Tutte le versioni:

  • trigger
  • vista indicizzata
  • proc memorizzato (per esempio test di scrittura)

SQL Server 2008: a filtered index

CREATE UNIQUE INDEX IX_foo ON bar (MyBitCol) WHERE MyBitCol = 1 
+0

Beh, questo sicuramente impedirebbe loro di salvare più record con un valore predefinito. – NotMe

+1

Gli indici filtrati richiedono ANSI IMBOTTITURA ON. Quindi eseguire 'SET ANSI PADDING ON 'prima di creare un indice filtrato. – naXa

1

Si potrebbe applica un Invece di Inserisci trigger e verifica il valore come sta arrivando.

Create Trigger TRG_MyTrigger 
on MyTable 
Instead of Insert 
as 
Begin 

    --Check to see if the row is marked as active.... 
    If Exists(Select * from inserted where IsDefault= 1) 
    Begin 
    Update Table Set IsDefault=0 where ID= (select ID from inserted); 

    insert into Table(Columns) 
    select Columns from inserted 
    End 

End 

In alternativa è possibile applicare un vincolo univoco sulla colonna.

16

Assumendo che il PK è un singolo, colonna numerica, si potrebbe aggiungere una colonna calcolata al vostro tavolo:

ALTER TABLE YourTable 
    ADD IsDefaultCheck AS CASE IsDefault 
    WHEN 1 THEN -1 
    WHEN 0 THEN YourPK 
    END 

quindi creare un indice univoco nella colonna calcolata.

CREATE UNIQUE INDEX IX_DefaultCheck ON YourTable(IsDefaultCheck) 
+0

+1 mai pensato a questo. Una soluzione DRI senza indice filtrato – gbn

+0

+ 1 soluzione piacevole. –

+0

Questa è la soluzione migliore, secondo me, dal momento che non comporta alcun trigger. In effetti, tutto ciò che viene fornito in questa soluzione può probabilmente essere implementato in linea nella definizione della tabella originale. – Tripartio

2

penso che il grilletto è l'idea migliore se si vuole cambiare il vecchio record di default a 0 quando si inserisce/aggiorna uno nuovo e se si vuole fare in modo un record è sempre tale valore (cioè se si cancella il record con il valore che si assegnerebbe a un record diverso). Dovresti decidere le regole per farlo. Questi trigger possono essere complicati perché devi tenere conto di più record nelle tabelle inserite e cancellate. Quindi se 3 record in un batch cercano di aggiornare per diventare il record predefinito, quale uno vince?

Se si desidera assicurarsi che il record predefinito non cambi mai quando qualcun altro tenta di cambiarlo, l'indice filtrato è una buona idea.

1

La risposta accettata alla domanda qui sotto è sia interessante e pertinente: "Ma la gente relazionali gravi vi dirà queste informazioni dovrebbe essere solo in un altro tavolo"

Constraint for only one record marked as default

Avere una tabella di 1 riga separata che indica quale record è "predefinito". Anon ha toccato questo nel suo commento.

Penso che questo sia l'approccio migliore: semplice, pulito & non richiede una soluzione esoterica "intelligente" soggetta a errori o successive incomprensioni. È anche possibile rilasciare la colonna IsDefualt.

Problemi correlati