SQL — один з найбільш недооцінених скілів для QA початківців. Але коли ви вперше зможете самостійно перевірити що дані правильно збереглись в БД після тесту — це змінить підхід до тестування.
Ця стаття — практичний мінімум. Без академічних визначень, з реальними прикладами з QA роботи.
Навіщо QA знати SQL
Верифікація даних. UI показує "замовлення збережено" — але чи правильні дані в базі? Тільки SQL-запит дасть точну відповідь.
Підготовка тест-даних. Потрібно протестити обробку замовлень "старших 30 днів" — простіше вставити тестові дані через SQL ніж створювати їх через UI.
Дебаг багів. "Баг не репродукується" — перевіряємо стан даних в БД і знаходимо причину.
Тестування без UI. Перевірити що бекграунд-процес правильно обробив записи — тільки через БД.
Основи SELECT
1-- Отримати всі записи з таблиці
2SELECT * FROM users;
3
4-- Отримати конкретні поля
5SELECT id, name, email FROM users;
6
7-- З умовою
8SELECT * FROM users WHERE email = 'test@example.com';
9
10-- Кілька умов
11SELECT * FROM users WHERE role = 'admin' AND is_active = true;
12SELECT * FROM orders WHERE status = 'pending' OR status = 'processing';WHERE: умови відбору
1-- Рівність і нерівність
2WHERE age = 25
3WHERE age != 25 -- або <> 25
4WHERE age > 18
5WHERE age >= 18
6WHERE age BETWEEN 18 AND 65
7
8-- Рядки
9WHERE name = 'Іван'
10WHERE email LIKE '%@gmail.com' -- закінчується на @gmail.com
11WHERE name LIKE 'Ів%' -- починається з "Ів"
12WHERE name ILIKE '%іван%' -- case-insensitive пошук (PostgreSQL)
13
14-- NULL перевірка
15WHERE deleted_at IS NULL -- активні записи
16WHERE deleted_at IS NOT NULL -- видалені записи
17
18-- Список значень
19WHERE status IN ('pending', 'processing', 'shipped')
20WHERE id NOT IN (1, 2, 3)
21
22-- Дати
23WHERE created_at >= '2026-01-01'
24WHERE created_at BETWEEN '2026-01-01' AND '2026-12-31'
25WHERE created_at >= NOW() - INTERVAL '7 days' -- за останні 7 днівРеальні QA приклади
Перевірити що user зареєструвався
1-- Після реєстрації через UI або API:
2SELECT id, name, email, created_at, is_verified
3FROM users
4WHERE email = 'test@example.com';
5
6-- Що перевіряємо:
7-- ✅ Запис існує
8-- ✅ name і email відповідають введеним даним
9-- ✅ created_at = сьогодні
10-- ✅ is_verified = false (якщо потрібна верифікація email)Перевірити що замовлення створилось
1SELECT
2 o.id,
3 o.status,
4 o.total_amount,
5 o.created_at,
6 o.user_id
7FROM orders o
8WHERE o.user_id = 123
9ORDER BY o.created_at DESC
10LIMIT 1;
11
12-- Перевіряємо найновіше замовлення цього userПеревірити що пароль змінився (без бачення самого пароля)
1-- Запам'ятовуємо хеш ДО зміни
2SELECT password_hash FROM users WHERE id = 456;
3-- '...старий_хеш...'
4
5-- Змінюємо пароль через UI
6
7-- Перевіряємо що хеш змінився
8SELECT password_hash FROM users WHERE id = 456;
9-- '...новий_хеш...' (повинен відрізнятись)ORDER BY і LIMIT
1-- Сортування за датою (нові спочатку)
2SELECT * FROM orders ORDER BY created_at DESC;
3
4-- Перші 10 записів
5SELECT * FROM users ORDER BY created_at DESC LIMIT 10;
6
7-- Сторінка 2 з 10 записів (пагінація)
8SELECT * FROM users ORDER BY id LIMIT 10 OFFSET 10;
9
10-- Знайти останнє замовлення конкретного user
11SELECT * FROM orders
12WHERE user_id = 123
13ORDER BY created_at DESC
14LIMIT 1;COUNT, SUM, AVG: агрегатні функції
1-- Кількість users
2SELECT COUNT(*) FROM users;
3
4-- Кількість активних users
5SELECT COUNT(*) FROM users WHERE is_active = true;
6
7-- Загальна сума замовлень
8SELECT SUM(total_amount) FROM orders WHERE status = 'completed';
9
10-- Середній чек
11SELECT AVG(total_amount) FROM orders WHERE status = 'completed';
12
13-- Кількість замовлень по статусам
14SELECT status, COUNT(*) as count
15FROM orders
16GROUP BY status;
17
18-- Результат:
19-- pending | 45
20-- processing | 12
21-- completed | 234
22-- cancelled | 8JOIN: об'єднання таблиць
Найважливіша тема для QA. Реальні дані зберігаються в кількох таблицях.
INNER JOIN — тільки ті що є в обох таблицях
1-- Замовлення з іменами users
2SELECT
3 o.id as order_id,
4 o.total_amount,
5 o.status,
6 u.name as user_name,
7 u.email
8FROM orders o
9INNER JOIN users u ON o.user_id = u.id
10WHERE o.status = 'pending';LEFT JOIN — всі з лівої таблиці + відповідні з правої
1-- Всі users і кількість їх замовлень (включно з тими хто не замовляв)
2SELECT
3 u.id,
4 u.name,
5 u.email,
6 COUNT(o.id) as orders_count
7FROM users u
8LEFT JOIN orders o ON u.id = o.user_id
9GROUP BY u.id, u.name, u.email
10ORDER BY orders_count DESC;Реальний QA приклад: перевірити що order_items правильні
1-- Після створення замовлення з 2 товарами
2SELECT
3 o.id as order_id,
4 o.total_amount,
5 oi.product_id,
6 oi.quantity,
7 oi.price,
8 p.name as product_name
9FROM orders o
10JOIN order_items oi ON o.id = oi.order_id
11JOIN products p ON oi.product_id = p.id
12WHERE o.id = 789;
13
14-- Перевіряємо:
15-- ✅ Є 2 рядки (2 товари)
16-- ✅ Quantity і price відповідають тому що вибрали
17-- ✅ total_amount = SUM(oi.quantity * oi.price)Перевірка цілісності даних
1-- Orphan records: order_items без orders (баг!)
2SELECT oi.*
3FROM order_items oi
4LEFT JOIN orders o ON oi.order_id = o.id
5WHERE o.id IS NULL;
6
7-- Users з дублікатами email (якщо такого не повинно бути)
8SELECT email, COUNT(*) as count
9FROM users
10GROUP BY email
11HAVING COUNT(*) > 1;
12
13-- Замовлення з нульовою сумою (підозріло)
14SELECT * FROM orders
15WHERE total_amount = 0 OR total_amount IS NULL;
16
17-- Рядки в невалідному статусі
18SELECT * FROM orders
19WHERE status NOT IN ('pending', 'processing', 'shipped', 'completed', 'cancelled');Підготовка тест-даних
1-- Вставка тестового user
2INSERT INTO users (name, email, role, created_at)
3VALUES ('Test User', 'testqa@example.com', 'user', NOW());
4
5-- Масова вставка тестових даних
6INSERT INTO products (name, price, category) VALUES
7 ('Тестовий продукт 1', 100.00, 'electronics'),
8 ('Тестовий продукт 2', 250.00, 'electronics'),
9 ('Тестовий продукт 3', 50.00, 'books');
10
11-- Оновлення для тесту (наприклад, зробити замовлення "старим")
12UPDATE orders
13SET created_at = NOW() - INTERVAL '35 days'
14WHERE id = 789;
15
16-- Видалення тестових даних після тесту
17DELETE FROM users WHERE email LIKE '%testqa%';⚠️ Завжди робіть INSERT/UPDATE/DELETE тільки в тестовій БД! Перед виконанням перевірте до якої бази підключені.
Транзакції: коли тестуєте критичні операції
1-- Починаємо транзакцію (зміни не застосовуються одразу)
2BEGIN;
3
4-- Робимо тестові зміни
5UPDATE orders SET status = 'cancelled' WHERE id = 789;
6
7-- Перевіряємо результат
8SELECT * FROM orders WHERE id = 789;
9
10-- Якщо все ок — застосовуємо
11COMMIT;
12
13-- Або скасовуємо якщо щось не так
14ROLLBACK;Практичний чеклист SQL для QA
1Базовий рівень (Junior):
2□ SELECT з WHERE і кількома умовами
3□ ORDER BY і LIMIT
4□ COUNT записів
5□ Перевірка NULL значень
6
7Середній рівень (Middle):
8□ JOIN двох таблиць (INNER і LEFT)
9□ GROUP BY з COUNT/SUM
10□ Пошук дублікатів
11□ Дати і часові відрізки
12
13Практика:
14□ Верифікація даних після кожного API тесту
15□ Пошук orphan records
16□ Перевірка цілісності після batch операційДе практикуватись
SQLZoo (sqlzoo.net) — інтерактивні завдання в браузері, безкоштовно.
LeetCode SQL — задачі від простих до складних.
pgexercises.com — PostgreSQL-специфічні вправи.
Реальна практика: попросіть доступ до тестової БД на роботі або встановіть PostgreSQL локально і практикуйтесь на реальних даних.
Підсумок
Для QA не потрібно знати весь SQL на рівні DBA. Потрібно впевнено писати SELECT запити з умовами, JOIN і базовою агрегацією — і це вже відкриє можливість тестувати на рівні даних, а не тільки UI.
Почніть з SELECT і WHERE, за тиждень практики додайте JOIN — і ви вже будете в топ 30% QA за цим скілом.