PostgreSQL / Хязгаарлалт (PRIMARY KEY, UNIQUE, NOT NULL)

Хязгаарлалт (PRIMARY KEY, UNIQUE, NOT NULL)

Өгөгдлийн санд буруу, давтагдсан, хоосон мэдээлэл орохоос сэргийлэхийн тулд constraint буюу хязгаарлалт ашиглана. Constraint нь хүснэгтийн "дүрэм" юм — энэ дүрмийг зөрчсөн ямар ч бичлэг орохыг PostgreSQL автоматаар татгалздаг. Мэдээллийн чанарыг хамгаалах хамгийн найдвартай арга бол code дотор биш, өгөгдлийн санд хязгаарлалт тавих явдал.

NOT NULL — хоосон байж болохгүй

NOT NULL нь тухайн баганад NULL утга орохыг хориглодог хамгийн энгийн хязгаарлалт:

sql
CREATE TABLE users (
    id    BIGSERIAL PRIMARY KEY,
    нэр   TEXT NOT NULL,       -- заавал байх ёстой
    имэйл TEXT NOT NULL,       -- заавал байх ёстой
    утас  TEXT                 -- NULL байж болно (заасаагүй)
);

NOT NULL зөрчвөл:

sql
INSERT INTO users (нэр) VALUES ('Болд');
-- ERROR:  null value in column "имэйл" of relation "users"
-- violates not-null constraint

Одоо байгаа баганад NOT NULL нэмэх:

sql
ALTER TABLE users ALTER COLUMN утас SET NOT NULL;

-- Хасах
ALTER TABLE users ALTER COLUMN утас DROP NOT NULL;

PRIMARY KEY — давтагдашгүй танигч

PRIMARY KEY нь хүснэгтийн хамгийн чухал хязгаарлалт юм. Хоёр шаардлагыг нэгэн зэрэг биелүүлнэ: NOT NULL ба UNIQUE. Хүснэгт бүрт яг нэг PRIMARY KEY байна.

sql
-- SERIAL + PRIMARY KEY хамтдаа
CREATE TABLE products (
    id   BIGSERIAL PRIMARY KEY,
    нэр  TEXT NOT NULL
);

-- Эсвэл доор тусдаа зарлах хэлбэр
CREATE TABLE products (
    id   BIGINT GENERATED ALWAYS AS IDENTITY,
    нэр  TEXT NOT NULL,
    CONSTRAINT products_pkey PRIMARY KEY (id)
);

Нийлмэл primary key — хоёр баганын хослол давтагдашгүй байх:

sql
CREATE TABLE lesson_progress (
    user_id    INTEGER NOT NULL,
    lesson_id  INTEGER NOT NULL,
    дууссан    BOOLEAN DEFAULT FALSE,
    PRIMARY KEY (user_id, lesson_id)   -- хоёулаа хамтдаа давтагдахгүй
);

UNIQUE — давтагдашгүй утга

UNIQUE нь тухайн баганын утга хүснэгтэд давтагдахгүй байхыг баталгаажуулна. PRIMARY KEY-с ялгаатай нь NULL утга зөвшөөрдөг (NULL ≠ NULL тул хэд хэдэн NULL байж болно):

sql
CREATE TABLE users (
    id     BIGSERIAL PRIMARY KEY,
    имэйл  TEXT UNIQUE NOT NULL,
    утас   TEXT UNIQUE       -- NULL байж болно, гэхдээ утга байвал давтагдахгүй
);

UNIQUE зөрчвөл:

sql
INSERT INTO users (имэйл) VALUES ('bold@example.com');
INSERT INTO users (имэйл) VALUES ('bold@example.com');
-- ERROR:  duplicate key value violates unique constraint "users_имэйл_key"
-- DETAIL:  Key (имэйл)=(bold@example.com) already exists.

Нийлмэл unique — хоёр баганын хослол давтагдахгүй:

sql
CREATE TABLE enrollments (
    user_id   INTEGER NOT NULL,
    course_id INTEGER NOT NULL,
    UNIQUE (user_id, course_id)   -- нэг хэрэглэгч нэг курст нэг удаа л бүртгэгдэнэ
);

CHECK — нөхцөлт хязгаарлалт

CHECK нь баганын утга тодорхой нөхцөлийг хангаж байхыг шаарддаг:

sql
CREATE TABLE products (
    id       BIGSERIAL PRIMARY KEY,
    нэр      TEXT NOT NULL,
    үнэ      NUMERIC(10,2) CHECK (үнэ >= 0),
    нөөц     INTEGER CHECK (нөөц >= 0),
    үнэлгээ  SMALLINT CHECK (үнэлгээ BETWEEN 1 AND 5)
);

Нэрлэсэн CHECK constraint:

sql
CREATE TABLE users (
    id   BIGSERIAL PRIMARY KEY,
    нас  INTEGER,
    CONSTRAINT нас_хүчин_төгөлдөр CHECK (нас >= 0 AND нас <= 150)
);

CHECK зөрчвөл:

sql
INSERT INTO products (нэр, үнэ) VALUES ('Бараа', -500);
-- ERROR:  new row for relation "products" violates check constraint "products_үнэ_check"

DEFAULT — өгөгдмөл утга

DEFAULT нь хязгаарлалт биш боловч constraint-уудтай хамт байнга ашиглагддаг. Утга оруулаагүй үед автоматаар тавигдах утга тодорхойлно:

sql
CREATE TABLE posts (
    id          BIGSERIAL PRIMARY KEY,
    гарчиг      TEXT NOT NULL,
    нийтлэгдсэн BOOLEAN DEFAULT FALSE,
    харагдсан   INTEGER DEFAULT 0,
    үүсгэсэн    TIMESTAMPTZ DEFAULT NOW(),
    статус      TEXT DEFAULT 'draft' CHECK (статус IN ('draft', 'published', 'archived'))
);

Одоо байгаа хүснэгтэд constraint нэмэх

sql
-- UNIQUE нэмэх
ALTER TABLE users
ADD CONSTRAINT users_утас_unique UNIQUE (утас);

-- CHECK нэмэх
ALTER TABLE products
ADD CONSTRAINT үнэ_эерэг CHECK (үнэ > 0);

-- Constraint хасах
ALTER TABLE products
DROP CONSTRAINT үнэ_эерэг;

Бүх constraint-уудыг нэгтгэсэн жишээ

sql
CREATE TABLE orders (
    id          BIGSERIAL PRIMARY KEY,
    user_id     INTEGER NOT NULL,
    нийт_үнэ   NUMERIC(12,2) NOT NULL CHECK (нийт_үнэ > 0),
    статус      TEXT NOT NULL DEFAULT 'pending'
                    CHECK (статус IN ('pending','processing','shipped','delivered','cancelled')),
    хаяг        TEXT NOT NULL,
    үүсгэсэн    TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE (id, user_id)
);

Constraint нь хөгжүүлэгчийн алдааг хамгаалдаг хамгийн зардал багатай хамгаалалт — код бичихдээ заавал ашиглах дадал болго.

Дараагийн хичээлд:

Хүснэгтүүдийг хоорондоо холбох FOREIGN KEY хязгаарлалтыг сурч — харилцаат өгөгдлийн санг зөв бүтцэлэх үндэс суурийг тавина.