sqlpostgresqlstringslpad

LPAD и RPAD в SQL: как дополнить строку слева или справа

Практический разбор LPAD и RPAD: дополнение нулями, фиксированная ширина, обрезка длинных строк и различия PostgreSQL, MySQL и ClickHouse.

7 мин чтенияСправочникsql · postgresql · strings · lpad · rpad · formatting

Иногда значение в базе нужно не просто вывести, а красиво привести к нужному формату. Например, у пользователя есть id = 42, а в интерфейсе или выгрузке нужно показать код 000042. Или нужно собрать строку для старой банковской системы, где каждое поле занимает строго определённое количество символов.

Для таких задач в SQL используют функции LPAD и RPAD. Они дополняют строку до нужной длины: LPAD добавляет символы слева, а RPAD — справа.

Главная идея простая: мы берём исходное значение, задаём нужную длину и говорим, каким символом добить строку.

SELECT LPAD('42', 6, '0') AS code;

Результат:

000042

Число 42 занимало два символа. Мы попросили получить строку длиной шесть символов, поэтому SQL добавил четыре нуля слева.

Чем отличаются LPAD и RPAD

Названия функций удобно читать буквально:

  • LPAD — left padding, дополнение слева;
  • RPAD — right padding, дополнение справа.
SELECT
    LPAD('42', 6, '0')    AS padded_left,
    RPAD('SQL', 8, '.')   AS padded_right;

Результат:

padded_left | padded_right
------------+--------------
000042      | SQL.....

LPAD чаще используют для кодов, номеров заказов, счетов и других значений, где нужны ведущие нули.

RPAD чаще используют для текстовых полей, когда нужно выровнять строку до фиксированной ширины: например, имя, город, код страны или название отдела.

Синтаксис LPAD и RPAD

В PostgreSQL функции выглядят так:

LPAD(string, length, fill)
RPAD(string, length, fill)

Например:

SELECT
    LPAD('7', 5, '0')      AS user_number,
    RPAD('Alex', 10, ' ')  AS name_for_export;

Результат:

user_number | name_for_export
------------+----------------
00007       | Alex

Во втором примере после Alex будут добавлены пробелы. В таблице их визуально почти не видно, но в строке они есть.

В PostgreSQL третий аргумент можно не указывать. Тогда по умолчанию строка будет дополнена пробелами:

SELECT RPAD('SQL', 6);

Результат будет строкой длиной 6 символов:

SQL

Но на практике лучше указывать заполнитель явно. Так код легче читать, особенно начинающим.

Важный момент: LPAD и RPAD работают со строками

Даже если вы хотите дополнить нулями обычный числовой id, сначала его нужно превратить в текст.

В PostgreSQL это часто делают через ::text:

SELECT
    id,
    LPAD(id::text, 6, '0') AS user_code
FROM users;

Если в таблице есть такие данные:

id
--
1
7
42
105

то результат будет таким:

id  | user_code
----+----------
1   | 000001
7   | 000007
42  | 000042
105 | 000105

Такой формат часто используют для человекочитаемых кодов. В базе хранится нормальный числовой id, а красивый код собирается только при выводе.

Это хороший подход: число остаётся числом, его удобно сортировать, фильтровать и связывать с другими таблицами. А красивое представление строится отдельно.

Коды пользователей, заказов и счетов

Самый популярный сценарий для LPAD — сделать код фиксированной длины.

Например, хотим получить код пользователя в формате USR-000007:

SELECT
    id,
    'USR-' || LPAD(id::text, 6, '0') AS user_code
FROM users
ORDER BY id;

Результат:

id | user_code
---+-----------
1  | USR-000001
7  | USR-000007
42 | USR-000042

Здесь происходит две вещи:

  1. LPAD(id::text, 6, '0') превращает 7 в 000007.
  2. 'USR-' || ... добавляет префикс USR-.

То же самое можно сделать для заказов:

SELECT
    id,
    'ORD-' || LPAD(id::text, 8, '0') AS order_number
FROM orders
ORDER BY id;

Результат:

id  | order_number
----+--------------
15  | ORD-00000015
238 | ORD-00000238

Или для счетов:

SELECT
    id,
    'INV-2026-' || LPAD(id::text, 6, '0') AS invoice_number
FROM invoices
WHERE status = 'paid'
ORDER BY id;

Результат:

id  | invoice_number
----+----------------
12  | INV-2026-000012
123 | INV-2026-000123

Такой код удобно показывать пользователю, вставлять в письмо или выгружать во внешнюю систему.

Почему не стоит хранить готовый код в таблице

У новичков часто появляется желание создать отдельную колонку user_code и сразу хранить там USR-000007.

Иногда так действительно делают, но в простых случаях лучше не спешить.

Если код полностью строится из id, хранить его отдельно обычно не нужно. Иначе в таблице появится дублирование: id уже есть, а user_code просто повторяет его в красивом виде.

Лучше хранить чистые данные:

