Det er absolut muligt.
ORDER BY varchar_column::int
Sørg for at have gyldige heltalsliteraler i din varchar
kolonne for hver post, eller du får en undtagelse invalid input syntax for integer: ...
. (Første og efterfølgende hvide mellemrum er ok - det trimmes automatisk.)
Hvis det er tilfældet, hvorfor så ikke konvertere kolonnen til integer
til at starte med? Mindre, hurtigere, renere, enklere.
Hvordan undgår man undtagelser?
For at fjerne ikke-cifrede tegn før rollebesætningen og derved undgå mulige undtagelser:
ORDER BY NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '')::int
-
regexp_replace()
udtryk fjerner effektivt alle ikke-cifre, så kun cifre er tilbage eller en tom streng. (Se nedenfor.) -
\D
er en forkortelse for tegnklassen[^[:digit:]]
, hvilket betyder alle ikke-cifre ([^0-9]
).
I gamle Postgres-versioner med den forældede indstillingstandard_conforming_strings = off
, skal du bruge Posix escape streng syntaksE'\\D'
for at undslippe omvendt skråstreg\
. Dette var standard i Postgres 8.3, så det skal du bruge til din forældede version. -
Den 4. parameter
g
er for "globalt" , med instruktion om at erstatte alle hændelser, ikke kun den første. -
Du må ønsker at tillade en indledende bindestreg (
-
) for negative tal. -
Hvis strengen slet ikke har nogen cifre, er resultatet en tom streng, som ikke er gyldig for en cast til
integer
. Konverter tomme strenge tilNULL
medNULLIF
. (Du kan overveje0
i stedet.)
Resultatet er garanteret gyldigt. Denne procedure er for en cast til integer
som anmodet i brødteksten i spørgsmålet, ikke for numeric
som titlen nævner.
Hvordan gør man det hurtigt?
En måde er et indeks på et udtryk.
CREATE INDEX tbl_varchar_col2int_idx ON tbl
(cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer));
Brug derefter det samme udtryk i ORDER BY
klausul:
ORDER BY
cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer)
Test med EXPLAIN ANALYZE
om funktionsindekset rent faktisk bliver brugt.