在没有 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 甚至有关于此主题的条目。
并非所有数据库都需要 select
的 from
子句 -- 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
我很惊讶这个问题还没有被问到。我一定错过了一些非常明显的东西,我已经准备好接受所有的反对票和 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 甚至有关于此主题的条目。
并非所有数据库都需要 select
的 from
子句 -- 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