PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Commander la chaîne varchar en tant que numérique

C'est tout à fait possible.

ORDER BY varchar_column::int

Assurez-vous d'avoir des littéraux entiers valides dans votre varchar colonne pour chaque entrée ou vous obtenez une exception invalid input syntax for integer: ... . (Les espaces blancs de début et de fin sont acceptables - ils seront automatiquement coupés.)

Si tel est le cas, alors pourquoi ne pas convertir la colonne en integer pour commencer? Plus petit, plus rapide, plus propre, plus simple.

Comment éviter les exceptions ?

Pour supprimer les caractères non numériques avant le cast et éviter ainsi d'éventuelles exceptions :

ORDER BY NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '')::int
  • Le regexp_replace() expression supprime efficacement tous les non-chiffres, il ne reste donc que des chiffres ou une chaîne vide. (Voir ci-dessous.)

  • \D est un raccourci pour la classe de caractères [^[:digit:]] , c'est-à-dire tous les non-chiffres ([^0-9] ).
    Dans les anciennes versions de Postgres avec le paramètre obsolète standard_conforming_strings = off , vous devez utiliser la syntaxe de chaîne d'échappement Posix E'\\D' pour échapper la barre oblique inverse \ . C'était la valeur par défaut dans Postgres 8.3, vous en aurez donc besoin pour votre version obsolète.

  • Le 4ème paramètre g est pour "globalement" , demandant de remplacer tous occurrences, pas seulement la première.

  • Vous pouvez souhaitez autoriser un tiret initial (- ) pour les nombres négatifs.

  • Si la chaîne n'a aucun chiffre, le résultat est une chaîne vide qui n'est pas valide pour une conversion en integer . Convertir les chaînes vides en NULL avec NULLIF . (Vous pourriez considérer 0 à la place.)

Le résultat est garanti valide. Cette procédure est pour un transtypage en integer comme demandé dans le corps de la question, pas pour numeric comme le titre l'indique.

Comment faire vite ?

Une façon est un index sur une expression.

CREATE INDEX tbl_varchar_col2int_idx ON tbl
(cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer));

Utilisez ensuite la même expression dans le ORDER BY clause :

ORDER BY
cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer)

Testez avec EXPLAIN ANALYZE si l'index fonctionnel est réellement utilisé.