Це другий пост у серії про Postgres, рекомендую почати з нього, щоб ознайомитись з деякими іншими важливими концепціями PostgreSQL. Але якщо ви готові зануритись глибше в забезпечення цілісності даних, давайте почнемо!
У цьому пості ми розглянемо один з найефективніших інструментів для забезпечення цілісності даних у PostgreSQL: обмеження. Зокрема, я покажу, як можна використовувати обмеження для забезпечення таких правил, як гарантована позитивність цін або те, що знижки не перевищують початкову ціну — безпосередньо в базі даних.
У PostgreSQL обмеження відіграють важливу роль у забезпеченні цілісності даних, застосовуючи конкретні правила до даних, що зберігаються у вашій базі даних. Обмеження є потужним інструментом для того, щоб забезпечити відповідність даних певним умовам, запобігаючи помилкам до того, як вони зможуть вплинути на ваш додаток.
Один з типових прикладів — це забезпечення того, щоб стовпець ціни завжди містив лише позитивні значення, починаючи з 0. На відміну від MySQL, який надає тип цілого числа UNSIGNED
для забезпечення цієї умови, PostgreSQL не має вбудованого типу даних, щоб зберігати лише позитивні числа. Натомість, ви можете використовувати обмеження перевірки (check constraints) для застосування цього правила.
Чому обмеження важливі
За допомогою обмежень ви можете забезпечити відповідність даних безпосередньо в базі даних для збереження цілісності. Наприклад:
price
повинна завжди бути позитивною.discount_price
повинна завжди бути меншою заprice
.abbr
(абревіатура) повинна завжди містити рівно 5 символів.
Ці обмеження допомагають уникнути ризику потрапляння некоректних даних у базу даних, будь-то при вставці, оновленні або навіть при спробах обходу перевірок на рівні додатку.
Приклади обмежень
Давайте розглянемо кілька прикладів, щоб зрозуміти, як можна використовувати обмеження в PostgreSQL.
Приклад 1: Обмеження на рівні стовпців
Ви можете застосовувати обмеження безпосередньо до окремих стовпців, щоб переконатись, що вони відповідають певним умовам. Ось приклад, де ми визначаємо таблицю з трьома стовпцями: price
, discount_price
і abbr
.
CREATE TABLE checks_example (
price NUMERIC
CONSTRAINT price_must_be_positive CHECK (price > 0),
-- Обмеження на рівні стовпця discount_price NUMERIC
CONSTRAINT discount_price_must_be_positive CHECK (discount_price > 0),
abbr TEXT
CONSTRAINT abbr_length_check CHECK (LENGTH(abbr) = 5)
);
Тут ми додали наступні обмеження:
price_must_be_positive
: Гарантує, щоprice
завжди буде більше за 0.discount_price_must_be_positive
: Гарантує, щоdiscount_price
також буде більше за 0.abbr_length_check
: Гарантує, щоabbr
містить рівно 5 символів.
Тепер, якщо ви спробуєте вставити рядок, де abbr
має менше ніж 5 символів, PostgreSQL виведе помилку:
INSERT INTO checks_example(price, discount_price, abbr)
VALUES (10, 10, 'abcd');
- ERROR: new row for relation "checks_example" violates check constraint "abbr_length_check"
Приклад 2: Обмеження на рівні таблиці
Ви також можете визначати обмеження, які стосуються кількох стовпців.
Це обмеження на рівні таблиці. Наприклад, ми можемо захотіти переконатись, що discount_price
завжди менше за price
.
CREATE TABLE checks_example (
price NUMERIC CHECK (price > 0),
discount_price NUMERIC
CONSTRAINT discount_must_be_positive CHECK (discount_price > 0),
abbr TEXT
CONSTRAINT abbr_length_check CHECK (LENGTH(abbr) = 5),
CONSTRAINT discount_price_must_be_less_price CHECK (price > discount_price)
-- discount_price_must_be_less_price - ОБМЕЖЕННЯ НА РІВНІ ТАБЛИЦІ
);
Тут, обмеження discount_price_must_be_less_price
гарантує, що discount_price
завжди буде менше за price
.
Це обмеження на рівні таблиці, оскільки воно стосується кількох стовпців.
Вставка даних і обробка помилок
Давайте спробуємо вставити кілька рядків у таблицю:
- Це не вдасться, тому що discount_price (15) більша за price (10)
INSERT INTO checks_example(price, discount_price, abbr)
VALUES (10, 15, 'abcde');
- ERROR: new row for relation "checks_example" violates check constraint "discount_price_must_be_less_price"
- Це працює, тому що discount_price (8) менша за price (10)
INSERT INTO checks_example(price, discount_price, abbr)
VALUES (10, 8, 'abcde');
- Success
Як ви бачите, PostgreSQL виводить помилку, якщо discount_price
перевищує price
, тим самим дотримуючись правила, яке ми визначили в обмеженні на рівні таблиці.
Іменовані обмеження для зрозумілості
Можливо, ви помітили, що деякі обмеження мають імена, як-от price_must_be_positive
та discount_must_be_positive
. Надання імен обмеженням — це найкраща практика, оскільки це робить повідомлення про помилки більш інформативними та допомагає простіше знаходити проблеми. Якщо обмеження не проходить, у повідомленні про помилку буде зазначено ім'я порушеного обмеження, що значно полегшує налагодження.
Висновок
Підсумовуючи, обмеження перевірки (check constraints) у PostgreSQL — це потужний інструмент для забезпечення цілісності даних на рівні бази даних. Вони дозволяють забезпечити дотримання таких правил, як позитивність цін, взаємозв’язки між стовпцями та конкретні формати для текстових полів — все безпосередньо в схемі бази даних. Хоча важливо проводити перевірку даних на рівні додатку, використання обмежень у базі даних забезпечує додатковий рівень захисту, гарантуючи, що ваші дані залишатимуться послідовними і надійними, навіть коли до них здійснюється прямий доступ.
Використовуючи обмеження перевірки, ви не тільки забезпечуєте цілісність даних, а й вбудовуєте бізнес-правила в базу даних, ускладнюючи можливість проникнення некоректних або непослідовних даних — незалежно від того, чи відбувається це через логіку додатку, ручне маніпулювання базою даних або інтеграцію з іншими системами.
Останні думки
Хоча перевірки на рівні додатку важливі, обмеження бази даних надають критичний другий рівень захисту. Вони гарантують, що дані відповідають бізнес-правилам послідовно і надійно. Пам’ятайте, що ніхто не застрахований від можливості обходу логіки додатку, і саме тут обмеження допомагають захистити ваші дані.
Якщо ви знайшли цей пост корисним, я буду вдячний за лайк або коментар, щоб я міг зрозуміти, що вам це цікаво! Ваші відгуки допомагають мені створювати більше контенту, який буде корисний для вас.
А якщо ви хочете залишатися в курсі наступних постів у цій серії про PostgreSQL (і багато інших порад з баз даних), не забудьте підписатися на мій блог. У мене є багато цінних інсайтів, які я скоро поділюсь з вами.
Дякую за читання, і удачі в програмуванні!
Перекладено з: Enforcing Data Integrity with PostgreSQL Constraints