[英]SQL with nested CASE and joining strings gives trailing spaces
I am using Firebird 2.5. 我正在使用Firebird 2.5。 When I run 当我跑步
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
field BILANCA2 is 'NUME '
(there are 4 spaces after NUME) and BILANCA1 is 'NUME'
. 字段BILANCA2为'NUME '
( 'NUME '
之后有4个空格),BILANCA1为'NUME'
。 Number of added spaces is equal to length of longest string in CASE. 添加空格的数量等于CASE中最长字符串的长度。 The only difference is in joining string in BILANCA1: 唯一的区别在于BILANCA1中的连接字符串:
ELSE 'A'||'B' END
DDL is DDL是
CREATE TABLE GS01BILANCA
(BILANCA INTEGER DEFAULT 0 NOT NULL,
CONSTRAINT PK_GS01BILANCA PRIMARY KEY (BILANCA));
Table has 2 records: 表有2条记录:
Result is 结果是
'NUME '
(there are 4 spaces after NUME), 'NUME'
'NUME '
( 'NUME '
之后有4个空格), 'NUME'
'AB'
, 'AB'
'AB'
, 'AB'
Question: Is this expected and why? 问题:这是预期的,为什么?
String literals in Firebird are of type CHAR
, the datatype of a case expression will have the longest length of all branches. Firebird中的字符串文字为CHAR
类型,case表达式的数据类型将具有所有分支中最长的长度。 So with 所以用
CASE BILANCA WHEN 0 THEN 'SMALLINT' WHEN 1 THEN 'NUME' END
The datatype will be CHAR(8)
. 数据类型将为CHAR(8)
。 A CHAR
value will always be right-padded with the spaces to the declared length. CHAR
值将始终用空格右填充到声明的长度。
However when one of the branches of a case expression is a VARCHAR
, then all branches are coerced to a VARCHAR
. 但是,当case表达式的分支之一是VARCHAR
,则所有分支都被强制转换为VARCHAR
。 And concatenation in Firebird will always produce a VARCHAR
, even if both operands are CHAR
而且即使两个操作数均为CHAR
,Firebird中的串联也将始终产生VARCHAR
This means that in the case of BILANCA1
: 这意味着对于BILANCA1
:
CASE BILANCA
WHEN 1 THEN
CASE BILANCA WHEN 0 THEN 'SMALLINT' WHEN 1 THEN 'NUME' END
ELSE 'A'||'B' END
that 'A'||'B'
is a VARCHAR(2)
, this causes the entire case to be coerced to VARCHAR
, which then causes 'SMALLINT'
to become a VARCHAR(8)
and 'NUME'
a VARCHAR(4)
, which makes the entire expression becomes a VARCHAR(8)
. 'A'||'B'
是VARCHAR(2)
,这将导致整个案例被强制转换为VARCHAR
,这随后将导致'SMALLINT'
成为VARCHAR(8)
而'NUME'
成为VARCHAR(4)
,这使得整个表达式变为VARCHAR(8)
。
Note that this type coercion is pushed down, so the literal will be a varchar
from the start and not be blanked padded* by intermediate evaluation of the innermost case statement. 请注意,这种类型的强制转换是向下推的,因此文字从一开始就是varchar
,不会被最里面的case语句的中间评估所填充*。
That is not the case for BILANCA2
, as all (nested) branches are literals, therefor it will be a CHAR(8)
. 对于BILANCA2
并非如此,因为所有(嵌套的)分支都是文字,因此它将是CHAR(8)
。
If you want both to behave the same you can do: 如果您希望两者的行为相同,则可以执行以下操作:
bilanca1
and bilanca2
) 将整个表达式转换为所需的类型(这对bilanca1
和bilanca2
都适用) varchar
; 将表达式的一部分(例如,文字之一或嵌套的大小写)转换为varchar
; this only works to force bilanca2
to a varchar
这仅适用于将bilanca2
强制为varchar
char
; 将字符串串联转换为char
; this only works to force bilanca1
to a char
这只能将bilanca1
强制为char
bilanca2
to a varchar
这仅适用于将bilanca2
强制为varchar
trim
on the entire expression (this also coerces to varchar
) 在整个表达式上使用trim
(这也会强制转换为varchar
) *) This in contrast to for example cast(cast('nume' as char(8)) as varchar(8))
which will produce 'nume '
and not just 'nume'
as in this case the intermediate result is preserved, and existing spaces are not thrown away in a varchar
. *)这与例如cast(cast('nume' as char(8)) as varchar(8))
产生'nume '
而不是'nume'
会生成'nume '
,因为在这种情况下,中间结果得以保留,并且现有空间不会在varchar
丢弃。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.