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

Couper les espaces de fin avec PostgreSQL

Il existe de nombreux personnages invisibles différents. Beaucoup d'entre eux ont la propriété WSpace=Y ("espace blanc") en Unicode. Mais certains caractères spéciaux ne sont pas considérés comme des "espaces blancs" et n'ont toujours pas de représentation visible. Les excellents articles de Wikipédia sur les espaces (ponctuation) et les espaces blancs devraient vous donner une idée.

Unicode craint à cet égard :introduire de nombreux caractères exotiques qui servent principalement à confondre les gens.

Le SQL standard trim() fonction par défaut ne supprime que le caractère d'espacement latin de base (Unicode :U+0020 / ASCII 32). Idem avec le rtrim() et ltrim() variantes. Votre appel ne cible également que ce personnage particulier.

Utiliser des expressions régulières avec regexp_replace() à la place.

À la fin

Pour supprimer tous les espaces blancs de fin (mais pas d'espace blanc à l'intérieur la chaîne):

SELECT regexp_replace(eventdate, '\s+$', '') FROM eventdates;

L'expression régulière expliquée :
\s ... raccourci de classe d'expression régulière pour [[:space:]]
    - qui est le jeu d'espaces blancs - voir les limitations ci-dessous
+ ... 1 ou plusieurs correspondances consécutives
$ ... fin de chaîne

Démo :

SELECT regexp_replace('inner white   ', '\s+$', '') || '|'

Renvoie :

inner white|

Oui, c'est un single barre oblique inverse (\ ). Détails dans cette réponse connexe :

  • SQL sélectionne où la colonne commence par \

En tête

Pour supprimer tous les espaces blancs de début (mais pas d'espace blanc à l'intérieur de la chaîne) :

regexp_replace(eventdate, '^\s+', '')

^ .. début de chaîne

Les deux

Pour supprimer les deux , vous pouvez enchaîner les appels de fonction ci-dessus :

regexp_replace(regexp_replace(eventdate, '^\s+', ''), '\s+$', '')

Ou vous pouvez combiner les deux en un seul appel avec deux succursales .
Ajouter 'g' comme 4ème paramètre pour remplacer toutes les correspondances, pas seulement la première :

regexp_replace(eventdate, '^\s+|\s+$', '', 'g')

Mais cela devrait généralement être plus rapide avec substring() :

substring(eventdate, '\S(?:.*\S)*')

\S ... tout sauf espace blanc
(?: re ) ... ensemble de parenthèses non capturantes
.* ... toute chaîne de 0 à n caractères

Ou l'un de ceux-ci :

substring(eventdate, '^\s*(.*\S)')
substring(eventdate, '(\S.*\S)')  -- only works for 2+ printing characters

( re ) ... Capture d'un jeu de parenthèses

Prend effectivement le premier caractère non-espace et tout jusqu'au dernier caractère non-espace si disponible.

Espace ?

Il y a quelques autres caractères apparentés qui ne sont pas classés comme "espaces blancs" dans Unicode - donc non contenus dans la classe de caractères [[:space:]] .

Ceux-ci s'impriment sous forme de glyphes invisibles dans pgAdmin pour moi :"voyelle mongole", "espace de largeur zéro", "sans jointure de largeur zéro", "joindre de largeur zéro":

SELECT E'\u180e', E'\u200B', E'\u200C', E'\u200D';

'᠎' | '​' | '‌' | '‍'

Deux autres, impression visible glyphes dans pgAdmin, mais invisibles dans mon navigateur :"word joiner", "zero width inbreaking space":

SELECT E'\u2060', E'\uFEFF';
'⁠' | ''

En fin de compte, le fait que les caractères soient rendus invisibles ou non dépend également de la police utilisée pour l'affichage.

Pour supprimer tous ces éléments remplacez également '\s' avec '[\s\u180e\u200B\u200C\u200D\u2060\uFEFF]' ou '[\s᠎​‌‍⁠]' (notez les caractères invisibles à la fin !).
Exemple, au lieu de :

regexp_replace(eventdate, '\s+$', '')

utiliser :

regexp_replace(eventdate, '[\s\u180e\u200B\u200C\u200D\u2060\uFEFF]+$', '')

ou :

regexp_replace(eventdate, '[\s᠎​‌‍⁠]+$', '')  -- note invisible characters

Limites

Il existe également la classe de caractères Posix [[:graph:]] censé représenter des "caractères visibles". Exemple :

substring(eventdate, '([[:graph:]].*[[:graph:]])')

Cela fonctionne de manière fiable pour les caractères ASCII dans chaque configuration (où cela se résume à [\x21-\x7E] ), mais au-delà de cela, vous dépendez actuellement (incl. pg 10) des informations fournies par le système d'exploitation sous-jacent (pour définir ctype ) et éventuellement les paramètres régionaux.

À proprement parler, c'est le cas pour tous référence à une classe de caractères, mais il semble y avoir plus de désaccord avec les moins couramment utilisés comme graph . Mais vous devrez peut-être ajouter plus de caractères à la classe de caractères [[:space:]] (raccourci \s ) pour capturer tous les caractères d'espacement. Comme :\u2007 , \u202f et \u00a0 semblent également manquer pour @XiCoN JFS.

Le manuel :

Dans une expression entre parenthèses, le nom d'une classe de caractères entre [: et :] représente la liste de tous les caractères appartenant à cette classe. Les noms de classe de caractères standard sont :alnum , alpha , blank , cntrl ,digit , graph , lower , print , punct , space , upper , xdigit .Ceux-ci représentent les classes de caractères définies dans ctype.Une locale peut en fournir d'autres.

J'insiste sur moi.

Notez également cette limitation qui a été corrigée avec Postgres 10 :

Correction de la gestion des classes de caractères des expressions régulières pour les grands codes de caractères, en particulier les caractères Unicode au-dessus de U+7FF (Tom Lane)

Auparavant, ces caractères n'étaient jamais reconnus comme appartenant à des classes de caractères dépendantes des paramètres régionaux telles que [[:alpha:]] .