sql >> Databasteknik >  >> RDS >> PostgreSQL

Trimma efterföljande utrymmen med PostgreSQL

Det finns många olika osynliga karaktärer. Många av dem har egenskapen WSpace=Y ("whitespace") i Unicode. Men vissa specialtecken anses inte vara "whitespace" och har fortfarande ingen synlig representation. De utmärkta Wikipedia-artiklarna om mellanslag (interpunktion) och blanksteg bör ge dig en idé.

Unicode suger i detta avseende:att introducera massor av exotiska karaktärer som främst tjänar till att förvirra människor.

Standard SQL trim() funktionen trimmar som standard bara det grundläggande latinska mellanslagstecknet (Unicode:U+0020 / ASCII 32). Samma med rtrim() och ltrim() varianter. Ditt samtal riktar sig också bara till just den karaktären.

Använd reguljära uttryck med regexp_replace() istället.

Slutande

För att ta bort alla efterföljande vita utrymmen (men inte vitt utrymme inuti strängen):

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

Det reguljära uttrycket förklarade:
\s ... reguljärt uttryck klass förkortning för [[:space:]]
    - som är uppsättningen av blanksteg - se begränsningar nedan
+ ... 1 eller fler på varandra följande matchningar
$ ... slutet av strängen

Demo:

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

Returnerar:

inner white|

Ja, det är en singel omvänt snedstreck (\ ). Detaljer i detta relaterade svar:

  • SQL välj var kolumnen börjar med \

Ledande

För att ta bort alla ledande blanksteg (men inte vitt utrymme inuti strängen):

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

^ .. början av strängen

Båda

För att ta bort båda , kan du koppla ovanstående funktionsanrop:

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

Eller så kan du kombinera båda i ett enda samtal med två filialer .
Lägg till 'g' som fjärde parameter för att ersätta alla matchningar, inte bara den första:

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

Men det borde vanligtvis vara snabbare med substring() :

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

\S ... allt utom vitt utrymme
(?: re ) ... icke-fångande uppsättning parenteser
.* ... valfri sträng med 0-n tecken

Eller någon av dessa:

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

( re ) ... Fångar uppsättning parenteser

Tar effektivt det första tecknet utan blanksteg och allt upp till det sista tecknet som inte är blanksteg om tillgängligt.

Whitespace?

Det finns några fler relaterade tecken som inte klassificeras som "blanksteg" i Unicode - så ingår inte i teckenklassen [[:space:]] .

Dessa skrivs ut som osynliga glyfer i pgAdmin för mig:"mongolisk vokal", "noll bredd mellanrum", "noll bredd icke-fogare", "noll bredd sammanfogning":

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

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

Två till, skriv ut som synliga glyfer i pgAdmin, men osynliga i min webbläsare:"word joiner", "noll width non-breaking space":

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

I slutändan, om tecken görs osynliga eller inte beror också på vilket teckensnitt som används för visning.

För att ta bort alla dessa ersätt även '\s' med '[\s\u180e\u200B\u200C\u200D\u2060\uFEFF]' eller '[\s᠎​‌‍⁠]' (observera efterföljande osynliga tecken!).
Exempel istället för:

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

använd:

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

eller:

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

Begränsningar

Det finns också Posix-teckenklassen [[:graph:]] ska representera "synliga tecken". Exempel:

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

Det fungerar tillförlitligt för ASCII-tecken i alla inställningar (där det kokar ner till [\x21-\x7E] ), men utöver det är du för närvarande (inkl. s. 10) beroende av information från det underliggande operativsystemet (för att definiera ctype ) och eventuellt språkinställningar.

Strängt taget är det fallet för alla hänvisning till en teckenklass, men det verkar finnas mer oenighet med de mindre vanligt använda som graf . Men du kanske måste lägga till fler tecken i teckenklassen [[:space:]] (shorthand \s ) för att fånga alla blanksteg. Gilla:\u2007 , \u202f och \u00a0 verkar också saknas för @XiCoN JFS.

Manualen:

Inom en hakparentes, namnet på en teckenklass innesluten i[: och :] står för listan över alla karaktärer som tillhör den klassen. Standardteckenklassnamn är:alnum , alpha , blank , cntrl ,digit , graph , lower , print , punct , space , upper , xdigit .Dessa står för teckenklasserna som definieras i ctype. En lokal kan tillhandahålla andra.

Djärv betoning min.

Notera också denna begränsning som fixades med Postgres 10:

Fixa reguljära uttrycks teckenklasshantering för stora teckenkoder, särskilt Unicode-tecken ovanför U+7FF (Tom Lane)

Tidigare kändes sådana tecken aldrig igen som tillhörande lokalt beroende teckenklasser som [[:alpha:]] .



  1. Beräkna tidsskillnaden mellan två rader

  2. Användbara frågor om oracle EBS lösenords utgång/policy/inställningar

  3. 2 sätt att få de teckenuppsättningar som finns tillgängliga i MariaDB

  4. org.postgresql.util.PSQLEUndantag:FATAL:ledsen, för många klienter redan