id
--
7

А форматировать их при выводе:

SELECT 'USR-' || LPAD(id::text, 6, '0') AS user_code
FROM users;

Так база остаётся аккуратной: в ней лежит значение, а не его декоративная версия.

Главная ловушка: строка может быть обрезана

У LPAD и RPAD есть важное поведение, о котором легко забыть.

Если исходная строка уже длиннее нужной длины, SQL не оставит её как есть, а обрежет до указанного размера.

SELECT LPAD('1234567', 6, '0') AS result;

Результат:

123456

Мы попросили строку длиной 6 символов. Исходная строка была длиной 7 символов, поэтому SQL просто отрезал лишнее.

Для учебного примера это не страшно. Но в реальной жизни такая ошибка может быть неприятной.

Представьте, что вы делаете номер заказа длиной 6 символов:

SELECT LPAD(id::text, 6, '0') AS order_code
FROM orders;

Пока id маленький, всё хорошо:

000001
000042
123456

Но когда id станет семизначным, например 1234567, результат будет обрезан:

123456

Часть значения потерялась, а ошибка не появилась. Это опасно.

Как защититься от случайной обрезки

Если вы не хотите, чтобы длинные значения обрезались, можно сделать целевую длину динамической: брать максимум между нужной шириной и реальной длиной строки.

В PostgreSQL это можно сделать через GREATEST:

SELECT
    id,
    LPAD(id::text, GREATEST(6, LENGTH(id::text)), '0') AS safe_code
FROM users;

Как это работает:

  • если id короткий, например 42, длина будет 6, и получится 000042;
  • если id длинный, например 1234567, длина будет 7, и значение останется 1234567.

То есть мы говорим базе: «Дополняй до 6 символов, но если значение уже длиннее — не режь его».

Заполнитель может быть не одним символом

Чаще всего в качестве заполнителя используют один символ: 0, пробел, точку или дефис.

Но технически заполнитель может быть длиннее одного символа:

SELECT LPAD('7', 5, 'ab') AS result;

Результат:

abab7

SQL повторяет строку-заполнитель столько раз, сколько нужно, а потом обрезает лишнее до нужной длины.

Ещё пример:

SELECT RPAD('SQL', 10, '-*') AS result;

Результат:

SQL-*-*-*

В обычных бизнес-задачах лучше использовать простой заполнитель из одного символа. Так результат легче предсказать и читать.

RPAD для выравнивания текста

RPAD полезен, когда текстовое поле должно занимать фиксированную ширину.

Например, нужно вывести имя сотрудника так, чтобы оно всегда занимало 15 символов:

SELECT RPAD(name, 15, ' ') AS name_fixed
FROM employees;

Если имя короткое, справа добавятся пробелы:

Alex
Maria
Konstantin

В обычной таблице пробелы почти не видны. Но они важны, если вы собираете строку для отчёта или файла фиксированной ширины.

Например:

SELECT
    RPAD(name, 20, ' ') || LPAD(salary::text, 10, ' ') AS report_line
FROM employees
ORDER BY name;

Результат может выглядеть так:

Alex                     2500
Maria                    3100
Konstantin               4500

Здесь имя выравнивается влево, а зарплата — вправо.

Именно поэтому для текста часто используют RPAD, а для чисел — LPAD.

Выгрузки фиксированной ширины

В современных системах данные часто передают в CSV, JSON или Excel. Но в банковских, бухгалтерских и старых корпоративных системах всё ещё встречаются форматы фиксированной ширины.

Это формат, где у строки нет разделителей вроде запятых или точек с запятой. Вместо этого каждое поле занимает строго определённое количество символов.

Например:

Ivan Petrov         RU000000001500
Maria Smirnova      KZ000000002300

Здесь можно договориться, что:

  • имя занимает 20 символов;
  • страна занимает 2 символа;
  • сумма занимает 12 символов.

SQL-запрос для такой строки может выглядеть так:

SELECT
      RPAD(u.name, 20, ' ')
   || RPAD(u.country_code, 2, ' ')
   || LPAD(o.amount::text, 12, '0') AS export_line
FROM users u
JOIN orders o ON o.user_id = u.id
ORDER BY u.id;

Если данные такие:

name          | country_code | amount
--------------+--------------+-------
Ivan Petrov   | RU           | 1500
Maria         | KZ           | 2300

то итоговые строки будут приведены к единому формату:

Ivan Petrov         RU000000001500
Maria               KZ000000002300

Такой формат неудобен для человека, зато его любят некоторые внешние системы: они читают строку не по разделителям, а по позициям символов.

Что проверять перед выгрузкой

Если вы используете LPAD и RPAD для выгрузок, особенно важно заранее проверять длину полей.

Например, если имя должно занимать 20 символов, а в базе лежит имя длиной 35 символов, RPAD не спасёт ситуацию. Значение будет обрезано.

Можно найти такие строки заранее:

