【发布时间】:2018-11-26 20:42:26
【问题描述】:
我在 stackoverflow 上找到了一种使用 ROW 值处理多变量 case 语句的巧妙方法。它看起来多么干净真是太棒了......
但是,直接将由 text 类型的 2 个表列组成的行值与由字符串文字组成的行进行比较时出现错误。
我使用了函数spTup('Deposit', '' ) 的变通方法,它可以工作但可能会更慢。另一种可行的方法是将字符串文字显式转换为text,但这会造成很多视觉混乱。
问题:
- 为什么 Postgres 不能推断应该处理字符串文字
如
text类型? - 为什么 Postgres 可以在单个元素行中推断字符串文字的类型,但不能在具有 2 个元素的行中推断出字符串字面量的类型?
- 我以为我掌握了 Postgres 类型处理的句柄,但我不太明白这种情况,谁能解释一下?
- 是否有任何其他方法可以最大限度地减少视觉混乱?
我在本地主机上使用 Postgres 10.1,在测试和生产服务器上使用 9.6.6。
测试设置:
create table if not exists tblTest ( SeqID serial, EventType text, EventResult text, Amt decimal );
truncate table tblTest;
insert into tblTest( EventType, EventResult, Amt )
values ( 'Withdrawal', '', 1.11 ), ('Deposit', '', 2.22 ), ('Deposit', 'succeeded', 3.33 ), ('Deposit', 'failed', 4.44 );
create or replace function spTup( p_1 text, p_2 text )
returns record as $func$
select ( p_1, p_2 );
$func$ LANGUAGE sql IMMUTABLE;
-- Runs without error (using single element tuple)
select SeqID, EventType, case ( EventType ) when ( 'Deposit' ) then Amt else 9.999 end
from tblTest;
-- ERROR: cannot compare dissimilar column types text and unknown at record column 1
select SeqID, EventType, EventResult, case ( EventType, EventResult )
when ( 'Deposit', '' ) then Amt else 9.999 end
from tblTest;
-- Runs without error -- visually the cleanest apart from using spTup function
select SeqID, EventType, EventResult, case ( EventType, EventResult )::text
when ( 'Deposit', '' )::text then Amt else 9.999 end
from tblTest;
-- Runs without error
select SeqID, EventType, EventResult, case ( EventType, EventResult )
when ( 'Deposit'::text, ''::text ) then Amt else 9.999 end
from tblTest;
select SeqID, EventType, EventResult, case ( EventType, EventResult )
when spTup( 'Deposit', '' ) then Amt else 9.999 end
from tblTest;
-- ERROR: input of anonymous composite types is not implemented
select SeqID, EventType, EventResult, case ( EventType, EventResult )
when '( "Deposit", "" )' then Amt else 9.999 end
from tblTest;
-- Just out of interest
select ( 'Deposit', '' ), ( 'Deposit'::text, ''::text );
/**
row row
(Deposit,"") (Deposit,"")
**/
select SeqID, EventType, EventResult, ( EventType, EventResult )
from tblTest;
/**
seqid eventtype eventresult row
1 Withdrawal (Withdrawal,"")
2 Deposit (Deposit,"")
3 Deposit succeeded (Deposit,succeeded)
4 Deposit failed (Deposit,failed)
**/
【问题讨论】:
标签: postgresql casting case