PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Изрежете крайните интервали с PostgreSQL

Има много различни невидими герои. Много от тях имат свойството WSpace=Y („прабел“) в Unicode. Но някои специални знаци не се считат за "прабел" и все още нямат видимо представяне. Отличните статии в Уикипедия за интервал (пунктуация) и бели символи трябва да ви дадат представа.

Unicode е гадно в това отношение:въвеждането на много екзотични знаци, които основно служат за объркване на хората.

Стандартният SQL trim() функцията по подразбиране отрязва само основния символ на латински интервал (Unicode:U+0020 / ASCII 32). Същото с rtrim() и ltrim() варианти. Вашето обаждане също е насочено само към този конкретен знак.

Използвайте регулярни изрази с regexp_replace() вместо това.

Завършване

За да премахнете всички крайни бели интервали (но не и бяло пространство вътре низа):

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

Регулярният израз е обяснен:
\s ... съкращаване на класа на регулярни изрази за [[:space:]]
    - което е набор от знаци за интервал - вижте ограниченията по-долу
+ ... 1 или повече последователни съвпадения
$ ... край на низ

Демо:

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

Връща:

inner white|

Да, това е единично обратна наклонена черта (\ ). Подробности в този свързан отговор:

  • SQL изберете къде колоната започва с \

Водеща

За да премахнете всички водещи бели интервали (но не празно пространство вътре в низа):

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

^ .. начало на низ

И двете

За да премахнете и двете , можете да верижите по-горе извиквания на функции:

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

Или можете да комбинирате и двете в едно обаждане с два клона .
Добавете 'g' като 4-ти параметър за замяна на всички съвпадения, а не само на първия:

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

Но това обикновено трябва да е по-бързо с substring() :

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

\S ... всичко освен бяло пространство
(?: re ) ... неулавящ набор от скоби
.* ... всеки низ от 0-n знака

Или едно от тези:

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

( re ) ... Заснемане на набор от скоби

Ефективно приема първия знак без интервал и всичко до последния знак без интервал, ако е наличен.

Пространство?

Има още няколко свързани знака, които не са класифицирани като "бели интервали" в Unicode - така че не се съдържат в символния клас [[:space:]] .

Те се отпечатват като невидими глифове в pgAdmin за мен:"монголска гласна", "пространство с нула ширина", "несъединяване с нулева ширина", "дограма с нула ширина":

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

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

Още две, отпечатване като видимо глифове в pgAdmin, но невидими в моя браузър:"word joiner", "zero width non-breaking space":

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

В крайна сметка, дали знаците ще бъдат изобразени невидими или не, също зависи от шрифта, използван за показване.

За да премахнетевсички тези също така заменете '\s' с '[\s\u180e\u200B\u200C\u200D\u2060\uFEFF]' или '[\s᠎​‌‍⁠]' (обърнете внимание на невидимите знаци в края!).
Пример, вместо:

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

използвайте:

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

или:

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

Ограничения

Съществува и класът на символите Posix [[:graph:]] трябва да представлява "видими знаци". Пример:

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

Работи надеждно за ASCII знаци във всяка настройка (където се свежда до [\x21-\x7E] ), но освен това в момента (вкл. стр. 10) зависи от информацията, предоставена от основната ОС (за да дефинирате ctype ) и евентуално локални настройки.

Строго погледнато, това е така за всеки препратка към клас символи, но изглежда има повече несъгласия с по-рядко използваните, като графика . Но може да се наложи да добавите още знаци към класа от знаци [[:space:]] (съкратено \s ), за да улови всички символи за интервал. Харесайте:\u2007 , \u202f и \u00a0 изглежда липсва и за @XiCoN JFS.

Ръководството:

В рамките на израз в скоби, името на клас от знаци, затворен в[: и :] означава списък на всички знаци, принадлежащи към този клас. Стандартните имена на класове на знаци са:alnum , alpha , blank , cntrl ,digit , graph , lower , print , punct , space , upper , xdigit .Те означават символните класове, дефинирани в ctype. Локалът може да предостави други.

Удебелен акцент мой.

Също така имайте предвид това ограничение, което беше коригирано с Postgres 10:

Коригирайте обработката на класовете на знаците на регулярните изрази за големи кодове на знаци, особено Unicode знаци над U+7FF (Том Лейн)

Преди това такива знаци никога не са били разпознавани като принадлежащи на зависими от локал класове знаци, като [[:alpha:]] .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PostgreSQL срещу версии на ядрото на Linux

  2. Функцията low() за международни знаци в postgresql

  3. Открийте дали редът е актуализиран или вмъкнат

  4. Heroku pg:pull неуспешно попълване на схемата

  5. Rails:PG::UndefinedTable:ГРЕШКА:релация ... не съществува