W3docs

MySQL Where

Узнайте, как использовать WHERE в MySQL из Python с параметризованными запросами, операторами сравнения, LIKE, IN, BETWEEN, проверками NULL и составными условиями.

Конструкция WHERE — основной способ фильтрации строк в операторах MySQL SELECT, UPDATE и DELETE. В этой главе показано, как использовать её из Python с помощью mysql-connector-python: фильтры по одному условию, операторы сравнения, LIKE, IN, BETWEEN, проверки NULL и составная логика AND/OR — всё с параметризованными запросами для защиты от SQL-инъекций.

Предварительные требования

Убедитесь, что перед запуском примеров у вас есть следующее:

  • Python 3.x и работающий сервер MySQL.
  • Установленный mysql-connector-python:
pip install mysql-connector-python
  • База данных с уже созданной таблицей customers — смотрите MySQL Create Database и MySQL Create Table, если вы ещё не выполнили эту настройку.

В примерах используется следующая таблица с несколькими строками:

CREATE TABLE IF NOT EXISTS customers (
  id      INT AUTO_INCREMENT PRIMARY KEY,
  name    VARCHAR(255) NOT NULL,
  address VARCHAR(255),
  age     INT
);

INSERT INTO customers (name, address, age) VALUES
  ('Alice',   'Oak Avenue 1',     30),
  ('Bob',     'Pine Street 42',   25),
  ('Charlie', 'Maple Road 7',     35),
  ('Diana',   'Oak Avenue 3',     28),
  ('Eve',     NULL,               22);

Зачем использовать параметризованные запросы

Прежде чем перейти к примерам кода, запомните одно правило: никогда не формируйте условие WHERE путём конкатенации строк, введённых пользователем, непосредственно в SQL. Этот подход опасен:

# NEVER do this — SQL injection risk
name = input("Enter name: ")
sql = "SELECT * FROM customers WHERE name = '" + name + "'"

Если пользователь введёт ' OR '1'='1, запрос вернёт все строки. Вместо этого всегда передавайте значения через параметризованный интерфейс mysql-connector-python:

sql = "SELECT * FROM customers WHERE name = %s"
mycursor.execute(sql, (name,))

Коннектор безопасно экранирует значение до того, как оно попадёт в базу данных. Заполнитель всегда %s, независимо от типа данных столбца (целое число, string, дата и т. д.).

Фильтрация по точному значению

Наиболее распространённый случай: получить строки, в которых столбец равен определённому значению.

import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    sql = "SELECT * FROM customers WHERE name = %s"
    val = ("Alice",)

    mycursor.execute(sql, val)
    results = mycursor.fetchall()

    for row in results:
        print(row)

except Error as e:
    print(f"Error: {e}")

finally:
    if mydb.is_connected():
        mycursor.close()
        mydb.close()

Пример вывода:

(1, 'Alice', 'Oak Avenue 1', 30)

Обратите внимание, что val должен быть кортежем, даже если в нём только одно значение — отсюда замыкающая запятая в ("Alice",).

Операторы сравнения

Конструкция WHERE поддерживает все стандартные операторы сравнения SQL:

ОператорЗначениеПример условия
=Равноage = 30
<> или !=Не равноage <> 30
>Большеage > 25
>=Больше или равноage >= 28
<Меньшеage < 30
<=Меньше или равноage <= 30

Пример: строки, где возраст больше 28

import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    sql = "SELECT name, age FROM customers WHERE age > %s"
    val = (28,)

    mycursor.execute(sql, val)
    for row in mycursor.fetchall():
        print(row)

except Error as e:
    print(f"Error: {e}")

finally:
    if mydb.is_connected():
        mycursor.close()
        mydb.close()

Пример вывода:

('Alice', 30)
('Charlie', 35)

Сопоставление по шаблону с LIKE

LIKE сопоставляет шаблоны в строковых столбцах. Доступны два символа-подстановочных знака:

  • % — соответствует нулю или более символам.
  • _ — соответствует ровно одному символу.
import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    # Find customers whose address starts with "Oak"
    sql = "SELECT name, address FROM customers WHERE address LIKE %s"
    val = ("Oak%",)

    mycursor.execute(sql, val)
    for row in mycursor.fetchall():
        print(row)

except Error as e:
    print(f"Error: {e}")

finally:
    if mydb.is_connected():
        mycursor.close()
        mydb.close()

Пример вывода:

('Alice', 'Oak Avenue 1')
('Diana', 'Oak Avenue 3')

LIKE нечувствителен к регистру для столбцов с кодировкой utf8mb4 по умолчанию. Используйте LIKE BINARY, если требуется сопоставление с учётом регистра.

Проверка нескольких значений с IN

IN проверяет, входит ли значение столбца в список. Это эквивалентно цепочке нескольких условий OR, но значительно удобнее для чтения.

import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    names = ("Alice", "Charlie", "Eve")
    # Build one %s placeholder per value
    placeholders = ", ".join(["%s"] * len(names))
    sql = f"SELECT name, age FROM customers WHERE name IN ({placeholders})"

    mycursor.execute(sql, names)
    for row in mycursor.fetchall():
        print(row)

except Error as e:
    print(f"Error: {e}")

finally:
    if mydb.is_connected():
        mycursor.close()
        mydb.close()

Пример вывода:

('Alice', 30)
('Charlie', 35)
('Eve', 22)

Поскольку количество значений в IN может меняться во время выполнения, приведённый выше шаблон динамически формирует строку заполнителей (", ".join(["%s"] * len(names))). Это сохраняет параметризацию независимо от длины списка.

Фильтрация диапазона с BETWEEN

