Работа со строками — повседневная задача в SQL: очистка данных, форматирование, поиск по шаблону, извлечение частей текста. Разберём все ключевые функции PostgreSQL.
Длина строки
SELECT
LENGTH('Привет') AS char_length, -- 6 символов
CHAR_LENGTH('Привет') AS char_length2, -- 6 (alias)
OCTET_LENGTH('Привет') AS byte_length; -- 12 байт (UTF-8: 2 байта на кириллицу)
Регистр
SELECT
UPPER('hello world') -- HELLO WORLD
LOWER('HELLO WORLD') -- hello world
INITCAP('hello world') -- Hello World (первые буквы в верхнем регистре)
Практичный пример — нормализация email:
SELECT LOWER(TRIM(email)) AS normalized_email FROM users;
TRIM — убираем пробелы и символы
-- Убрать пробелы с обеих сторон
SELECT TRIM(' hello '); -- 'hello'
-- Только слева или справа
SELECT LTRIM(' hello '); -- 'hello '
SELECT RTRIM(' hello '); -- ' hello'
-- Убрать конкретный символ
SELECT TRIM(BOTH ',' FROM ',hello,'); -- 'hello'
SELECT TRIM(LEADING '0' FROM '00123'); -- '123'
CONCAT — объединение строк
-- Через функцию
SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM users;
-- Через оператор || (PostgreSQL)
SELECT first_name || ' ' || last_name AS full_name FROM users;
Разница с NULL:
-- CONCAT игнорирует NULL (MySQL-стиль в PostgreSQL 9.1+)
SELECT CONCAT('Hello', NULL, ' World'); -- 'Hello World'
-- || с NULL возвращает NULL!
SELECT 'Hello' || NULL || ' World'; -- NULL
Для безопасного объединения используйте COALESCE:
SELECT COALESCE(first_name, '') || ' ' || COALESCE(last_name, '') AS name
FROM users;
CONCAT_WS — объединение с разделителем
SELECT CONCAT_WS(', ', city, street, building) AS address FROM locations;
-- 'Москва, Льва Толстого, 16'
-- Если один элемент NULL — пропускается, разделитель не дублируется
SUBSTRING — извлечение подстроки
-- SUBSTRING(строка FROM начало FOR длина)
SELECT SUBSTRING('Hello World' FROM 1 FOR 5); -- 'Hello'
SELECT SUBSTRING('Hello World' FROM 7); -- 'World' (до конца)
-- Сокращённая форма
SELECT SUBSTR('Hello World', 7, 5); -- 'World'
Практичный пример — извлечь год из строки-даты:
SELECT SUBSTRING(date_str FROM 1 FOR 4) AS year FROM events;
POSITION / STRPOS — поиск подстроки
SELECT POSITION('World' IN 'Hello World'); -- 7 (позиция первого вхождения)
SELECT STRPOS('Hello World', 'World'); -- 7 (то же самое)
SELECT STRPOS('Hello World', 'xyz'); -- 0 (не найдено)
Извлечь домен из email:
SELECT
email,
SUBSTRING(email FROM STRPOS(email, '@') + 1) AS domain
FROM users;
REPLACE — замена подстроки
SELECT REPLACE('Hello World', 'World', 'SQL'); -- 'Hello SQL'
-- Убрать лишние символы
SELECT REPLACE(phone, '-', '') AS clean_phone FROM users;
-- '8-800-555-35-35' → '88005553535'
LEFT, RIGHT — n символов с края
SELECT LEFT('Hello World', 5); -- 'Hello'
SELECT RIGHT('Hello World', 5); -- 'World'
SELECT RIGHT('2026-03-15', 5); -- '03-15'
SPLIT_PART — разбить строку по разделителю
-- Разбить email на части
SELECT
SPLIT_PART('user@example.com', '@', 1) AS username, -- 'user'
SPLIT_PART('user@example.com', '@', 2) AS domain; -- 'example.com'
-- Второй элемент CSV
SELECT SPLIT_PART('apple,banana,cherry', ',', 2); -- 'banana'
LIKE и ILIKE — поиск по шаблону
-- LIKE: чувствительный к регистру
SELECT * FROM products WHERE name LIKE '%ноутбук%';
-- ILIKE: нечувствительный к регистру (PostgreSQL)
SELECT * FROM products WHERE name ILIKE '%ноутбук%';
-- Шаблоны:
-- % — любое количество любых символов
-- _ — ровно один любой символ
SELECT * FROM users WHERE email LIKE '%.ru'; -- emails на .ru
SELECT * FROM codes WHERE code LIKE 'AB__'; -- AB + 2 символа
⚠️
LIKE '%текст%'не использует обычный B-tree индекс. Для поиска в большой таблице нуженpg_trgmили полнотекстовый поиск.
Регулярные выражения в PostgreSQL
-- ~ : совпадает с regex (case-sensitive)
-- ~* : совпадает (case-insensitive)
-- !~ : не совпадает
-- !~*: не совпадает (case-insensitive)
SELECT * FROM emails WHERE address ~ '^[a-zA-Z].*@gmail\.com$';
-- REGEXP_REPLACE — замена по regex
SELECT REGEXP_REPLACE('тел. +7 (495) 123-45-67', '[^0-9]', '', 'g');
-- '74951234567'
-- REGEXP_MATCHES — извлечение совпадений
SELECT REGEXP_MATCHES('order-1234-extra', 'order-(\d+)', 'g');
-- {'1234'}
FORMAT — форматирование строки
SELECT FORMAT('Пользователь %s, ID %s', name, id) AS message FROM users;
-- 'Пользователь Алиса, ID 42'
-- С форматированием числа
SELECT FORMAT('Цена: %.2f руб.', 1234.5);
-- 'Цена: 1234.50 руб.'
TO_CHAR — числа и даты в строку
-- Число в строку с форматом
SELECT TO_CHAR(1234567.89, '9,999,999.99'); -- '1,234,567.89'
-- Дата в строку
SELECT TO_CHAR(NOW(), 'DD.MM.YYYY HH24:MI'); -- '15.03.2026 14:30'
SELECT TO_CHAR(NOW(), 'TMMonth YYYY', 'ru_RU'); -- 'Март 2026' (локаль)
Практические кейсы
Очистка номеров телефона
UPDATE users
SET phone = REGEXP_REPLACE(
TRIM(phone),
'[^0-9+]', '', 'g'
);
Маскировка email для логов
SELECT
CONCAT(
LEFT(SPLIT_PART(email, '@', 1), 2),
'***@',
SPLIT_PART(email, '@', 2)
) AS masked_email
FROM users;
-- 'us***@example.com'
Нормализация имён
SELECT INITCAP(LOWER(TRIM(full_name))) AS normalized_name FROM users;
-- ' ИВАНОВ ИВАН ' → 'Иванов Иван'
Итог: шпаргалка
| Функция | Что делает |
|---|---|
UPPER/LOWER | Регистр |
INITCAP | Первые буквы заглавные |
TRIM/LTRIM/RTRIM | Убирает пробелы/символы |
CONCAT/|| | Склейка строк |
CONCAT_WS | Склейка с разделителем |
SUBSTRING/SUBSTR | Подстрока |
POSITION/STRPOS | Позиция вхождения |
REPLACE | Замена подстроки |
LEFT/RIGHT | N символов с края |
SPLIT_PART | Разбить по разделителю |
LENGTH | Длина в символах |
LIKE/ILIKE | Поиск по шаблону |
~ / REGEXP_REPLACE | Регулярные выражения |
TO_CHAR | Число/дата → строка |