我正在使用Firebird 2.5。我跑的时候
SELECT
CASE BILANCA
WHEN 1 THEN
CASE BILANCA WHEN 0 THEN 'SMALLINT' WHEN 1 THEN 'NUME' END
ELSE 'A'||'B' END
AS BILANCA1,
CASE BILANCA
WHEN 1 THEN
CASE BILANCA WHEN 0 THEN 'SMALLINT' WHEN 1 THEN 'NUME' END
ELSE 'AB' END
AS BILANCA2
FROM GS01BILANCA
字段BILANCA2为'NUME '
(NUME后有4个空格),BILANCA1为'NUME'
。添加的空格数等于CASE中最长字符串的长度。
唯一的区别是在BILANCA1中加入字符串:
ELSE 'A'||'B' END
DDL
CREATE TABLE GS01BILANCA
(BILANCA INTEGER DEFAULT 0 NOT NULL,
CONSTRAINT PK_GS01BILANCA PRIMARY KEY (BILANCA));
表有2条记录:
结果是
'NUME '
(NUME后有4个空格),'NUME'
'AB'
,'AB'
问题:这是预期的吗?为什么?
答案 0 :(得分:2)
Firebird中的字符串文字属于CHAR
类型,案例表达式的数据类型将具有所有分支的最长长度。所以用
CASE BILANCA WHEN 0 THEN 'SMALLINT' WHEN 1 THEN 'NUME' END
数据类型为CHAR(8)
。 CHAR
值将始终右对齐,空格为声明的长度。
但是,当案例表达式的一个分支是VARCHAR
时,则所有分支都被强制转换为VARCHAR
。 Firebird中的串联将始终生成VARCHAR
,即使两个操作数都是CHAR
这意味着在BILANCA1
:
CASE BILANCA
WHEN 1 THEN
CASE BILANCA WHEN 0 THEN 'SMALLINT' WHEN 1 THEN 'NUME' END
ELSE 'A'||'B' END
'A'||'B'
是VARCHAR(2)
,这会导致整个案例被强制转移到VARCHAR
,从而导致'SMALLINT'
成为VARCHAR(8)
和{ {1}} 'NUME'
,这使得整个表达式变为VARCHAR(4)
。
请注意,此类型强制被推下,因此文字从一开始就是VARCHAR(8)
,并且不会通过对最内层case语句的中间评估来填充*。
varchar
不是这种情况,因为所有(嵌套)分支都是文字,因此它将是BILANCA2
。
如果您希望两者的行为相同,则可以执行以下操作:
CHAR(8)
和bilanca1
都适用bilanca2
;这仅适用于强制varchar
bilanca2
varchar
;这仅适用于强制char
bilanca1
char
bilanca2
varchar
(这也强制为trim
) *)这与例如varchar
形成对比,后者将产生cast(cast('nume' as char(8)) as varchar(8))
而不仅仅是'nume '
,因为在这种情况下保留了中间结果,并且不会丢弃现有空格'nume'
。