最近整理一份oracle常用函数清单的时候发现其经常用来去除字符串空格的三个函数,也就是trim()、ltrim()、rtrim(),看起来简简单单,其实大有玄机。以下见解来自网络,但内容经由博主撰写并验证,尽量确保准确无误。
trim()、ltrim()、rtrim()三个函数有两个作用,分别是:
一、去除字符串前后空格(基本用法)
trim(string):去除指定字符串string的左右空格,当然,string中间有空格的时候是不会被去除的
SELECT trim(' aaa bbb ccc ') trim FROM dual;
TRIM
-------
aaa bbb ccc
ltrim(string)、rtrim(string):分别去除指定字符串string左侧和右侧的空格
SELECT ltrim(' aaa bbb ccc ') ltrim FROM dual;
LTRIM
---------
aaa bbb ccc (注意,此时返回的字符串右侧是有空格的)
SELECT rtrim(' aaa bbb ccc ') rtrim FROM dual;
RTRIM
---------
aaa bbb ccc(显然此时返回的字符串左侧是有空格的)
病灶时间:字符串左右的空格真的可以全部都去掉吗?不见得。如果你的字符串两侧带有全角空格,你就会惊奇的发现,全角空格完全去不掉!包括Java中trim()方法,对于字符串前后的全角空格也是无能为力。
将输入法切换到中文输入法,并且在打空格的时候使用全角,你就会发现,原来去空格不是我们想的那样简单,并不是见着字符串左右的空白都能用这三个方法简单的去掉。至于原因,推测应该与字符编码集有关,全角空格是占两个字节,即 2 bytes,而半角空格是只占一个字节,这意味着他们使用的并不是同一个编码集。而这三个函数,包括Java中的trim()方法,可能只是简单的根据ASCII中的“空格”编码来左右删除空格。(以上推测部分未经严格验证,有兴趣的朋友可以验证一下告诉我一声)
那么如果真的在字符串中遇到了全角空格,有办法去除掉吗?有的,待会就讲。
二、去除字符串左右 / 中指定字符(进阶用法)
去除空格仅仅是这三个函数的“默认行为”,事实上,这三个函数还可以接收其他的参数来完成在指定字符串左右 / 中去除字符。
trim( leading | trailing | both string1 FROM string2):从string2中去除左侧 | 右侧 | 左侧两侧(默认是both,即左右侧都去掉)的string1字符,注意,string1只能是单个字符。
SELECT trim(leading ' ' from ' aaa bbb ccc ') leadingtrim FROM dual;
LEADINGTRIM
---------------------
aaa bbb ccc (注意,此时返回的字符串右侧是有空格的)
SELECT trim(trailing ' ' from ' aaa bbb ccc ') trailingtrim FROM dual;
TRAILINGTRIM
---------------------
aaa bbb ccc(显然,此时返回的字符串左侧是有空格的)
SELECT trim(both ' ' from ' aaa bbb ccc ') bothtrim FROM dual;
BOTHTRIM
----------------
aaa bbb ccc(返回的字符串两侧的空格都被去掉)
(注意,以上三个示例中,如果都是要完成“去空格”的话,可以简写成 trim( leading | trailing | both FROM string),即省略空格。)
前面介绍的全角空格不能去除的问题,在这里就可以得到解决了,即将string1也写成全角空格,这样,我们就是”从string2这个左右带全角空格的字符串中将左右的全角空格去掉”了。你看,so EZ。
ltrim(string1,string2),rtrim(string1,string2):从字符串string1左侧(右侧)开始去除与string2字符集合中单个字符匹配的字符,直到在string1中遇上某个字符,该字符不在string2字符集合中。
这段话读起来有点拗口,但是对于真正理解这两个函数的用法至关重要。oracle中的这两个函数中的第二个参数,可以是多个字符组成的“字符集合”,为什么说是“字符集合”而不是“字符串”(虽然严格意义上讲并没有字符集合这个概念),因为在以string2为基础对string1做字符去除的时候,string2并不是作为一个字符串那样的整体来与string1匹配的,而是单个单个字符的匹配。比如string1='abccba',string2='abc',如果string2作为一个整体来匹配,显然不管是用ltrim还是rtrim函数,对string1操作之后返回的结果应该是'cba',但实际上不是,返回的是一个空串!
SELECT ltrim('abccba','abc') ltrim FROM dual;
LTRIM
--------
(返回的是空串)
SELECT rtrim('abccba','abc') rtrim FROM dual;
RTRIM
--------
(返回的是空串)
而至于“直到在string1中遇上某个字符,该字符不在string2字符集合中”这句话,则是体现ltrim函数和rtrim函数区别的时候。我们在上面两个例子的基础上对string1稍作改动,在string1中加个“x”:
SELECT ltrim('abcxcba','abc') ltrim FROM dual;
LTRIM
--------
xcba(结果并不是只剩一个“x”,而是包括stirng1中“x”以及右侧的字符)
SELECT rtrim('abcxcba','abc') rtrim FROM dual;
RTRIM
--------
abcx(结果并不是只剩一个“x”,而是包括stirng1中“x”以及左侧的字符)
ltrim函数从string1左侧往右读,左侧前三个字符分别在string2中找到了对应的单个字符匹配,所以都被去除掉,读到“x”的时候,没有匹配上,所以从这开始到string1右侧都被保留并返回;相反,rtrim函数从string2右侧往左读,右侧前三个字符分别在string2中找到了对应的单个字符匹配,所以都被去掉,读到“x”的时候,没有匹配上,所以从这开始到string1左侧都被保留并返回。
由此类推,如果string1中左侧(右侧)第一个字符在string2中找不到对应,那么ltrim(rtrim)函数将会把string1字符串完整返回:
SELECT ltrim(' abcxcba','abc') ltrim FROM dual;
LTRIM
--------
abcxcba(string2中并没有空格这个字符串,所以string1带着左侧空格完整返回了)
病灶时间:可能有些朋友在使用trim()、ltrim()、rtrim()这三个函数的进阶用法的时候会出现一个问题,即“我明明指定以空格为条件去除原字符串,为什么返回的是一个空串”,可能的原因是错把“空串”当“空格”。“空串”指的是两个单引号之间什么也没有(即 '' ,看起来跟英文输入法里面一个双引号一样),而“空格”指的是两个单引号之间有个空格(即 ' ',这个看起来就不像英文输入法里面的双引号了)。如果使用的是空串,原字符串会被去的干干净净的!