繁体   English   中英

带有嵌套CASE和连接字符串的SQL给出尾随空格

[英]SQL with nested CASE and joining strings gives trailing spaces

我正在使用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条记录:

  • 1
  • 2

结果是

  • 'NUME ''NUME '之后有4个空格), 'NUME'

  • 'AB''AB'

问题:这是预期的,为什么?

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

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

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

但是,当case表达式的分支之一是VARCHAR ,则所有分支都被强制转换为VARCHAR 而且即使两个操作数均为CHAR ,Firebird中的串联也将始终产生VARCHAR

这意味着对于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'成为VARCHAR(4) ,这使得整个表达式变为VARCHAR(8)

请注意,这种类型的强制转换是向下推的,因此文字从一开始就是varchar ,不会被最里面的case语句的中间评估所填充*。

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

如果您希望两者的行为相同,则可以执行以下操作:

  1. 将整个表达式转换为所需的类型(这对bilanca1bilanca2都适用)
  2. 将表达式的一部分(例如,文字之一或嵌套的大小写)转换为varchar 这仅适用于将bilanca2强制为varchar
  3. 将字符串串联转换为char ; 这只能将bilanca1强制为char
  4. 将一个空字符串连接到其中一个文字; 这仅适用于将bilanca2强制为varchar
  5. 在整个表达式上使用trim (这也会强制转换为varchar

*)这与例如cast(cast('nume' as char(8)) as varchar(8))产生'nume '而不是'nume'会生成'nume ' ,因为在这种情况下,中间结果得以保留,并且现有空间不会在varchar丢弃。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM