pst*_*ton 3 regex postgresql postgresql-9.0 set-returning-functions
我试图在PostgreSQL 9.0.1中进行稍微复杂的字符串转换.值中my_col的长字符串格式为:
'12345_sometext_X12B_1'
'12345_sometext_optionaltext_Y09B_1'
'12345_sometext_optionaltext_X12A_1'
Run Code Online (Sandbox Code Playgroud)
我需要将'X12'部分转换为已知的数值,有几个不同的已知值(最多5个).
我希望能够在一个查询中确定这一点,而不需要子查询.但是,以下内容对我不起作用.最后一列是抛出异常的那一列.CASE由于某种原因,我似乎无法使用这些函数的输出结合语句.我列出了进行中的列仅用于演示目的.
select
regexp_matches(my_col, E'^.*_([^_]*)[A-Z]{1}_\\d*$'), -- returns {'X12'}
(regexp_matches(my_col, E'^.*_([^_]*)[A-Z]{1}_\\d*$'))[1], -- returns 'X12'
case (regexp_matches(my_col, E'^.*_([^_]*)[A-Z]{1}_\\d*$'))[1]
when 'X12' then '1200'
when 'Y09' then '950'
else '?' end -- should return '1200' but throws error
from my_table;
Run Code Online (Sandbox Code Playgroud)
相反,我收到错误:
ERROR: set-valued function called in context that cannot accept a set
SQL state: 0A000
Run Code Online (Sandbox Code Playgroud)
有人可以告诉我吗?
鉴于数据:
create table my_table(my_col text);
insert into my_table(my_col) values
('12345_sometext_X12B_1'),
('12345_sometext_optionaltext_Y09B_1'),
('12345_sometext_optionaltext_X12A_1'),
('nomatch');
Run Code Online (Sandbox Code Playgroud)
上述查询确实会产生您报告的错误.非常奇怪,因为:
SELECT pg_typeof((regexp_matches(my_col, E'^.*_([^_]*)[A-Z]{1}_\\d*$'))[1]);
Run Code Online (Sandbox Code Playgroud)
返回'文字'.它应该说,setof text但这是陷阱:regex_matches是一个集合返回功能.当在PostgreSQL中的FROM子句之外调用时,那些...有趣...行为.
从模式匹配:
regexp_matches函数返回由匹配POSIX正则表达式模式产生的所有捕获的子字符串的文本数组.它具有语法regexp_matches(string,pattern [,flags]).该函数不能返回任何行,一行或多行
尝试重新构造查询以使用子查询来调用SRF.如果匹配器返回多行,则会失败:
SELECT
CASE (SELECT x[1] FROM regexp_matches(my_col, E'^.*_([^_]*)[A-Z]{1}_\\d*$') x)
WHEN 'X12' THEN '1200'
WHEN 'Y09' THEN '950'
ELSE '?'
END
FROM my_table;
Run Code Online (Sandbox Code Playgroud)
想看看SELECT中有多奇怪的SRF在Pg中?比较这些查询的结果:
SELECT generate_series(1,10), generate_series(1,15);
Run Code Online (Sandbox Code Playgroud)
和:
SELECT generate_series(1,10), generate_series(1,20);
Run Code Online (Sandbox Code Playgroud)
1号产生30排.第二个产生20.有趣解释原因.如果偶尔有用的结果,Pg中SELECT列表中的多个SRF会产生疯狂.
LATERAL由于Tom Lane提供了一个理智且定义明确的替代方案,PostgreSQL 9.3支持SQL标准子句.