QA Interview Hub · База знань · Тести
SQL
Основи баз даних
таблиці, ключі, типи, NULL
Що таке реляційна база даних і що таке SQL?
Реляційна база даних зберігає дані в таблицях: кожен рядок — це один запис (користувач, рахунок, транзакція), кожен стовпець — його властивість. Таблиці пов'язані між собою ключами: транзакція знає, до якого рахунку належить, рахунок — до якого користувача.
SQL (Structured Query Language) — мова, якою з цими даними працюють: читають, додають, змінюють, видаляють і описують структуру. Головна особливість — SQL декларативний: ти описуєш, що хочеш отримати, а як саме це знайти, вирішує сама СУБД.
Популярні СУБД: PostgreSQL, MySQL, Microsoft SQL Server, Oracle. Базовий SQL у них однаковий, відрізняються деталі: LIMIT проти TOP, функції дат, деякі типи. Приклади в цьому гайді — для PostgreSQL.
На співбесіді: Реляційна база зберігає дані в пов'язаних між собою таблицях, а SQL — це декларативна мова для роботи з ними: я описую, які дані хочу отримати, а база сама вирішує, як їх знайти. Я працював переважно з PostgreSQL, але базовий синтаксис у різних СУБД однаковий.
Що таке первинний і зовнішній ключ?
- Первинний ключ (PRIMARY KEY) — стовпець, що однозначно ідентифікує рядок. Він унікальний і не може бути NULL. Зазвичай це
id.
- Зовнішній ключ (FOREIGN KEY) — стовпець, що посилається на первинний ключ іншої таблиці. Він створює зв'язок і не дає записати посилання на неіснуючий запис.
У нашій схемі accounts.user_id посилається на users.id. Спроба створити рахунок для користувача 999, якого немає, впаде з помилкою порушення зовнішнього ключа.
CREATE TABLE accounts (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id),
currency CHAR(3) NOT NULL,
balance NUMERIC(14,2) NOT NULL DEFAULT 0
);
На співбесіді: Первинний ключ однозначно ідентифікує рядок — він унікальний і не буває порожнім. Зовнішній ключ посилається на первинний ключ іншої таблиці і гарантує цілісність: наприклад, не можна створити рахунок для користувача, якого не існує. Для мене як QA це ще й підказка, що тестувати: чи система коректно обробляє такі помилки.
Які типи даних QA варто знати?
| Тип | Для чого | На що звернути увагу |
INTEGER, BIGINT | Цілі числа, ID | Межі діапазону: INTEGER до ~2,1 млрд |
NUMERIC(p,s) / DECIMAL | Точні дробові, гроші | NUMERIC(14,2) — до 14 цифр, 2 після коми |
REAL, DOUBLE PRECISION | Наближені дробові | Мають похибку — не для грошей |
VARCHAR(n), TEXT | Рядки | Довжина: що буде з рядком довшим за n |
BOOLEAN | Так / ні | Може бути ще й NULL |
DATE, TIMESTAMP, TIMESTAMPTZ | Дати й час | Із часовим поясом чи без |
UUID, JSONB | Унікальні ID, гнучкі дані | Формат, вкладені поля |
Тип стовпця прямо підказує граничні значення для тестів: максимальна довжина рядка, кількість знаків після коми, діапазон чисел.
На співбесіді: Найчастіше я маю справу з цілими числами для ID, NUMERIC для грошей, рядками, булевими значеннями і датами з часовим поясом чи без. Тип стовпця для мене — джерело граничних значень: максимальна довжина рядка, кількість знаків після коми, діапазон числа. Якщо UI дозволяє більше, ніж база, — це потенційний баг.
Що таке NULL і чим він відрізняється від 0 і порожнього рядка?
NULL означає «значення невідоме або відсутнє». Це не нуль і не порожній рядок:
0 — відоме значення: баланс дорівнює нулю.
'' — відоме значення: рядок, у якому нічого немає.
NULL — значення невідоме: баланс ще не порахований, телефон не вказаний.
Головна властивість: будь-яке порівняння з NULL дає не TRUE і не FALSE, а UNKNOWN. Навіть NULL = NULL — не TRUE. А арифметика з NULL дає NULL: 100 + NULL = NULL.
Через це NULL — джерело багатьох багів: рядки «зникають» з фільтрів, суми стають порожніми, лічильники не сходяться.
На співбесіді: NULL означає, що значення невідоме або відсутнє, — це не нуль і не порожній рядок. Будь-яке порівняння з NULL дає не «так» і не «ні», а «невідомо», тому рядки з NULL часто випадають з фільтрів, а арифметика з NULL дає NULL. Тому я завжди окремо перевіряю, як система поводиться з порожніми значеннями.
На які групи поділяються команди SQL?
| Група | Команди | Що роблять |
| DQL — запити | SELECT | Читають дані |
| DML — маніпуляція | INSERT, UPDATE, DELETE | Змінюють дані |
| DDL — визначення | CREATE, ALTER, DROP, TRUNCATE | Змінюють структуру |
| DCL — доступ | GRANT, REVOKE | Керують правами |
| TCL — транзакції | BEGIN, COMMIT, ROLLBACK | Керують транзакціями |
Іноді SELECT відносять до DML — обидва варіанти зустрічаються.
На співбесіді: Команди SQL поділяють на групи: SELECT для читання, INSERT, UPDATE і DELETE для зміни даних, CREATE, ALTER і DROP для структури, GRANT і REVOKE для прав, а BEGIN, COMMIT і ROLLBACK для транзакцій. Як QA я найчастіше пишу SELECT, рідше — INSERT і UPDATE для підготовки тестових даних, і завжди в транзакції.
Навіщо QA знати SQL?
- Перевірка результату: UI показує «Переказ успішний», а в базі — правильна сума, статус, комісія, запис в історії?
- Тестові дані: знайти користувача в потрібному стані або створити його, не проходячи десять кроків в UI.
- Діагностика: баг у фронтенді, в API чи в самих даних? Запит до бази часто відповідає за хвилину.
- Цілісність: знайти дублікати, «осиротілі» записи, неможливі стани.
- Автотести: підготовка й очищення даних, перевірки після дій.
На співбесіді: SQL для мене — це спосіб перевірити правду поза інтерфейсом. UI може показати «успішно», а в базі буде не та сума чи статус. Ще я використовую SQL, щоб швидко знайти або створити тестові дані, локалізувати баг — фронтенд, бекенд чи дані — і шукати порушення цілісності, як-от дублікати чи записи без батьківського.