我有一个带有'T'或'F'值的字段(标志)的表,当我执行以下语句时它显示记录:
SELECT * FROM table WHERE DECODE(flag,'F',0,'T',1,NULL) is null AND flag='F';
虽然它不应该。解码函数始终使用此特定表执行此操作。我的第一个想法是编码问题,但上面的陈述取消了这个想法。 如果有人帮忙,我会感激不尽。
答案 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
要解决此问题,您必须:
DECODE(TRIM(flag), ...)
这是因为表达式'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章节中阅读更多内容。