Пробелы с PostgreSQL
колонки eventDate
, который содержит пробелы. Я пытаюсь удалить их с помощью функции PostgreSQL TRIM()
. Более конкретно, я бегу:
SELECT TRIM(both ' ' from eventDate)
FROM EventDates;
однако конечные пробелы не исчезают. Кроме того, когда я пытаюсь обрезать другой символ с даты (например, число), он также не обрезается. Если я читаю руководство правильно это должно работать. Есть мысли?
3 ответов
есть много различных невидимых символов. Многие из них имеют свойство WSpace=Y
("пробел") в 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
,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. Таким образом, вы захотите удалить их в своем коде.