Postgresql. Косяк при преобразовании текста в число, Теряются разряды

В таблице есть столбец с идентификаторами вида YYMM.DD№№

2101.1601#
2101.1602#
2101.1701#

т.е. это дата плюс двузначное число. Мне нужно создать новый идентификатор на определённую дату.

Регуляркой выбираю последние 3 цифры из идентификаторов за опред дату напр 16.01.2021

SELECT REGEXP_MATCHES(номСделки, '\d\d\d(?=\D*$)', 'g')  
FROM db.Сделки 
WHERE номСделки ~ '2101\.16';

получаю набор: ( кстати что значат эти фиг скобки при выводе? )

{601}
{602}

теперь мне нужно изменит их тип на integer.

Пробовал to_number( val, '999' ); Почему то возвращает 60 вместо 601 куда-то девается один разряд.

Если пишу вручную to_number( '601', '999' ); результат правильный,

Если пишу вручную со скобками как в рез выборки to_number( '{601}', '999' );

то опять получаю такой же косяк 60 вместо 601. В чём дело?


Ответы (1 шт):

Автор решения: Alexander Pavlov

получаю набор: ( кстати что значат эти фиг скобки при выводе? )

В документации это явно указывается

The regexp_matches function returns a set of text arrays of captured substring(s)

Т.е. эта функция возвращает не первое подходящее значение, а все (даже если оно только одно) в виде массива.

Я бы на твоём месте решал обратную задачу - стереть ненужное

select regexp_replace(regexp_replace('2021.0119687asd', '^\d{4}\.\d{4}', ''), '\D*$', '')

или даже (если ты уверен в длине префикса)

select regexp_replace(substr('2021.0119687asd', 10), '\D*$', '')

Ещё, кстати, совет создать дату в таблице сделок, индекс по этой дате и фильтровать по ней, вместо регулярного выражения, потому что с ростом размера таблицы твой фильтр просто убьёт всю производительность. Ну и прямо сейчас заменить WHERE номСделки ~ '2101\.16'; на WHERE номСделки ~ '^2101\.16';

→ Ссылка