Constraints

Constraints är säkerhetsbältena i databasen – de hindrar felaktig data från att ens komma in. När du lär dig använda dem rätt slipper du skriva massor av extra kod för att sanera data i efterhand.

TL;DR

  • PRIMARY KEY och FOREIGN KEY håller ordning på identitet och relationer.
  • NOT NULL, UNIQUE, CHECK och DEFAULT ser till att kolumner beter sig som du tänkt.
  • Kombinera constraints med index och transaktioner för robusta system.

Översikt

ConstraintVad den görTypiskt exempel
PRIMARY KEYUnikt, icke-null, identifierar en radId INTEGER PRIMARY KEY
FOREIGN KEYPeker på primärnyckel i annan tabellAuthorId REFERENCES Authors(AuthorId)
NOT NULLTvingar fram värdeName TEXT NOT NULL
UNIQUETillåter värde bara en gångEmail TEXT UNIQUE
CHECKEget villkor per radCHECK (Stock >= 0)
DEFAULTFörifyllt värde när INSERT saknar kolumnCreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP

Exempel: komplett tabell

CREATE TABLE Orders (
    OrderId      INTEGER PRIMARY KEY,
    CustomerId   INTEGER NOT NULL,
    OrderDate    DATE    NOT NULL DEFAULT CURRENT_DATE,
    TotalAmount  DECIMAL(12,2) CHECK (TotalAmount >= 0),
    Status       TEXT    NOT NULL CHECK (Status IN ('Draft','Sent','Paid','Cancelled')),
    UNIQUE (CustomerId, OrderDate),
    FOREIGN KEY (CustomerId)
        REFERENCES Customers(CustomerId)
        ON UPDATE CASCADE
        ON DELETE RESTRICT
);

Primärnycklar

  • Ska vara korta och stabila: använd INTEGER/BIGINT eller GUID (om distribuerat system).
  • I SQLite/SQL Server kan du använda INTEGER PRIMARY KEY + AUTOINCREMENT/IDENTITY.
  • Undvik att låta affärsdata (t.ex. personnummer) vara primärnyckel – de kan behöva ändras.

Främmande nycklar

  • Definiera alltid ON DELETE/ON UPDATE-beteenden så att framtiden inte blir överraskning.
    • CASCADE när barn ska tas bort automatiskt.
    • RESTRICT eller NO ACTION när du vill stoppa borttagning.
    • SET NULL när relationen är frivillig.
  • Indexera kolumen som refererar – annars blir JOINs tröga.

Datakvalitet med NOT NULL, UNIQUE och CHECK

ALTER TABLE Products
    ADD CONSTRAINT CK_Products_Price CHECK (Price >= 0);

ALTER TABLE Products
    ADD CONSTRAINT UQ_Products_Sku UNIQUE (Sku);

CHECK kan kombinera flera kolumner:

CHECK (SalePrice <= RegularPrice OR SalePrice IS NULL)

DEFAULT – smarta startvärden

  • Bra för tidsstämplar (DEFAULT CURRENT_TIMESTAMP).
  • Används ofta tillsammans med BIT/BOOLEAN flaggor, t.ex. IsActive BIT DEFAULT 1.
  • Kom ihåg att DEFAULT inte körs när du explicit skickar NULL – kombinera med NOT NULL om värdet är obligatoriskt.

Checklista innan du deployar schemat

  1. Har varje tabell en primärnyckel?
  2. Är alla obligatoriska kolumner markerade som NOT NULL?
  3. Har varje relation en tydlig ON DELETE/UPDATE-regel?
  4. Finns unika constraints där du kräver unika värden (t.ex. e-post)?
  5. Finns det CHECK-villkor på kritiska siffror som inte får vara negativa?

Vanliga misstag

  • Glömda index på foreign keys → långsamma JOINs.
  • Överlappande constraints (t.ex. både UNIQUE och PRIMARY KEY på samma kolumn utan anledning).
  • Fel ordning vid dataimport – skapa constraints efter att du laddat legacy-data, sedan aktivera dem.
  • Silent fail: i SQLite måste PRAGMA foreign_keys = ON; aktiveras i varje connection, annars ignoreras constraints.

Koppling till C#

SQL constraintMotsvarighet i C# / EF Core
PRIMARY KEY[Key] eller modelBuilder.Entity().HasKey()
FOREIGN KEYNavigation properties + HasOne/WithMany
NOT NULLRequired i data annotations/fluently
UNIQUEHasIndex(...).IsUnique()
CHECKHasCheckConstraint()
DEFAULTHasDefaultValue() eller HasDefaultValueSql()

Sammanfattning

  • Constraints är första försvarslinjen – låt databasen hjälpa dig hålla datan ren.
  • Kombinera flera constraint-typer för att uttrycka affärsregler direkt i schemat.
  • Dokumentera alltid varför du valt en viss ON DELETE-strategi så att framtida utvecklare vet vad som gäller.

Dad joke

Varför älskar databasen regler? För att då blir det inte så många relationsproblem.


Upp

Upp


Licens: Apache 2.0 | © 2023 Marcus Medina, Campus Mölndal. Alla rättigheter förbehållna.
Du får använda och modifiera detta verk enligt villkoren i Apache License, Version 2.0. Du får inte använda detta verk för kommersiella ändamål utan tillstånd från upphovsmannen.