sql >> Databáze >  >> RDS >> Sqlserver

Jak vytvořit omezení CHECK v SQL Server (příklady T-SQL)

V SQL Server můžete vytvořit CHECK omezení v tabulce k určení hodnot dat, které jsou přijatelné v jednom nebo více sloupcích.

Pokud tabulka obsahuje CHECK omezení a vy se pokoušíte poskytnout data, která neodpovídají CHECK omezení, operace selže s chybou.

To pomáhá udržovat integritu dat, protože to pomáhá zabránit vstupu neplatných dat do databáze.

Když vytvoříte CHECK omezení, zadáte logický výraz, který vrátí TRUE nebo FALSE . Tento logický výraz se používá ke kontrole dat.

CHECK omezení jsou podobná omezením cizího klíče, protože řídí hodnoty, které se vkládají do sloupce. Rozdíl je však v tom, jak určují, které hodnoty jsou platné:Omezení cizího klíče získávají seznam platných hodnot z jiné tabulky, zatímco CHECK omezení určují platné hodnoty z logického výrazu.

Omezení lze definovat na úrovni sloupců nebo tabulky. Omezení na úrovni sloupce platí pouze pro data v tomto sloupci. Omezení na úrovni tabulky platí pro celý řádek a kontroluje data z více sloupců.

Níže jsou uvedeny příklady vytváření CHECK na úrovni sloupců i na úrovni tabulky omezení.

Příklad 1 – Vytvoření omezení KONTROLY na úrovni sloupců

Zde je příklad vytvoření základního CHECK na úrovni sloupce omezení v době vytváření tabulky.

CREATE TABLE ConstraintTest
(
  ConstraintTestId int IDENTITY(1,1) NOT NULL PRIMARY KEY,
  Price smallmoney NOT NULL,
  CONSTRAINT chkPrice CHECK (Price > 0)
);

V tomto případě CHECK omezení určuje, že všechna data v Price musí být větší než 0. Jinými slovy, cena nemůže být nula ani záporná. Toto je omezení na úrovni sloupců, protože se vztahuje na data v jednom sloupci.

Protože se jedná o omezení na úrovni sloupce, mohl jsem ho definovat jako součást sloupce (bez čárky). Takže jsem mohl udělat toto:

CREATE TABLE ConstraintTest
(
  ConstraintTestId int IDENTITY(1,1) NOT NULL PRIMARY KEY,
  Price smallmoney NOT NULL CONSTRAINT chkPrice CHECK (Price > 0)
);

Ať tak či onak, zkusme vložit neplatnou hodnotu:

INSERT INTO ConstraintTest ( Price )
VALUES ( 0 );

Výsledek:

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'.

Příklad 2 – Přidat další sloupce a další omezení KONTROLY na úrovni sloupců

Pojďme do naší tabulky přidat další sloupce a poté přidat další CHECK na úrovni sloupce omezení.

ALTER TABLE ConstraintTest
ADD 
  TeamSize tinyint NOT NULL,
  StartDate date NOT NULL,
  EndDate date NOT NULL,
  CONSTRAINT chkTeamSize CHECK (TeamSize >= 3 AND TeamSize <= 15)
  ;

Jeden z nových sloupců zaznamenává počet členů týmu. V tomto případě platí obchodní pravidlo, že tým musí mít alespoň 3 členy, ale ne více než 15. Databáze by proto měla zabránit situaci, kdy má tým méně než 3 členy nebo více než 15.

Zkusme vložit neplatnou hodnotu:

INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate )
VALUES ( 1, 2, '2020-01-01', '1900-02-02' );

Výsledek:

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'.

Příklad 3 – Přidání omezení KONTROLY na úrovni tabulky

Nyní přidáme omezení na úrovni tabulky. Tím zkontrolujete data ve dvou sloupcích.

Mimochodem, k přidání CHECK nemusíte přidávat další sloupec omezení. Omezení můžete jednoduše přidat samo.

Příklad:

ALTER TABLE ConstraintTest
  ADD CONSTRAINT chkValidEndDate 
  CHECK (EndDate >= StartDate)
  ;

V tomto případě přidávám omezení, které zajistí, že datum ukončení nemůže být nikdy dřívější než datum zahájení. Toto je kontrola dat ve dvou sloupcích, a proto je to omezení na úrovni tabulky.

Zkuste vložit neplatnou hodnotu:

INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate )
VALUES ( 1, 3, '2020-01-01', '1900-02-02' );

