2017-07-17 79 views
1

我正在使用Firebird 2.5。当我运行使用嵌套CASE和加入字符串的SQL提供尾随空格

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 '(有4位NUME后),'NUME'

  • 'AB''AB'

问:这个预期,为什么?

回答

2

Firebird中的字符串文字的类型为CHAR,case表达式的数据类型将具有所有分支的最长长度。所以用

CASE BILANCA WHEN 0 THEN 'SMALLINT' WHEN 1 THEN 'NUME' END 

该数据类型将是CHAR(8)。一个CHAR值将始终用空格填充到声明的长度。

然而,当案例表达式的其中一个分支是VARCHAR时,则所有分支被强制为VARCHAR。和串联在火鸟总是会产生一个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)'NUME' a VARCHAR(4),这使得整个表达式变成VARCHAR(8)

请注意,这种类型的强制被压低,所以文字从头开始将是varchar,并且不会通过对最内层case语句的中间评估填充*。

对于BILANCA2,情况并非如此,因为所有(嵌套)分支都是文字,因此它将是CHAR(8)

如果你想同时有同样的表现,你可以这样做:

  1. 演员,整个表达式的所需的类型(这会工作既为bilanca1bilanca2)表达
  2. 铸件(如其中一个文字或嵌套的情况)到varchar;这只能强制bilanca2varchar
  3. 将字符串连接强制转换为char;这只能将bilanca1强制为char
  4. 将空字符串连接到其中一个文字;这仅适用于强制bilanca2对整个表达式varchar
  5. 使用trim(这也要挟到varchar

*)此相反,例如cast(cast('nume' as char(8)) as varchar(8))将产生'nume '并不仅仅是'nume',因为在这种情况下,中间结果被保留,并且存在的空间不会被丢弃在varchar中。