Пробелы с PostgreSQL

колонки eventDate, который содержит пробелы. Я пытаюсь удалить их с помощью функции PostgreSQL TRIM(). Более конкретно, я бегу:

SELECT TRIM(both ' ' from eventDate) 
FROM EventDates;

однако конечные пробелы не исчезают. Кроме того, когда я пытаюсь обрезать другой символ с даты (например, число), он также не обрезается. Если я читаю руководство правильно это должно работать. Есть мысли?

3 ответов


есть много различных невидимых символов. Многие из них имеют свойство WSpace=Y ("пробел") в Unicode. Но некоторые специальные символы не считаются "пробелами" и до сих пор не имеют видимого представления. Отличные статьи Википедии о пробел (знаки препинания) и пробельные символы должно дать вам представление.

Unicode отстой в этом отношении: введение множества экзотических символов, которые в основном служат запутать людей.

стандартный SQL trim() функции по умолчанию только обрезает основной символ латинского пробела (Unicode: U+0020 / ASCII 32). То же самое с rtrim() и ltrim() вариантов. Ваш вызов также нацелен только на этого конкретного персонажа.

использовать регулярные выражения с regexp_replace().

Trailing

удалить все запаздывающие белый космос!--71--> (но не пробел внутри строка):

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

регулярное выражение, объяснил:
\s .. класс регулярных выражений стенография для [[:space:]]
     - который является набором символов пробела-см. Ограничения ниже
+ .. 1 или более последовательных матчей
$ .. конец строка

Demo:

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

возвращает:

inner white|

Да, это один обратная косая черта (\). Подробности в этом ответе.

ведущий

удалить все ведущие пробелы (но не пробел внутри строки):

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)')

(re) .. захват скобки

эффективно принимает первый символ без пробелов и все до последнего символа без пробелов, если доступный.

пробелы?

есть еще несколько связанные символы, которые не классифицируются как "пробелы" в Unicode - так не содержится в классе символов [[:space:]].

эти печатают как невидимые глифы в pgAdmin для меня: "монгольская гласная", "нулевое пространство ширины", "нулевая ширина не столяр", "нулевая ширина столяр":

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

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

еще два, печать как видимого глифы в pgAdmin, но невидимые в моем браузер: "word joiner", "нулевая ширина неразрывного пространства":

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]), но помимо этого вы в настоящее время (ВКЛ. pg 10) зависит от информации, предоставляемой базовой ОС (определить ctype) и возможно, настройки локали.

строго говоря, это относится к каждый ссылка на класс символов, но, похоже, больше разногласий с менее часто используемыми, такими как графика. Но вам может потребоваться добавить больше символов в класс символов [[:space:]] (стенография \s), чтобы поймать все пробелы. как: \u2007, \u202f и \u00a0 кажется, также отсутствует для @XiCoN JFS.

инструкции:

в скобочном выражении имя класса символов, заключенного в [: и :] означает список всех символов, принадлежащих к этому класс. Стандартные имена классов символов:alnum, alpha, blank, cntrl, digit, graph, lower, print, punct, space, upper, xdigit. Эти стенд для классы символов, определенные в ctype. Ля язык может предоставить другим.

жирным выделено мной.

также обратите внимание на это ограничение, которое было исправлено с помощью Postgres 10:

исправлена обработка класса символов регулярных выражений для больших символов коды, особенно символы Юникода выше U+7FF (Том Лэйн)

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


Он должен работать так, как вы его обрабатываете, но трудно сказать, не зная конкретной строки.

Если вы только обрезаете ведущие пробелы, вы можете использовать более краткую форму:

SELECT RTRIM(eventDate) 
FROM EventDates;

Это маленький тест чтобы показать вам, что это работает. Скажи нам, если получится!


если ваш пробел больше, чем просто space meta значение, чем вам нужно будет использовать regexp_replace:

 SELECT '(' || REGEXP_REPLACE(eventDate, E'[[:space:]]', '', 'g') || ')' 
 FROM EventDates;

в приведенном выше примере я ограничиваю возвращаемое значение в ( и ) просто так вы можете легко посмотреть что regex replace работает в приглашении psql. Таким образом, вы захотите удалить их в своем коде.