Сравнение строк в SQL: равенство, LIKE и неизвестный NULL
Сравнение текстовых значений — не то же самое, что вычисление разницы соседних записей. Для текста выбирают условие равенства, шаблон или принадлежность набору. Ни один из этих вариантов не отменяет правила NULL и выбранной collation. Ниже используются правила PostgreSQL.
Равенство и NULL
SELECT
'John' = 'John' AS equal_names,
NULL::text = NULL::text AS unknown_equal,
NULL::text IS NOT DISTINCT FROM NULL::text AS nulls_match,
'John' IS DISTINCT FROM NULL::text AS differs;
-- true, NULL, true, trueОбычные = и <> при сравнении с NULL дают неизвестный результат NULL. Условие WHERE оставляет только true, поэтому WHERE name = NULL не ищет отсутствующие имена: используйте name IS NULL. Для сравнения двух потенциально пустых полей IS DISTINCT FROM даёт true/false и считает два NULL одинаковыми.
LIKE, IN и включённые границы
SELECT 'John' COLLATE "C" LIKE 'J%' AS starts_with_j;
-- true
SELECT 'Jane' IN ('John', 'Jane', 'Jack') AS in_list;
-- true
SELECT 18 BETWEEN 18 AND 30 AS adult_range;
-- true
SELECT 'Anna' NOT IN ('John', NULL::text) AS uncertain;
-- NULLВ LIKE знак % соответствует любому числу символов, а _ — одному. Шаблон применяется ко всей строке. Чтобы искать буквальные % и _, задайте экранирование. BETWEEN включает обе границы; для чисел используйте числовой тип, а не строковое представление возраста.
NULL внутри NOT IN особенно опасен: отсутствие совпадения с John ещё не делает результат true. При проверке отсутствия связанных строк часто понятнее NOT EXISTS с явным условием связи; отдельно решите, как трактовать NULL в ключе.
Регистр и правила сортировки
В PostgreSQL есть ILIKE для поиска без учёта регистра; LOWER/UPPER преобразуют текст по соответствующим языковым правилам. Но это не обещание одинакового поведения всех Unicode-строк, СУБД и collations. Для ожидаемого строгого побайтного сравнения в небольшом тесте можно явно выбрать collation C:
SELECT 'John' COLLATE "C" = 'john' COLLATE "C";
-- false
SELECT LOWER('John') = LOWER('JOHN');
-- trueВ запросе приложения
Пользовательское имя или шаблон передавайте параметром через драйвер, не вставляйте его в SQL конкатенацией. Выберите точное сравнение или LIKE по задаче: функция LOWER на колонке и поиск с ведущим % могут изменить использование индексов. План и требования к collation проверяйте на вашей схеме и данных.