oracle解码与字符不兼容

时间:2018-04-27 12:14:10

标签: oracle

我有一个带有'T'或'F'值的字段(标志)的表,当我执行以下语句时它显示记录:

SELECT * FROM table WHERE DECODE(flag,'F',0,'T',1,NULL) is null AND flag='F';

虽然它不应该。解码函数始终使用此特定表执行此操作。我的第一个想法是编码问题,但上面的陈述取消了这个想法。 如果有人帮忙,我会感激不尽。

1 个答案:

答案 0 :(得分:1)

您能否确认flag的数据类型是CHAR而不是VARCHAR2? 这与下面显示的行为一致......

create table t1(
  flag  char(2)
 ,flag2 varchar2(2) 
);

insert into t1 values('F', 'F');
insert into t1 values('T', 'T');
insert into t1 values('X', 'X');
insert into t1 values(null, null);

commit;


select decode(flag,  'F', 0, 'T', 1, null) as with_char
      ,decode(flag2, 'F', 0, 'T', 1, null) as with_varchar
  from t1;

WITH_CHAR   WITH_VARCHAR
----------  ------------
   null          0
   null          1
   null         null
   null         null

要解决此问题,您必须:

  1. 重写您的逻辑(首选
  2. 使用DECODE(TRIM(flag), ...)
  3. 将数据类型更改为VARCHAR2
  4. 编辑:为什么flag ='F'为真?

    这是因为表达式'F'的隐式数据类型为CHAR(1)。在比较两个char(x)表达式的特殊情况下,Oracle会将其中较短的一个表示为较长列的长度。显然,这是ANSI / ISO SQL标准的要求。

    根据char(2)语义,标志列已经空白到'F ',当oracle看到你的'F'表达式时,它意识到将char(2)与char(1)进行比较,将'F'表达式空白到'F '

    这就是为什么'F' = 'F ':)

    DECODE不是这样,因为这里'F' <> 'F '。这不是DECODE与SQL不一致的唯一时间,你应该尽量避免使用它。

    您可以在Oracle文档的CHAR versus VARCHAR2 Semantics章节中阅读更多内容。