Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
WHERE в SQL
WHERE — это фундаментальное предложение (clause) в SQL, которое используется для фильтрации данных в результирующем наборе запроса. Оно позволяет указать условия, которым должны удовлетворять строки из таблицы, чтобы быть включёнными в результат SELECT, UPDATE или DELETE операций.
Основной синтаксис
SELECT с WHERE:
SELECT column1, column2, ...
FROM table_name
WHERE condition;
Примеры условий:
-- Простое равенство
SELECT * FROM employees WHERE department_id = 5;
-- Неравенство
SELECT * FROM products WHERE price > 100;
-- Логические операторы
SELECT * FROM orders WHERE status = 'pending' AND created_at > '2024-01-01';
Операторы сравнения
Числовые операторы:
-- Равно
SELECT * FROM employees WHERE salary = 50000;
-- Не равно
SELECT * FROM employees WHERE salary != 50000;
SELECT * FROM employees WHERE salary <> 50000;
-- Больше / Меньше
SELECT * FROM orders WHERE amount > 1000;
SELECT * FROM products WHERE stock < 10;
-- Больше или равно / Меньше или равно
SELECT * FROM employees WHERE salary >= 60000;
SELECT * FROM users WHERE age <= 18;
Текстовые операторы:
-- Точное совпадение
SELECT * FROM users WHERE first_name = 'John';
-- Чувствительность к регистру зависит от collation
SELECT * FROM users WHERE LOWER(first_name) = 'john';
-- Использование LIKE (шаблоны)
SELECT * FROM users WHERE email LIKE '%@gmail.com';
SELECT * FROM products WHERE name LIKE 'iPhone%';
SELECT * FROM employees WHERE last_name LIKE '_mith'; -- один символ
Логические операторы
AND - оба условия должны быть истинны:
SELECT * FROM employees
WHERE department_id = 5 AND salary > 50000;
-- Несколько условий
SELECT * FROM orders
WHERE status = 'completed'
AND created_at > '2024-01-01'
AND total_amount > 1000;
OR - хотя бы одно условие должно быть истинным:
SELECT * FROM users
WHERE first_name = 'John' OR first_name = 'Jane';
SELECT * FROM products
WHERE category = 'electronics' OR price > 500;
NOT - отрицание условия:
SELECT * FROM employees WHERE NOT department_id = 5;
SELECT * FROM products WHERE NOT status = 'inactive';
Комбинация операторов:
SELECT * FROM orders
WHERE (status = 'completed' OR status = 'shipped')
AND created_at > '2024-01-01'
AND total_amount > 500;
Специальные операторы WHERE
IN - проверка наличия в списке:
SELECT * FROM employees
WHERE department_id IN (1, 2, 3, 5);
SELECT * FROM orders
WHERE status IN ('pending', 'processing', 'shipped');
BETWEEN - диапазон значений:
SELECT * FROM products WHERE price BETWEEN 100 AND 500;
SELECT * FROM orders
WHERE created_at BETWEEN '2024-01-01' AND '2024-12-31';
IS NULL / IS NOT NULL - проверка на NULL:
SELECT * FROM users WHERE middle_name IS NULL;
SELECT * FROM orders WHERE deleted_at IS NOT NULL;
EXISTS - проверка наличия подзапроса:
SELECT * FROM users u
WHERE EXISTS (
SELECT 1 FROM orders o WHERE o.user_id = u.id AND o.total > 1000
);
WHERE в Java с помощью SQL параметров
Использование PreparedStatement (защита от SQL инъекций):
public User findByEmail(String email) throws SQLException {
String query = "SELECT * FROM users WHERE email = ?";
try (PreparedStatement stmt = connection.prepareStatement(query)) {
stmt.setString(1, email);
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
return mapRowToUser(rs);
}
}
}
return null;
}
ПЛОХО - SQL инъекция:
// НИКОГДА ТАК НЕ ДЕЛАЙ!
public User findByEmail(String email) throws SQLException {
String query = "SELECT * FROM users WHERE email = '" + email + "'";
// Уязвимо для SQL инъекции!
Statement stmt = connection.createStatement();
return stmt.executeQuery(query);
}
WHERE с JOIN
Фильтрация после объединения таблиц:
SELECT u.id, u.email, o.order_id, o.total
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE u.created_at > '2024-01-01' AND o.total > 100;
В Java с ORM (Hibernate):
public List<User> findActiveUsersWithOrders() {
return session.createQuery(
"FROM User u " +
"JOIN u.orders o " +
"WHERE u.active = true AND o.status = 'completed'",
User.class
).list();
}
WHERE с подзапросами (Subqueries)
Фильтрация по результатам подзапроса:
-- Найти все заказы пользователей из определённого города
SELECT * FROM orders
WHERE user_id IN (
SELECT id FROM users WHERE city = 'New York'
);
-- Найти продукты дороже средней цены
SELECT * FROM products
WHERE price > (SELECT AVG(price) FROM products);
В Java с JPA:
@Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
@Query("SELECT o FROM Order o WHERE o.user.city = :city")
List<Order> findOrdersByUserCity(@Param("city") String city);
@Query("SELECT o FROM Order o WHERE o.total > " +
"(SELECT AVG(o2.total) FROM Order o2)")
List<Order> findOrdersAboveAverage();
}
Performance и индексы
Индексы значительно ускоряют WHERE:
-- Создание индекса
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_orders_user_status ON orders(user_id, status);
-- Без индекса - полное сканирование таблицы (медленно)
SELECT * FROM users WHERE email = 'user@example.com'; -- O(n)
-- С индексом - быстрый поиск (логарифмический)
SELECT * FROM users WHERE email = 'user@example.com'; -- O(log n)
WHERE в UPDATE и DELETE
UPDATE с условием:
UPDATE employees
SET salary = salary * 1.1
WHERE department_id = 5 AND years_of_service > 5;
DELETE с условием:
-- БУДЬ ОСТОРОЖЕН!
DELETE FROM users WHERE active = false AND deleted_at < DATE_SUB(NOW(), INTERVAL 30 DAY);
В Java:
public void deactivateOldInactiveUsers() {
String query = "UPDATE User u SET u.active = false " +
"WHERE u.lastLogin < CURRENT_DATE - 90";
Query q = entityManager.createQuery(query);
q.executeUpdate();
}
Best Practices
1. Используй параметризованные запросы:
@Query("SELECT u FROM User u WHERE u.email = :email")
User findByEmail(@Param("email") String email);
2. Добавляй индексы на часто используемые WHERE колонки:
CREATE INDEX idx_active_users ON users(active) WHERE active = true;
3. Избегай функций на левой стороне WHERE (блокируют индексы):
-- ПЛОХО
WHERE LOWER(email) = 'test@example.com';
-- ХОРОШО
WHERE email = 'test@example.com';
4. Будь осторожен с NULL:
WHERE age IS NULL; -- Правильно
WHERE age = NULL; -- НИКОГДА не работает!
Заключение
WHERE — это критически важное предложение в SQL, которое позволяет эффективно фильтровать данные. Правильное использование WHERE с индексами, параметризованными запросами и логическими операторами обеспечивает как производительность, так и безопасность приложения.