CASE with regexp:“在上下文中调用的集值函数,不能接受集合”

我试图在PostgreSQL 9.0.1中进行稍微复杂的字符串转换. my_col中的值是长字符串,格式为:

'12345_sometext_X12B_1'
'12345_sometext_optionaltext_Y09B_1'
'12345_sometext_optionaltext_X12A_1'

我需要将’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;

相反,我收到错误:

ERROR: set-valued function called in context that cannot accept a set
SQL state: 0A000

有人可以告诉我吗?

最佳答案
鉴于数据:

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');

上述查询确实会产生您报告的错误.非常奇怪,因为:

SELECT pg_typeof((regexp_matches(my_col, E'^.*_([^_]*)[A-Z]{1}_\\d*$'))[1]);

返回’文字’.它应该真的说setof文本,这就是陷阱:regex_matches是一个集合返回函数.当在PostgreSQL中的FROM子句之外调用时,那些…有趣…行为.

pattern matching开始:

The regexp_matches function returns a text array of all of the
captured substrings resulting from matching a POSIX regular expression
pattern. It has the syntax regexp_matches(string, pattern [, flags ]).
The function can return no rows, one row, or multiple rows

尝试重新构造查询以使用子查询来调用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;

想看看SELECT中有多奇怪的SRF在Pg中?比较这些查询的结果:

SELECT generate_series(1,10), generate_series(1,15);

和:

SELECT generate_series(1,10), generate_series(1,20);

1号产生30排.第二个产生20.有趣解释原因.如果偶尔有用的结果,Pg中SELECT列表中的多个SRF会产生疯狂.

由于Tom Lane,PostgreSQL 9.3支持SQL标准的LATERAL子句,它为当前行为提供了一个理智且定义明确的替代方案.

转载注明原文:CASE with regexp:“在上下文中调用的集值函数,不能接受集合” - 代码日志