BETWEEN выбирает строки, у которых значение столбца попадает в включительный диапазон:

import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    sql = "SELECT name, age FROM customers WHERE age BETWEEN %s AND %s"
    val = (25, 30)

    mycursor.execute(sql, val)
    for row in mycursor.fetchall():
        print(row)

except Error as e:
    print(f"Error: {e}")

finally:
    if mydb.is_connected():
        mycursor.close()
        mydb.close()

Пример вывода:

('Alice', 30)
('Bob', 25)
('Diana', 28)

BETWEEN 25 AND 30 включает оба граничных значения (25 и 30). Работает с датами и строками, а также с числами.

Проверка значений NULL

Значение NULL означает, что в поле нет данных. Проверить NULL с помощью = невозможно — необходимо использовать IS NULL или IS NOT NULL.

import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    # Find customers with no address recorded
    sql = "SELECT name FROM customers WHERE address IS NULL"
    mycursor.execute(sql)

    for row in mycursor.fetchall():
        print(row)

except Error as e:
    print(f"Error: {e}")

finally:
    if mydb.is_connected():
        mycursor.close()
        mydb.close()

Пример вывода:

('Eve',)

IS NULL и IS NOT NULL не принимают параметров, поэтому второй аргумент в execute() не передаётся.

Составные условия с AND и OR

Объединяйте несколько условий в одном предложении WHERE с помощью AND (все условия должны выполняться) и OR (хотя бы одно условие должно выполняться).

Пример AND

import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    # Customers on "Oak Avenue" who are older than 28
    sql = "SELECT name, address, age FROM customers WHERE address LIKE %s AND age > %s"
    val = ("Oak%", 28)

    mycursor.execute(sql, val)
    for row in mycursor.fetchall():
        print(row)

except Error as e:
    print(f"Error: {e}")

finally:
    if mydb.is_connected():
        mycursor.close()
        mydb.close()

Пример вывода:

('Alice', 'Oak Avenue 1', 30)

Диана живёт на Oak Avenue, но ей 28 лет, поэтому она не удовлетворяет условию age > 28.

Пример OR

import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    # Customers named Alice OR younger than 25
    sql = "SELECT name, age FROM customers WHERE name = %s OR age < %s"
    val = ("Alice", 25)

    mycursor.execute(sql, val)
    for row in mycursor.fetchall():
        print(row)

except Error as e:
    print(f"Error: {e}")

finally:
    if mydb.is_connected():
        mycursor.close()
        mydb.close()

Пример вывода:

('Alice', 30)
('Eve', 22)

Используйте скобки для управления приоритетом при смешивании AND и OR: (a OR b) AND c ведёт себя иначе, чем a OR (b AND c).

Использование WHERE с UPDATE и DELETE

Конструкция WHERE одинаково важна в операторах UPDATE и DELETE. Без неё оператор затронет каждую строку таблицы.

import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    # Update only Alice's address
    sql = "UPDATE customers SET address = %s WHERE name = %s"
    val = ("New Street 10", "Alice")
    mycursor.execute(sql, val)
    mydb.commit()
    print(mycursor.rowcount, "row(s) updated")

except Error as e:
    print(f"Error: {e}")
    mydb.rollback()

finally:
    if mydb.is_connected():
        mycursor.close()
        mydb.close()

Пример вывода:

1 row(s) updated

Всегда проверяйте условие WHERE с помощью SELECT перед выполнением UPDATE или DELETE. Пропущенное или неверное условие в производственной таблице может быть трудно обратить. Подробнее см. MySQL Update и MySQL Delete.

Получение одной строки или всех строк

После execute() выберите, сколько строк нужно получить:

МетодВозвращаетИспользовать когда
fetchone()Первую подходящую строку (или None)Ожидается не более одного результата, например поиск по первичному ключу
fetchmany(n)До n строкПостраничный вывод или ограниченный предварительный просмотр
fetchall()Все подходящие строки в виде спискаНебольшие наборы результатов, где загрузка всех строк за раз допустима
mycursor.execute("SELECT * FROM customers WHERE age > %s", (25,))

# Fetch only the first result
first = mycursor.fetchone()
print(first)  # (1, 'Alice', 'Oak Avenue 1', 30)

Для больших наборов результатов предпочтительнее использовать fetchmany() в цикле или серверный курсор (MySQLCursorBuffered), чтобы не загружать все строки в память сразу.

Распространённые ошибки

Использование = для проверки NULL. WHERE address = NULL никогда не вернёт строк; всегда используйте IS NULL.

Забытая замыкающая запятая в кортеже с одним значением. val = ("Alice") создаёт string, а не кортеж. Пишите val = ("Alice",).

Форматирование значений в SQL в виде строк. F-строки и форматирование через % обходят параметризацию. Передавайте значения вторым аргументом в execute().

Пропуск WHERE в UPDATE или DELETE. Без конструкции WHERE будет затронута каждая строка таблицы.

Использование Python None там, где SQL ожидает NULL. mysql-connector-python автоматически преобразует Python None в SQL NULL, поэтому mycursor.execute("UPDATE customers SET address = %s WHERE id = %s", (None, 1)) корректно устанавливает address в NULL.

Что делать дальше

  • MySQL Order By — сортировка строк, возвращённых конструкцией WHERE.
  • MySQL Limit — ограничение количества возвращаемых строк.
  • MySQL Update — изменение строк, соответствующих условию.
  • MySQL Delete — удаление строк, соответствующих условию.
  • MySQL Join — фильтрация по нескольким таблицам с помощью WHERE в сочетании с объединениями.
Was this page helpful?