Es ist absolut möglich.
ORDER BY varchar_column::int
Stellen Sie sicher, dass Ihr varchar
gültige Integer-Literale enthält Spalte für jeden Eintrag oder Sie erhalten eine Ausnahme invalid input syntax for integer: ...
. (Leerraum am Anfang und am Ende ist ok - er wird automatisch gekürzt.)
Wenn dies jedoch der Fall ist, warum konvertieren Sie die Spalte dann nicht in integer
zunächst? Kleiner, schneller, sauberer, einfacher.
Wie vermeide ich Ausnahmen?
Um nicht-stellige Zeichen vor der Umwandlung zu entfernen und dadurch mögliche Ausnahmen zu vermeiden:
ORDER BY NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '')::int
-
Der
regexp_replace()
expression entfernt effektiv alle Nicht-Ziffern, sodass nur Ziffern oder eine leere Zeichenfolge übrig bleiben. (Siehe unten.) -
\D
ist eine Abkürzung für die Zeichenklasse[^[:digit:]]
, also alle Nichtziffern ([^0-9]
).
In alten Postgres-Versionen mit der veralteten Einstellungstandard_conforming_strings = off
, müssen Sie die Posix-Escape-String-SyntaxE'\\D'
verwenden um den Backslash\
zu maskieren . Dies war die Standardeinstellung in Postgres 8.3, also brauchen Sie das für Ihre veraltete Version. -
Der 4. Parameter
g
steht für "global" , die anweist, alle zu ersetzen Ereignisse, nicht nur das erste. -
Sie können einen führenden Bindestrich zulassen möchten (
-
) für negative Zahlen. -
Wenn der String überhaupt keine Ziffern enthält, ist das Ergebnis ein leerer String, der für eine Umwandlung in
integer
nicht gültig ist . Konvertieren Sie leere Zeichenfolgen inNULL
mitNULLIF
. (Sie könnten0
in Betracht ziehen stattdessen.)
Das Ergebnis ist garantiert valide. Dieses Verfahren ist für eine Umwandlung in integer
wie im Hauptteil der Frage gefordert, nicht für numeric
wie der Titel schon sagt.
Wie macht man es schnell?
Eine Möglichkeit ist ein Index für einen Ausdruck.
CREATE INDEX tbl_varchar_col2int_idx ON tbl
(cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer));
Verwenden Sie dann denselben Ausdruck in ORDER BY
Klausel:
ORDER BY
cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer)
Testen Sie mit EXPLAIN ANALYZE
ob der funktionale Index tatsächlich verwendet wird.