我有一个包含尾随空格的列eventDate
。我试图用PostgreSQL函数TRIM()
删除它们。更具体地说,我正在运行:
SELECT TRIM(both ' ' from eventDate)
FROM EventDates;
但是,尾随空格不会消失。此外,当我尝试修剪日期中的另一个字符(例如数字)时,它也不会修剪。如果我正确地阅读the manual,这应该有效。有什么想法吗?
答案 0 :(得分:60)
有许多不同的隐形字符。其中许多都具有Unicode中的属性WSpace=Y
(“空白”)。但是一些特殊字符不被视为“空白”,仍然没有可见的表示。关于space (punctuation)和whitespace characters的优秀维基百科文章应该会给你一个想法。
< rant> Unicode在这方面很糟糕:引入了许多主要用来混淆人们的异国情调。< / rant>
默认情况下, The standard SQL trim()
function仅修剪基本的拉丁空格字符(Unicode:U + 0020 / ASCII 32)。与rtrim()
and ltrim()
变体相同。您的电话也只针对该特定角色。
使用带regexp_replace()
的正则表达式。
要删除所有尾随空格 (但字符串中没有空格):
SELECT regexp_replace(eventdate, '\s+$', '') FROM eventdates;
正则表达式解释:
\s
.. regular expression class shorthand for [[:space:]]
- 这是一组空格字符 - 请参阅下面的限制
+
..连续1场或多场比赛
$
..字符串结尾
演示:
SELECT regexp_replace('inner white ', '\s+$', '') || '|'
返回:
inner white|
是的,这是一个单个反斜杠(\
)。这个相关答案的细节。
要删除 所有前导空格 (但不是字符串中的空格):
regexp_replace(eventdate, '^\s+', '')
^
..字符串的开头
要删除 两者 ,您可以链接上述函数调用:
regexp_replace(regexp_replace(eventdate, '^\s+', ''), '\s+$', '')
或者您可以在一次通话中将两者branches组合在一起
添加'g'
作为第四个参数来替换所有匹配,而不仅仅是第一个:
regexp_replace(eventdate, '^\s+|\s+$', '', 'g')
通常会更快
substring(eventdate, '\S(?:.*\S)*')
\S
..所有但是空格
(?:
re
)
Non-capturing set of parentheses
.*
..任意0-n字符串
或其中一个:
substring(eventdate, '^\s*(.*\S)')
substring(eventdate, '(\S.*\S)')
(
re
)
.. Capturing set of parentheses
有效地获取第一个非空白字符以及最后一个非空格字符(如果可用)。
还有一些related characters which are not classified as "whitespace" in Unicode - 因此未包含在字符类[[:space:]]
中。
这些在pgAdmin中打印为隐形字形对我来说:“mongolian元音”,“零宽度空间”,“零宽度非连接”,“零宽度连接器”:
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 character class [[:graph:]]
应该代表“可见字符”。例如:
substring(eventdate, '([[:graph:]].*[[:graph:]])')
它可以在每个设置中可靠地处理ASCII字符(归结为[\x21-\x7E]
),但除此之外,您当前(包括第10页)依赖于底层操作系统提供的信息(定义{{1可能是语言环境设置。
严格来说,每个对字符类的引用都是如此,但似乎与不常用的 graph 之间存在更多不同意见。但您可能需要在字符类ctype
(简写[[:space:]]
)中添加更多字符以捕获所有空格字符。 Like: \u2007
, \u202f
and \u00a0
seem to also be missing for @XiCoN JFS
在括号表达式中,括起来的字符类的名称
\s
和[:
代表属于该字符的所有字符的列表 类。标准字符类名称为::]
,alnum
,alpha
,blank
,cntrl
,digit
,graph
,lower
,punct
,space
,upper
。 它们代表ctype中定义的字符类。 区域设置可以提供其他区域。
大胆强调我的。
另请注意此限制为fixed with Postgres 10:
修复大字符的正则表达式字符类处理 代码,尤其是
xdigit
以上的Unicode字符(Tom Lane)以前,这些角色从未被认为属于 依赖于语言环境的字符类,例如
U+7FF
。
答案 1 :(得分:2)
它应该按照你处理它的方式工作,但是在不知道具体字符串的情况下很难说。
如果您只修剪前导空格,则可能需要使用更简洁的形式:
SELECT RTRIM(eventDate)
FROM EventDates;
这是一个little test,向您展示它有效。 告诉我们它是否成功!
答案 2 :(得分:2)
如果您的空白不仅仅是space
元值,那么您需要使用regexp_replace
:
SELECT '(' || REGEXP_REPLACE(eventDate, E'[[:space:]]', '', 'g') || ')'
FROM EventDates;
在上面的例子中,我绑定了(
和)
中的返回值,这样您就可以轻松查看正则表达式替换在psql提示符下工作。因此,您希望删除代码中的内容。
答案 3 :(得分:0)
SELECT replace((' devo system ') ,' ','');
它给出:devosystem
答案 4 :(得分:0)
经过测试,效果很好:
UPDATE company SET name = TRIM (BOTH FROM name) where id > 0