SQLLab
Все статьи

Строковые функции в SQL: полный справочник с примерами

SUBSTRING, CONCAT, TRIM, UPPER, LOWER, REPLACE, LIKE, REGEXP, LENGTH и другие строковые функции в PostgreSQL. Примеры для очистки и трансформации данных.

15 марта 2026 г.·5 мин чтения·

Работа со строками — повседневная задача в 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/RIGHTN символов с края
SPLIT_PARTРазбить по разделителю
LENGTHДлина в символах
LIKE/ILIKEПоиск по шаблону
~ / REGEXP_REPLACEРегулярные выражения
TO_CHARЧисло/дата → строка

Похожие статьи

Попробуй на практике

Тренажёр с реальными задачами — бесплатно и без регистрации

Открыть тренажёр →