To absolutnie możliwe.
ORDER BY varchar_column::int
Upewnij się, że w swoim varchar
masz prawidłowe literały liczb całkowitych kolumna dla każdego wpisu lub otrzymasz wyjątek invalid input syntax for integer: ...
. (Pierwsze i końcowe białe znaki są w porządku – zostaną przycięte automatycznie.)
Jeśli tak jest, to dlaczego nie przekonwertować kolumny na integer
? najpierw? Mniejszy, szybszy, czystszy, prostszy.
Jak unikać wyjątków?
Aby usunąć znaki niecyfrowe przed rzutowaniem i tym samym uniknąć możliwych wyjątków:
ORDER BY NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '')::int
-
regexp_replace()
wyrażenie skutecznie usuwa wszystkie cyfry niebędące cyframi, więc pozostają tylko cyfry lub pusty ciąg. (Patrz poniżej.) -
\D
jest skrótem klasy znaków[^[:digit:]]
, co oznacza wszystkie cyfry niebędące cyframi ([^0-9]
).
W starych wersjach Postgresa z przestarzałym ustawieniemstandard_conforming_strings = off
, musisz użyć składni łańcucha ucieczki PosixE'\\D'
aby zmienić ukośnik odwrotny\
. To było domyślne w Postgres 8.3, więc będziesz potrzebować tego w swojej przestarzałej wersji. -
Czwarty parametr
g
jest dla „globalnie” , instruując zastąpienie wszystkich wystąpienia, nie tylko pierwsze. -
możesz chcesz zezwolić na wiodący myślnik (
-
) dla liczb ujemnych. -
Jeśli ciąg w ogóle nie zawiera cyfr, wynikiem jest pusty ciąg, który nie jest prawidłowy do rzutowania na
integer
. Konwertuj puste ciągi naNULL
zNULLIF
. (Możesz rozważyć0
zamiast tego.)
Wynik jest gwarantowany. Ta procedura dotyczy rzutowania na integer
zgodnie z żądaniem w treści pytania, nie dla numeric
jak wskazuje tytuł.
Jak zrobić to szybko?
Jednym ze sposobów jest indeks wyrażenia.
CREATE INDEX tbl_varchar_col2int_idx ON tbl
(cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer));
Następnie użyj tego samego wyrażenia w ORDER BY
klauzula:
ORDER BY
cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer)
Przetestuj za pomocą EXPLAIN ANALYZE
czy indeks funkcjonalny faktycznie jest używany.