postgresql--与字符串相关的函数和操作符
楔子
我们在筛选数据的时候,很多时候要对字符串进行一些处理,下面来看看postgresql支持哪些字符串的操作吧
数据集如下
select * from t;
支持字符串操作的函数或者操作符
||
将多个字符串进行拼接
-- 需要注意的是,在pgsql中,所有的字符串都必须用单引号,双引号的话会被解释为字段 -- 为什么这么设计,是因为在pgsql中存在着大小写的问题,不管你查询的时候字段是大写还是小写,pgsql都会给你转成小写 -- 可如果这个时候表中的字段是大写的话,那么就会报出字段不存在的错误,因为pgsql给你转换成了小写 -- 解决的办法就是给查询的字段加上双引号,这个时候就不会给你转成小写了 -- 因此需要注意,双引号表示字段,单引号表示字符串 select 'my' || ' name' || ' is' || ' satori'; /* my name is satori */ -- 输出结果如上,另外在输出的时候,我就不写字段名了 -- 我们看到自动把所有的字符串都拼接起来了 select 'my' || ' age' || ' is ' || 16; /* my age is 16 */ -- 我们看到,即便出现了数字,也会隐式的将数字转化为字符串 -- 因此16会被转化为'16' -- 下面这句sql会输出什么呢? select 15 || 16; -- 很不幸,这是会报错的,会提示: "错误: 操作符不存在: integer || integer 建议:没有匹配指定名称和参数类型的操作符. 您也许需要增加明确的类型转换." -- 如果是||,两边不能全部都为数字,否则会报错 -- 对于||来说,pgsql要求||两边至少有一个元素要是字符串格式 select '1' || 2 || 3 || 4; /* 1234 */ -- 此时转化成功了,这是为什么呢? -- 我们刚才说||要求两边不能全部是数字啊。 -- 这是因为多个||是按照从左到右的顺序进行拼接的 -- 对于第一个||,左边是字符串'1',那么也会把2转化为'2',得到的结果就是'12' -- 对于第二个||,进行拼接的时候,左边的内容已经不是数字2了,而是变成了字符串'12',所以会把3变成'3',得到的结果就是'123' -- 同理对于第三个||也是如此,因此最后结果是'1234' select '1' + '2'; -- 这种操作也是不行的,因为+这种操作符是适用于整型、浮点型的 -- 因此上面的结果是不会进行拼接的,拼接需要使用||,或者后面介绍的concat select '1'::int + '2'::int; /* 3 */ -- 我们如果是想当成数字运算的话,需要进行转换,在pgsql中,转换的方式可以使用 column::type、'xxx'::type -- 另外如果含有NULL,那么得到的结果也是NULL select 'a' || 'b' || null; /* NULL */
concat
将多个字符串进行拼接
select concat('my', ' name', ' is', ' satori'); /* my name is satori */ -- concat是一个函数,用于将多个字符拼接起来 -- 那么它和之间介绍的||之间有什么区别呢? select concat(1, 2, 3, 4); /* my name is satori */ -- 因此看到区别了吧,对于concat来说,即使出现了数字也无所谓,会统统转成字符串 select concat('a', 'b', null); /* ab */ -- 如果含有NULL值,那么NULL会被忽略掉,这也是和||操作符之间的一个区别
bit_length
查看一个字符串占多少位
select bit_length('a'); /* 8 */ -- 一个英文字符或者数字占一个字节,8位 select bit_length('爱'); /* 24 */ -- 汉字,则是3字节 select bit_length('爱a1'); /* 40 */ -- 组合起来,依旧是汉字占3个字节,英文字符占1个字节
octet_length
查看一个字符串占多少个字节
select octet_length('a'); /* 1 */ select octet_length('灰原哀123'); /* 12 */ -- 汉字占3个,数字占1个
char_length
查看一个字符串的长度,注意是长度
select char_length('灰原ai'); /* 4 */ -- char_length是计算字符长度的,个人觉得这个比bit_length和octet_length要常用很多
lower、upper
将一个字符串转成小写、大写
select lower('My Lover'), upper('My Lover'); /* my lover MY LOVER */
initcap
将字符串中单词的首字母大写,其余转成小写
select initcap('my NamE iS SATORI'); /* My Name Is Satori */
substring
提取字符串的指定部分
select substring('hello', 1, 3); /* hel */ -- substring(str, start, count) -- 表示从第start个字符串开始取,取count个。注意:第几个,是从1开始的,不是0 -- 所以substring('hello', 1, 3),表示从第1个字符h开始取,取3个,所以是hel -- 另外这个substring还支持正则,这个正则我们后面介绍 select substring('hello', 2); /* ello */ -- 不指定取多少个,默认取到结尾
position
查找字符串中的某个子串的位置
select position('at' in 'satori'); /* 2 */ -- 注意结果是2,说明索引从1开始,a是第2个 select position('xxx' in 'satori'); /* 0 */ -- 不存在话返回0 -- 提取出hello the cruel world中的cruel world,不允许使用数数的方式 select substring('hello the cruel world', position('cruel' in 'hello the cruel world')) /* cruel world */ -- 两者就结合起来了
overlay
替换指定位置的字符串
select overlay('abcdef' placing '嘎嘎嘎' from 2 for 4); /* a嘎嘎嘎f */ -- 表示把字符串'abcdef'的第2个字符开始的后4个字符替换为'嘎嘎嘎' -- from 2表示从第2个字符开始,这里是b,for 4表示数4个,所以from 2 for 4表示的就是bcde -- 然后placing为'嘎嘎嘎',我们发现我们要换4个,但是却传入了3个字符,但是不影响 -- 比如我们想把第2个开始的字符之后的4个字符删掉就可以这么做 select overlay('abcdef' placing '' from 2 for 4); /* af */ select overlay('abcdef' placing 'xxxxxxxxxxxxxxxxxxx' from 2 for 4); /* axxxxxxxxxxxxxxxxxxxf */ -- 即使传入的字符个数比要替换的字符个数多,也不影响 select overlay('abcdef' placing '嘎嘎嘎' from 2); /* a嘎嘎嘎ef */ -- 如果不指定for,也就是不指定替换几个,那么传入的替换字符有几个,就替换几个 -- 我们从第2个开始,而我们传入的'嘎嘎嘎'有三个字符,所以替换3个 -- 操作一波,将字符串'hello cruel world'中间的cruel换成beautiful select overlay('hello cruel world' placing 'beautiful' from position('cruel' in 'hello cruel world') for char_length('cruel')) /* hello beautiful world */
replace
替换指定的字符串
select replace('aabbccddcceec', 'cc', '哈哈') /* aabb哈哈dd哈哈eec */ -- 将所有的'cc'换成'哈哈'
trim
从字符串的开头/结尾/两端开始将字符删掉,类似于python中的strip
select trim(leading 'abc' from 'abcdefg'); /* defg */ -- 从字符串'abcdefg'的左边开始一个字符一个字符的遍历,只要在'abc'当中,那么就剥掉 -- 遇见一个不在的,那么就立即停止 select trim(trailing 'eg' from 'abcdefg'); /* abcdef */ -- 从右边开始,g在'eg'里面,剥掉,f不在,所以停止 select trim(both 'abceg' from 'abcdefg'); /* def */ -- 不用想了,从两端开始
ascii
返回字符串中第一个字符的ASCII码
select ascii('gaga'); /* 103 */ select ascii('g'); /* 103 */ -- 返回参数的第一个字符的ASCII码 select ascii('嘎嘎嘎'); /* 22030 */
chr
将一个ascii码转成对应的字符
select chr(97); /* a */ select ascii('嘎'); /* 22030 */ select chr(22030); /* 嘎 */
concat_ws
将多个字符用指定的分隔符拼接起来
select concat('a', 'b', 'c'); /* abc */ select concat_ws('--', 'a', 'b', 'c'); /* a--b--c */
left
返回字符串的前n个字符
select left('satori', 3); /* sat */ -- 返回前3个字符 select left('satori', 30); /* satori */ -- 指定的个数超过了字符总个数,返回全部 select left('satori', -2); /* sato */ -- 如果指定个数n小于0,那么返回除了最后abs(n)个之外的所有字符 -- 这里是-2,返回最后两个之外的所有字符 select left('satori', -20) = ''; /* t */ -- 显然这里就为空字符串了
right
返回字符串的后n个字符
select right('satori', 3); /* ori */ -- 返回后3个字符 select right('satori', 30); /* satori */ -- 指定的个数超过了字符总个数,返回全部 select right('satori', -2); /* tori */ -- 如果指定个数n小于0,那么返回除了最前abs(n)个之外的所有字符 -- 这里是-2,返回最前两个之外的所有字符 select right('satori', -20) = ''; /* t */ -- 显然这里就为空字符串了
lpad
向左填充指定的字符串
select lpad('satori', 10, '0'); /* 0000satori */ -- 填充指定的字符'0',使得原来的字符串的个数达到10 select lpad('satori', 11, '01'); /* 01010satori */ -- 还可以指定一个字符串 select lpad('satori', 3, '01'); /* sat */ -- 原来的字符串有6个,但是我们要填充到3个,所以直接截断 -- 相当于从左往右取3个
rpad
向右填充指定的字符串
select rpad('satori', 10, '0'); /* satori0000 */ select rpad('satori', 11, '01'); /* satori01010 */ select rpad('satori', 3, '01'); /* sat */ -- 我们发现对于rpad,如果指定的长度比原来的字符串的长度小 -- 那么依旧是从左开始取
md5
计算一个字符串的hash值
select md5('嘎嘎嘎'); /* 27c75ea642dbd8d310e2903c3df91b84 */
reverse
翻转字符串
select reverse('abc'); /* cba */
repeat
重复字符串
select repeat('abc', 3); /* abcabcabc */
translate
对应字符替换
select translate('satori', 'ar', '12'); /* s1to2i */ -- 'a'会被替换为'1','r'会被替换为'2' select translate('satori', 'ari', '12'); /* s1to2 */ -- ari比12长,但是a依旧对应1,r对应2,i则对应空字符串
format
类似于C语言中的printf,可以格式化打印
select format('name is %s, age is %s', 'satori', 16); /* name is satori, age is 16 */ -- 这里数字也要使用%s,输出百分号则是%% select age from t limit 5; /* 44 54 45 39 46 */ select format('age is %s', age) from t limit 5; /* age is 44 age is 54 age is 45 age is 39 age is 46 */ -- 即便我们从表中筛选字段的时候,也是可以用的 -- 会将表中的每一个字段都进行format -- 不仅仅是format,concat、||等基本上任何函数都支持 -- 如果是表的字段,那么会将字段中的每一个记录都会进行相同的操作 select age || '岁' from t limit 5; /* 44岁 54岁 45岁 39岁 46岁 */ --format还支持其他的操作 select format('|%8s|', 'haha'); /* | haha| */ -- %8s表示替换之后,要占满8位,不够的话,用空字符在左边填充 select format('|%-8s|', 'haha'); /* |haha | */ -- %-8s,和%8s类似,只不过是在右边填充空字符 select format('|%3s|', 'hahaha'); /* |hahaha| */ -- 如果不够的话也不影响,不会影响后面的字符 -- %3s表示要填满3位,但是'hahaha'有6个字符,但是不影响,不会截断