In SQL Server puoi creare un CHECK
vincolo in una tabella per specificare i valori dei dati accettabili in una o più colonne.
Se una tabella ha un CHECK
vincolo su di esso e provi a fornire dati che non sono conformi a CHECK
vincolo, l'operazione avrà esito negativo con un errore.
Questo aiuta a mantenere l'integrità dei dati, perché aiuta a prevenire l'ingresso di dati non validi nel database.
Quando crei un CHECK
vincolo, fornisci un'espressione logica che restituisce TRUE
o FALSE
. Questa espressione logica è ciò che viene utilizzato per controllare i dati.
CHECK
i vincoli sono simili ai vincoli di chiave esterna perché controllano i valori inseriti in una colonna. Tuttavia, la differenza sta nel modo in cui determinano quali valori sono validi:i vincoli di chiave esterna ottengono l'elenco dei valori validi da un'altra tabella, mentre CHECK
i vincoli determinano i valori validi da un'espressione logica.
I vincoli possono essere definiti a livello di colonna o di tabella. Un vincolo a livello di colonna si applica solo ai dati in quella colonna. Un vincolo a livello di tabella si applica all'intera riga e controlla i dati da più colonne.
Di seguito sono riportati esempi di creazione di CHECK
sia a livello di colonna che a livello di tabella vincoli.
Esempio 1:creare un vincolo CHECK a livello di colonna
Ecco un esempio di creazione di un CHECK
di base a livello di colonna vincolo al momento della creazione di una tabella.
CREATE TABLE ConstraintTest ( ConstraintTestId int IDENTITY(1,1) NOT NULL PRIMARY KEY, Price smallmoney NOT NULL, CONSTRAINT chkPrice CHECK (Price > 0) );
In questo caso, il CHECK
vincolo specifica che tutti i dati nel Price
la colonna deve essere maggiore di 0. In altre parole, il prezzo non può essere zero e non può essere negativo. Questo è un vincolo a livello di colonna perché si applica ai dati in una colonna.
Poiché questo è un vincolo a livello di colonna, avrei potuto definirlo come parte della colonna (senza la virgola). Quindi avrei potuto farlo:
CREATE TABLE ConstraintTest ( ConstraintTestId int IDENTITY(1,1) NOT NULL PRIMARY KEY, Price smallmoney NOT NULL CONSTRAINT chkPrice CHECK (Price > 0) );
Ad ogni modo, proviamo a inserire un valore non valido:
INSERT INTO ConstraintTest ( Price ) VALUES ( 0 );
Risultato:
Msg 547, Level 16, State 0, Line 1 The INSERT statement conflicted with the CHECK constraint "chkPrice". The conflict occurred in database "Test", table "dbo.ConstraintTest", column 'Price'.
Esempio 2:aggiungere più colonne e un altro vincolo CHECK a livello di colonna
Aggiungiamo altre colonne alla nostra tabella e poi aggiungiamo un altro CHECK
a livello di colonna vincolo.
ALTER TABLE ConstraintTest ADD TeamSize tinyint NOT NULL, StartDate date NOT NULL, EndDate date NOT NULL, CONSTRAINT chkTeamSize CHECK (TeamSize >= 3 AND TeamSize <= 15) ;
Una delle nuove colonne registra il numero di membri del team. In questo caso, la regola aziendale è che una squadra deve avere almeno 3 membri, ma non più di 15. Pertanto il database dovrebbe prevenire la situazione in cui una squadra ha meno di 3 membri o più di 15.
Proviamo a inserire un valore non valido:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 1, 2, '2020-01-01', '1900-02-02' );
Risultato:
Msg 547, Level 16, State 0, Line 1 The INSERT statement conflicted with the CHECK constraint "chkTeamSize". The conflict occurred in database "Test", table "dbo.ConstraintTest", column 'TeamSize'.
Esempio 3:aggiungere un vincolo CHECK a livello di tabella
Ora aggiungiamo un vincolo a livello di tabella. Questo controllerà i dati in due colonne.
A proposito, non è necessario aggiungere un'altra colonna per aggiungere un CHECK
vincolo. Puoi semplicemente aggiungere il vincolo da solo.
Esempio:
ALTER TABLE ConstraintTest ADD CONSTRAINT chkValidEndDate CHECK (EndDate >= StartDate) ;
In questo caso aggiungo un vincolo per garantire che la data di fine non possa mai essere anteriore alla data di inizio. Questo sta controllando i dati su due colonne ed è quindi un vincolo a livello di tabella.
Prova a inserire un valore non valido:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 1, 3, '2020-01-01', '1900-02-02' );
Risultato:
Msg 547, Level 16, State 0, Line 1 The INSERT statement conflicted with the CHECK constraint "chkValidEndDate". The conflict occurred in database "Test", table "dbo.ConstraintTest".
Nota che per testare questo vincolo, ho dovuto aumentare i membri del team a 3 per evitare che il vincolo precedente venisse attivato per primo (CHECK
i vincoli vengono convalidati nell'ordine in cui sono stati creati).
Esempio 4 – Modificare un vincolo CHECK
Non puoi effettivamente modificare un CHECK
vincolo. Se devi modificarlo, dovrai rilasciarlo e crearlo con la nuova definizione.
Esempio:
ALTER TABLE ConstraintTest DROP CONSTRAINT chkTeamSize; ALTER TABLE ConstraintTest ADD CONSTRAINT chkTeamSize CHECK (TeamSize >= 5 AND TeamSize <= 20) ;
Come accennato, CHECK
i vincoli vengono convalidati nell'ordine in cui sono stati creati, quindi ciò può influire sull'errore rilevato per primo.
Pertanto in questo caso, se provo a inserire un valore non valido (e includo anche date non valide), le date non valide verranno catturate per prime:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 1, 4, '2020-01-01', '1900-02-02' );
Risultato:
Msg 547, Level 16, State 0, Line 1 The INSERT statement conflicted with the CHECK constraint "chkValidEndDate". The conflict occurred in database "Test", table "dbo.ConstraintTest".
Quindi, per controllare il mio ultimo vincolo, dovrò prima risolvere il problema della data:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 1, 4, '2020-01-01', '2020-02-02' );
Risultato:
Msg 547, Level 16, State 0, Line 1 The INSERT statement conflicted with the CHECK constraint "chkTeamSize". The conflict occurred in database "Test", table "dbo.ConstraintTest", column 'TeamSize'.
Quindi il mio ultimo vincolo funziona come previsto.
Esempio 5 – VERIFICA Vincoli e Colonne IDENTITÀ
Quindi, ora che abbiamo testato i vincoli, andiamo avanti e inseriamo dati validi:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 1, 5, '2020-01-01', '2020-02-02' );
Risultato:
+--------------------+---------+------------+-------------+------------+ | ConstraintTestId | Price | TeamSize | StartDate | EndDate | |--------------------+---------+------------+-------------+------------| | 13 | 1.0000 | 5 | 2020-01-01 | 2020-02-02 | +--------------------+---------+------------+-------------+------------+
Finalmente otteniamo un inserto di successo.
Tuttavia, noterai che IDENTITY
la colonna è già aumentata a 13.
Ricorda quando ho creato la tabella per la prima volta ho definito il ConstraintTestId
colonna per utilizzare IDENTITY(1,1)
, il che significa che dovrebbe iniziare da 1 e aumentare automaticamente di 1 ad ogni inserimento di riga.
Ma ora che ho finalmente inserito la mia prima riga, il valore è già 13. Questo perché IDENTITY
la colonna viene incrementata anche quando un CHECK
vincolo provoca il INSERT
operazione fallita.
Nota che ho fatto alcuni inserimenti extra non riusciti durante la creazione degli esempi per questo articolo, quindi il valore è aumentato a un valore superiore a quello che otterrai se segui semplicemente passo dopo passo questo articolo.
In ogni caso, facciamo un ultimo inserimento fallito, e poi uno riuscito per confermarlo.
Inserimento fallito:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 2, 4, '2020-01-02', '2020-02-03' );
Risultato:
Msg 547, Level 16, State 0, Line 1 The INSERT statement conflicted with the CHECK constraint "chkTeamSize". The conflict occurred in database "Test", table "dbo.ConstraintTest", column 'TeamSize'.
Inserimento riuscito:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 2, 6, '2020-01-02', '2020-02-03' ); SELECT * FROM ConstraintTest;
Risultato:
+--------------------+---------+------------+-------------+------------+ | ConstraintTestId | Price | TeamSize | StartDate | EndDate | |--------------------+---------+------------+-------------+------------| | 13 | 1.0000 | 5 | 2020-01-01 | 2020-02-02 | | 15 | 2.0000 | 6 | 2020-01-02 | 2020-02-03 | +--------------------+---------+------------+-------------+------------+
Possiamo vedere che il IDENTITY
la colonna passa da 13 a 15, quindi ovviamente è aumentata durante l'inserimento non riuscito.
Alcune restrizioni dei vincoli CHECK
Ecco alcune restrizioni a cui prestare attenzione quando si lavora con CHECK
vincoli:
- La condizione di ricerca deve restituire un'espressione booleana e non può fare riferimento a un'altra tabella.
- L'espressione non può contenere tipi di dati alias.
CHECK
i vincoli non possono essere definiti su testo , ntesto o immagine colonne.