在没有 DUAL table 的情况下使用 SYSDATE()

Using SYSDATE() without DUAL table

我很惊讶这个问题还没有被问到。我一定错过了一些非常明显的东西,我已经准备好接受所有的反对票和 3 秒的回答。

在 MSSQL 中,您可以调用 GETDATE() 而不必依赖数据库 table,但在 Oracle 中 SYSDATE 必须来自 DUAL。有没有办法在不通过 DUAL 的情况下获取 Oracle 中的当前日期?

编辑

显然,这与 SYSDATE 没有太大关系,但更多的是我对它的错误使用。请参阅以下 WHERE 子句:

WHERE (extract(YEAR from ORDER_DATE) = (case when extract(month from SYSDATE()) < 11 then extract(year from SYSDATE()) else extract(year from SYSDATE())+1 end)

上面的方法不行,从这里的回答来看似乎不推荐在里面加dual。这里的最佳解决方案是什么?

你的问题是关于sysdate,但它确实与sysdate无关。

在 Oracle 中,所有 select 查询都需要一个 from 子句。 from 子句 必须 包含某些内容。因此,曾几何时,Oracle 的某个人发明了 dual,连同它非常笨拙的名字,作为一个只有一行的 built-in table。 Wikipedia 甚至有关于此主题的条目。

并非所有数据库都需要 selectfrom 子句 -- SQL 服务器、MySQL 和 Postgres,例如,都允许 select 没有一个。

您可以在查询中允许使用标量表达式的任何位置使用标量表达式,例如 sysdate。您可以根据需要重复多次,完全独立于 from 子句中的内容。

可以在任何数据库的子查询中嵌入标量表达式。例如,

select (select sysdate from dual)
from dual

和:

select (select getdate())

都是有效的表达。然而,这几乎总是不好的做法,几乎总是应该避免的。 (我能想到的一个例外是在 SQL 服务器的 window 函数排序子句中使用常量来防止排序开销,例如 row_number() over (order by (select null)))。

您可以只使用 SYSDATE 而无需明确引用 DUAL table。

大概是这样的: INSERT INTO SOME_TABLE(some_date) VALUES (SYSDATE)

欢迎来到 Oracle,这里的一切都是莫名其妙、违背常识的。

Is there no way to get the current date in Oracle without having to go through DUAL?

Sysdate 是一个pseudo-column,我们可以认为它是一个returns 当前日期时间的函数。所以它可以像任何其他功能一样使用。是的,在像 ...

这样的查询投影中
 select sysdate from dual;

...或者...

insert into sometable (id, date_created)
values (id_seq.nextval, sysdate);

但也在 where 子句中。在过去三十天内雇用的员工:

 select * from emp
 where hire_date > sysdate - 30

要查找今年录用的员工,我们可以这样做:

 select * from emp
 where extract(year from hire_date) = extract(year from sysdate)

...但这可能表现更好

 select * from emp
 where hire_date >= trunc(sysdate, 'YYYY') -- resolves to 2019-01-01
 /

在PL/SQL中:

declare
    ld date;
begin
    ld := trunc(sysdate); 
end;

避免在 sysdate 之后写 ()。

示例 - 在 WHERE 子句中使用您的 CASE(不使用 DUAL):

create table T ( dt date ) ;

insert into T ( dt ) values ( sysdate ) ;


-- just write SYSDATE, not SYSDATE()
select *
from T   
where ( extract ( year from dt ) ) = ( 
  case 
    when extract( month from sysdate ) < 11 then
      extract( year from sysdate ) 
    else
      extract( year from sysdate ) + 1
  end 
) ;

-- output
DT       
---------
23-MAY-19

DBfiddle