sql >> Databáze >  >> RDS >> PostgreSQL

Ořízněte koncové mezery pomocí PostgreSQL

Existuje mnoho různých neviditelných postav. Mnoho z nich má vlastnost WSpace=Y ("mezera") v Unicode. Některé speciální znaky však nejsou považovány za „prázdné znaky“ a stále nemají žádnou viditelnou reprezentaci. Vynikající články Wikipedie o mezerách (interpunkci) a mezerách by vám měly poskytnout představu.

Unicode je v tomto ohledu na hovno:představuje spoustu exotických znaků, které slouží hlavně k matení lidí.

Standardní SQL trim() funkce ve výchozím nastavení ořízne pouze základní latinský znak mezery (Unicode:U+0020 / ASCII 32). Totéž s rtrim() a ltrim() varianty. Váš hovor také míří pouze na tuto konkrétní postavu.

Použijte regulární výrazy s regexp_replace() místo toho.

Trailing

Chcete-li odstranit všechna koncová bílá místa (ale ne prázdné místo uvnitř řetězec):

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

Regulární výraz vysvětluje:
\s ... zkratka třídy regulárních výrazů pro [[:space:]]
    – což je sada mezer mezi znaky – viz omezení níže
+ ... 1 nebo více po sobě jdoucích shod
$ ... konec řetězce

Demo:

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

Vrátí:

inner white|

Ano, to je single zpětné lomítko (\ ). Podrobnosti v této související odpovědi:

  • SQL vybere, kde sloupec začíná \

Vedení

Chcete-li odstranit všechna úvodní bílá místa (ale ne prázdné místo uvnitř řetězce):

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

^ .. začátek řetězce

Oba

Chcete-li odebrat obě , můžete zřetězit výše uvedená volání funkcí:

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

Nebo můžete obojí zkombinovat do jednoho hovoru se dvěma pobočkami .
Přidejte 'g' jako 4. parametr, který nahradí všechny shody, nejen první:

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

Ale to by mělo být obvykle rychlejší s substring() :

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

\S ... všechno ale mezera
(?: re ) ... nezachycující sadu závorek
.* ... libovolný řetězec 0-n znaků

Nebo jeden z těchto:

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

( re ) ... Zachycení sady závorek

Efektivně převezme první znak bez mezer a vše až po poslední znak bez mezer, pokud je k dispozici.

Mezerník?

Existuje několik dalších souvisejících znaků, které nejsou v Unicode klasifikovány jako "prázdné znaky" - takže nejsou obsaženy ve znakové třídě [[:space:]] .

Tyto se pro mě vytisknou jako neviditelné glyfy v pgAdmin:"mongolská samohláska", "mezera s nulovou šířkou", "nepojistka s nulovou šířkou", "spojovač s nulovou šířkou":

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

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

Další dvě, tisknou se jako viditelné piktogramy v pgAdmin, ale neviditelné v mém prohlížeči:"spojovač slov", "mezera s nulovou šířkou":

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

V konečném důsledku to, zda jsou znaky vykresleny jako neviditelné, závisí také na písmu použitém pro zobrazení.

Chcete-li odstranit všechny tyto také nahraďte '\s' s '[\s\u180e\u200B\u200C\u200D\u2060\uFEFF]' nebo '[\s᠎​‌‍⁠]' (všimněte si neviditelných znaků na konci!).
Příklad místo:

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

použití:

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

nebo:

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

Omezení

Existuje také znaková třída Posix [[:graph:]] má představovat „viditelné znaky“. Příklad:

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

Funguje spolehlivě pro znaky ASCII v každém nastavení (kde se scvrkává na [\x21-\x7E] ), ale kromě toho jste v současnosti (včetně str. 10) závislí na informacích poskytovaných základním operačním systémem (pro definování ctype ) a případně nastavení národního prostředí.

Přesně řečeno, to je případ každého odkaz na třídu znaků, ale zdá se, že existuje větší nesouhlas s těmi méně běžně používanými, jako je graf . Možná však budete muset přidat další znaky do znakové třídy [[:space:]] (zkráceně \s ), abyste zachytili všechny mezery. Jako:\u2007 , \u202f a \u00a0 Zdá se, že také chybí pro @XiCoN JFS.

Manuál:

Ve výrazu hranaté závorky název třídy znaků uzavřený v [: a :] znamená seznam všech znaků patřících do této třídy. Standardní názvy tříd znaků jsou:alnum , alpha , blank , cntrl ,digit , graph , lower , print , punct , space , upper , xdigit .Tyto znaky představují třídy znaků definované v ctype. Další může poskytnout národní prostředí.

Tučné zdůraznění moje.

Všimněte si také tohoto omezení, které bylo opraveno s Postgres 10:

Oprava zpracování znakových tříd regulárních výrazů pro velké kódy znaků, zejména znaky Unicode nad U+7FF (Tom Lane)

Dříve takové znaky nebyly nikdy rozpoznány jako znaky patřící do tříd znaků závislých na národním prostředí, jako je [[:alpha:]] .



  1. rs.last() dává Neplatnou operaci pro forward only resultset:last

  2. PHP a MySQL:mysqli_num_rows() očekává, že parametr 1 bude mysqli_result, daný booleovský

  3. Nelze vytvořit instanci chyby poskytovatele OLE DB jako uživatel ověřování systému Windows

  4. GROUP BY v Postgresu – žádná rovnost pro datový typ JSON?