PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Przycinaj końcowe spacje za pomocą PostgreSQL

Istnieje wiele różnych niewidzialnych postaci. Wiele z nich ma właściwość WSpace=Y („białe znaki”) w Unicode. Ale niektóre znaki specjalne nie są uważane za „białe znaki” i nadal nie mają widocznej reprezentacji. Świetne artykuły Wikipedii dotyczące spacji (interpunkcji) i białych znaków powinny dać ci pomysł.

Unicode jest pod tym względem do bani:wprowadzenie wielu egzotycznych znaków, które służą głównie do zmylenia ludzi.

Standardowy SQL trim() funkcja domyślnie przycina tylko podstawowy znak spacji łacińskiej (Unicode:U+0020 / ASCII 32). To samo z rtrim() i ltrim() warianty. Twoje wezwanie jest również kierowane tylko na tę konkretną postać.

Używaj wyrażeń regularnych z regexp_replace() zamiast tego.

Kontynuacja

Aby usunąć wszystkie końcowe białe znaki (ale nie spacja wewnątrz ciąg):

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

Wyjaśnienie wyrażenia regularnego:
\s ... skrót klasy wyrażenia regularnego dla [[:space:]]
    - czyli zestaw znaków odstępu – zobacz ograniczenia poniżej
+ ... 1 lub więcej kolejnych dopasowań
$ ... koniec ciągu

Demo:

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

Zwroty:

inner white|

Tak, to singiel ukośnik odwrotny (\ ). Szczegóły w tej powiązanej odpowiedzi:

  • SQL wybierz, gdzie kolumna zaczyna się od \

Wiodący

Aby usunąć wszystkie wiodące białe znaki (ale nie spacja wewnątrz ciągu):

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

^ .. początek ciągu

Oba

Aby usunąć oba , możesz połączyć powyższe wywołania funkcji:

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

Możesz też połączyć oba w jednym połączeniu z dwoma oddziałami .
Dodaj 'g' jako czwarty parametr zastępujący wszystkie dopasowania, nie tylko pierwszy:

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

Ale zazwyczaj powinno to być szybsze dzięki substring() :

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

\S ... wszystko ale spacja
(?: re ) ... nieprzechwytujący zestaw nawiasów
.* ... dowolny ciąg 0-n znaków

Lub jedno z tych:

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

( re ) ... Przechwytywanie zestawu nawiasów

Skutecznie pobiera pierwszy znak inny niż biały i wszystko aż do ostatniego znaku innego niż biały, jeśli jest dostępny.

białe znaki?

Istnieje kilka innych powiązanych znaków, które nie są klasyfikowane jako "białe znaki" w Unicode - więc nie są zawarte w klasie znaków [[:space:]] .

Dla mnie są one drukowane jako niewidoczne glify w pgAdmin:"mongolska samogłoska", "spacja o zerowej szerokości", "bez łączenia o zerowej szerokości", "łącznik o zerowej szerokości":

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

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

Jeszcze dwa, drukowanie jako widoczne glify w pgAdmin, ale niewidoczne w mojej przeglądarce:"word joiner", "zero szerokości nierozdzielającej spacji":

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

Ostatecznie to, czy znaki są renderowane jako niewidoczne, czy nie, zależy również od czcionki użytej do wyświetlania.

Aby usunąć wszystkie te również zastąp '\s' z '[\s\u180e\u200B\u200C\u200D\u2060\uFEFF]' lub '[\s᠎​‌‍⁠]' (zwróć uwagę na końcowe niewidoczne znaki!).
Przykład zamiast:

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

użyj:

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

lub:

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

Ograniczenia

Istnieje również klasa znaków Posix [[:graph:]] ma reprezentować „widoczne postacie”. Przykład:

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

Działa niezawodnie dla znaków ASCII w każdej konfiguracji (gdzie sprowadza się do [\x21-\x7E] ), ale poza tym obecnie (w tym str. 10) polegasz na informacjach dostarczanych przez bazowy system operacyjny (aby zdefiniować ctype ) i ewentualnie ustawienia regionalne.

Ściśle mówiąc, dotyczy to każdego odniesienie do klasy znaków, ale wydaje się, że istnieje więcej niezgodności z mniej powszechnie używanymi, takimi jak graph . Ale być może będziesz musiał dodać więcej znaków do klasy znaków [[:space:]] (skrót \s ), aby wychwycić wszystkie białe znaki. Na przykład:\u2007 , \u202f i \u00a0 wydaje się, że brakuje również dla @XiCoN JFS.

Instrukcja:

W wyrażeniu nawiasu klamrowego nazwa klasy znaku zawarta w [: i :] oznacza listę wszystkich postaci należących do tej klasy. Standardowe nazwy klas postaci to:alnum , alpha , blank , cntrl ,digit , graph , lower , print , punct , space , upper , xdigit .Oznaczają one klasy znaków zdefiniowane w ctype.Lokale mogą zapewnić inne.

Pogrubiony nacisk na moje.

Zwróć również uwagę na to ograniczenie, które zostało naprawione w Postgres 10:

Napraw obsługę klas znaków wyrażeń regularnych dla dużych kodów znaków, szczególnie znaków Unicode powyżej U+7FF (Tom Lane)

Wcześniej takie znaki nigdy nie były rozpoznawane jako należące do klas znaków zależnych od lokalizacji, takich jak [[: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. Liquibase/PostgreSQL:jak prawidłowo zachować wielkość liter?

  2. Klauzule Care To Know:Wszystko o SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY i LIMIT

  3. Nie znaleziono odpowiedniego sterownika po dołączeniu potrzebnych sterowników do wtyczki maven-assembly-plugin

  4. Postgres:Jak zrobić klucze kompozytowe?

  5. Pobierz dzień z daty w PostgreSQL