有人可以帮我理解下面的 SQL 输出吗?
SELECT *
FROM dual
WHERE SYSDATE >= DECODE(NVL(1,0),0,NULL,SYSDATE);
-- This returns row
SELECT *
FROM dual
WHERE SYSDATE <= DECODE(NVL(1,0),0,NULL,SYSDATE);
-- No output if we use <=
SELECT *
FROM dual
WHERE SYSDATE <= DECODE(NVL(1,0),0,SYSDATE,SYSDATE);
-- This returns row
Run Code Online (Sandbox Code Playgroud)
问题在于decode返回的数据类型。这是基于第一个可选返回的数据类型,但默认为varchar2. 所以表达式(我替换nvl(1,0)为1因为它不会改变行为并简化表达式)
DECODE(1,0,NULL,SYSDATE)
Run Code Online (Sandbox Code Playgroud)
返回一个varchar2值。这意味着查询实际上变成了
select *
from dual
where sysdate <= to_char(sysdate);
Run Code Online (Sandbox Code Playgroud)
如果你看一下计划你就可以看到
explain plan for
SELECT 1 FROM dual WHERE SYSDATE <= DECODE(1,0,null,SYSDATE);
select * from table( dbms_xplan.display() );
PLAN_TABLE_OUTPUT
Plan hash value: 4034615273
-----------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
|* 1 | FILTER | | | | |
| 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(SYSDATE@!<=TO_CHAR(SYSDATE@!))
Run Code Online (Sandbox Code Playgroud)
如果将您设置nls_date_format为包含日期时间部分的内容,则查询将返回一行,因为现在隐式转换不会丢失时间信息。
alter session set nls_date_format = 'yyyy-mm-dd hh24:mi:ss';
SELECT 1 "null" FROM dual WHERE SYSDATE <= DECODE(1,0,null,SYSDATE);
null
1
Run Code Online (Sandbox Code Playgroud)
或者,您可以decode通过显式强制转换返回正确的数据类型
SELECT 1 "cast(null)"
FROM dual
WHERE SYSDATE <= DECODE(1,0,cast(null as date),SYSDATE);
Run Code Online (Sandbox Code Playgroud)
无论会话是什么,这都会返回一行,nls_date_format因为decode现在将返回一个date数据类型,并且您正在将 adate与 a进行比较date。这也是decode(1,0,sysdate,sysdate)起作用的原因——因为该decode表达式也返回一个date.
| 归档时间: |
|
| 查看次数: |
564 次 |
| 最近记录: |