Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Come creare un vincolo CHECK in SQL Server (esempi T-SQL)

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.