SELECT id, name, LENGTH(name) AS name_length
FROM users
WHERE LENGTH(name) > 20;

Так вы увидите данные, которые не помещаются в формат, и сможете решить, что с ними делать: обрезать, исправить, вынести в отдельный отчёт или поменять требования к выгрузке.

LPAD и RPAD в MySQL

В MySQL синтаксис почти такой же:

SELECT LPAD('42', 6, '0') AS code;

Результат:

000042

Но есть важная деталь: в MySQL третий аргумент обязателен. То есть нужно явно указать, чем дополнять строку.

Если вы работаете с числом, лучше явно привести его к строке:

SELECT LPAD(CAST(id AS CHAR), 6, '0') AS user_code
FROM users;

MySQL часто сам приводит типы, но явное преобразование делает запрос понятнее и безопаснее для чтения.

LPAD и RPAD в ClickHouse

В ClickHouse похожая логика, но часто используют функции leftPad и rightPad.

Например:

SELECT leftPad(toString(id), 6, '0') AS user_code
FROM users;

Результат:

000042

Для дополнения справа:

SELECT rightPad(name, 20, ' ') AS name_fixed
FROM users;

В ClickHouse, как и в других СУБД, важно помнить про типы: числовой id лучше явно превратить в строку через toString.

NULL, пустые строки и Unicode

На простых значениях LPAD и RPAD ведут себя предсказуемо. Но в реальных данных почти всегда встречаются особые случаи:

  • NULL;
  • пустая строка '';
  • слишком длинное значение;
  • кириллица;
  • эмодзи;
  • заполнитель из нескольких символов.

Например, если имя может быть NULL, результат тоже может стать NULL:

SELECT RPAD(name, 20, ' ') AS name_fixed
FROM users;

Если для выгрузки вместо NULL нужна пустая строка, можно использовать COALESCE:

SELECT RPAD(COALESCE(name, ''), 20, ' ') AS name_fixed
FROM users;

COALESCE(name, '') означает: если name равен NULL, возьми пустую строку.

Для новичка это важный приём: перед форматированием лучше привести данные к ожидаемому виду.

Ещё один момент — длина в символах, а не в байтах. В PostgreSQL и ClickHouse LPAD и leftPad считают именно символы, поэтому кириллица и эмодзи дают ту ширину, которую вы ожидаете. Если же где-то длина считается в байтах, разметка колонок фиксированной ширины может «поехать». Перед переносом запросов между СУБД полезно прогнать тест на NULL, пустой строке, слишком длинном значении и имени с кириллицей.

Не используйте LPAD в WHERE без необходимости

LPAD удобно использовать в SELECT, когда мы готовим красивый вывод.

Но не стоит без необходимости писать так:

SELECT *
FROM users
WHERE LPAD(id::text, 6, '0') = '000042';

Такой запрос заставляет базу сначала посчитать LPAD для строк, а уже потом сравнивать результат. Обычный индекс по id в такой ситуации может не помочь.

Лучше фильтровать по исходному значению:

SELECT *
FROM users
WHERE id = 42;

А красивый код добавить только в вывод:

SELECT
    id,
    'USR-' || LPAD(id::text, 6, '0') AS user_code
FROM users
WHERE id = 42;

Запомните простое правило: фильтруем и соединяем таблицы по нормальным данным, а форматируем их уже при выводе.

Когда LPAD и RPAD действительно нужны

Используйте LPAD, когда нужно дополнить значение слева:

SELECT LPAD('42', 6, '0');

Результат:

000042

Это подходит для:

  • кодов пользователей;
  • номеров заказов;
  • номеров счетов;
  • значений с ведущими нулями;
  • числовых полей в выгрузках.

Используйте RPAD, когда нужно дополнить значение справа:

SELECT RPAD('SQL', 8, '.');

Результат:

SQL.....

Это подходит для:

  • имён;
  • названий;
  • кодов стран;
  • текстовых колонок фиксированной ширины;
  • строковых отчётов и legacy-выгрузок.

Коротко

LPAD и RPAD — это функции для дополнения строк до нужной длины.

LPAD добавляет символы слева:

SELECT LPAD('7', 4, '0');

Результат:

0007

RPAD добавляет символы справа:

SELECT RPAD('SQL', 6, '.');

Результат:

SQL...

Чаще всего LPAD используют для ведущих нулей, а RPAD — для выравнивания текста.

Главное, что стоит запомнить:

  • LPAD дополняет слева;
  • RPAD дополняет справа;
  • числа лучше явно приводить к тексту;
  • слишком длинные строки могут быть обрезаны;
  • для вывода форматирование подходит отлично;
  • для WHERE и JOIN лучше использовать исходные значения, а не форматированные строки.

Если держать эти правила в голове, LPAD и RPAD становятся простыми и очень полезными инструментами для кодов, отчётов и технических выгрузок.

Закрепи на практике

Решай задачи в SQL-тренажёре с мгновенной проверкой и подсказками.

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