Výsledek:

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".

Všimněte si, že abych otestoval toto omezení, musel jsem zvýšit počet členů týmu na 3, abych zabránil spuštění předchozího omezení jako první (CHECK omezení jsou ověřována v pořadí, v jakém jsou vytvořena).

Příklad 4 – Změňte omezení KONTROLY

Ve skutečnosti nemůžete změnit CHECK omezení. Pokud ji potřebujete změnit, budete ji muset vypustit a vytvořit ji s novou definicí.

Příklad:

ALTER TABLE ConstraintTest 
  DROP CONSTRAINT chkTeamSize;

ALTER TABLE ConstraintTest
  ADD CONSTRAINT chkTeamSize 
  CHECK (TeamSize >= 5 AND TeamSize <= 20)
  ;

Jak již bylo zmíněno, CHECK omezení jsou ověřována v pořadí, v jakém jsou vytvořena, takže to může ovlivnit, která chyba je zachycena jako první.

Pokud se tedy v tomto případě pokusím vložit neplatnou hodnotu (a také zahrnout neplatná data), neplatná data budou zachycena jako první:

INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate )
VALUES ( 1, 4, '2020-01-01', '1900-02-02' );

Výsledek:

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".

Abych tedy mohl zkontrolovat své nejnovější omezení, musím nejprve opravit problém s datem:

INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate )
VALUES ( 1, 4, '2020-01-01', '2020-02-02' );

Výsledek:

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'.

Moje nejnovější omezení tedy funguje podle očekávání.

Příklad 5 – ZKONTROLUJTE omezení a sloupce IDENTITY

Nyní, když jsme otestovali omezení, pojďme do toho a vložíme platná data:

INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate )
VALUES ( 1, 5, '2020-01-01', '2020-02-02' );

Výsledek:

+--------------------+---------+------------+-------------+------------+
| ConstraintTestId   | Price   | TeamSize   | StartDate   | EndDate    |
|--------------------+---------+------------+-------------+------------|
| 13                 | 1.0000  | 5          | 2020-01-01  | 2020-02-02 |
+--------------------+---------+------------+-------------+------------+

Nakonec získáme úspěšnou vložku.

Všimněte si však, že IDENTITY sloupec se již zvýšil na 13.

Pamatujte, že když jsem poprvé vytvořil tabulku, definoval jsem ConstraintTestId použít IDENTITY(1,1) , což znamená, že by měl začínat na 1 a automaticky se zvyšovat o 1 s každým vložením řádku.

Ale teď, když jsem konečně vložil svůj první řádek, hodnota je již 13. Je to proto, že IDENTITY sloupec se zvýší, i když CHECK omezení způsobí INSERT operace se nezdaří.

Všimněte si, že při vymýšlení příkladů pro tento článek jsem udělal několik dalších neúspěšných vložek, takže hodnota vzrostla na vyšší hodnotu, než jakou získáte, pokud budete jednoduše postupovat podle tohoto článku krok za krokem.

V každém případě udělejme poslední neúspěšné vložení a poté úspěšné, abychom to potvrdili.

Vložení se nezdařilo:

INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate )
VALUES ( 2, 4, '2020-01-02', '2020-02-03' );

Výsledek:

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'.

Úspěšné vložení:

INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate )
VALUES ( 2, 6, '2020-01-02', '2020-02-03' );

SELECT * FROM ConstraintTest;

Výsledek:

+--------------------+---------+------------+-------------+------------+
| 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 |
+--------------------+---------+------------+-------------+------------+

Vidíme, že IDENTITY sloupec skočí z 13 na 15, takže se zjevně zvýšil během neúspěšného vložení.

Některá omezení omezení CHECK

Zde je několik omezení, na která je třeba pamatovat při práci s CHECK omezení:

  • Podmínka vyhledávání se musí vyhodnotit jako booleovský výraz a nemůže odkazovat na jinou tabulku.
  • Výraz nemůže obsahovat datové typy aliasů.
  • CHECK omezení nelze definovat pro text , ntext nebo obrázek sloupce.

  1. Jak překonat náhodné smazání dat v MySQL a MariaDB

  2. Jak převést z jednoho formátu data na jiný v SQL Server pomocí CONVERT()

  3. Jak porovnat dva databázové objekty v Oracle?

  4. Jaký je nejelegantnější způsob, jak uložit časové razítko s nanosec v postgresql?