Напълно възможно е.
ORDER BY varchar_column::int
Уверете се, че имате валидни целочислени литерали във вашия varchar
колона за всеки запис или получавате изключение invalid input syntax for integer: ...
. (Началото и крайното бяло пространство е наред – то ще бъде изрязано автоматично.)
Ако случаят е такъв, защо тогава да не конвертирате колоната в integer
да започнем с? По-малък, по-бърз, по-чист, по-прост.
Как да избегнем изключения?
За да премахнете нецифрени знаци преди прехвърлянето и по този начин да избегнете възможни изключения:
ORDER BY NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '')::int
-
regexp_replace()
изразът ефективно премахва всички нецифрени числа, така че остават само цифри или празен низ. (Вижте по-долу.) -
\D
е съкращения за класа на знаците[^[:digit:]]
, което означава всички нецифрени ([^0-9]
).
В стари версии на Postgres с остарялата настройкаstandard_conforming_strings = off
, трябва да използвате синтаксис на escape низ на PosixE'\\D'
за избягване на обратната наклонена черта\
. Това беше по подразбиране в Postgres 8.3, така че ще ви трябва за остарялата ви версия. -
Четвъртият параметър
g
е за „глобално“ , с инструкция за замяна на всички събития, не само първите. -
Вие можете искате да разрешите водещо тире (
-
) за отрицателни числа. -
Ако низът изобщо няма цифри, резултатът е празен низ, който не е валиден за прехвърляне към
integer
. Преобразувайте празните низове вNULL
сNULLIF
. (Можете да помислите за0
вместо това.)
Резултатът е гарантирано валиден. Тази процедура е за прехвърляне към integer
както е поискано в тялото на въпроса, не за numeric
както се споменава в заглавието.
Как да го направя бързо?
Един от начините е индекс на израз.
CREATE INDEX tbl_varchar_col2int_idx ON tbl
(cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer));
След това използвайте същия израз в ORDER BY
клауза:
ORDER BY
cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer)
Тествайте с EXPLAIN ANALYZE
дали функционалният индекс действително се използва.