Oracle相当于SQL Server/Sybase DateDiff

Dav*_*rab 5 sql sql-server oracle sybase datediff

我们现在使用NHibernate连接到我们软件安装位置的不同数据库.所以我将许多SQL程序移植到Oracle.

SQL Server有一个很好的函数叫DateDiff,它接受一个日期部分,startdate和enddate.

日期部分示例是日,周,月,年等..

什么是Oracle等价物?

我还没有找到一个我必须创建自己的版本吗?

(由Mark Harrison更新)有几个很好的答案可以解释Oracle日期算术.如果你需要Oracle datediff(),请参阅爱因斯坦的回答.(我需要这样来保持Sybase和Oracle之间的spme SQL脚本兼容.)请注意,此问题同样适用于Sybase.

小智 5

我从几年前的一篇旧汤姆文章中窃取了大部分内容,修复了文章中的一些错误并进行了清理。datediff 的分界线在 oracle 和 MSSQL 之间的计算方式不同,因此您必须小心一些漂浮在那里的示例,这些示例不能正确解释不提供小数结果的 MSSQL/Sybase 样式边界。

通过以下内容,您应该能够使用 MSSQL 语法并获得与 MSSQL 相同的结果,例如 SELECT DATEDIFF(dd,getdate(),DATEADD(dd,5,getdate())) FROM DUAL;

我只声称它有效 - 而不是它有效或最好的方法。我不是 Oracle 人 :) 而且您可能要三思而后行,使用我的函数宏来解决需要在 dd、mm、hh、mi.. 等周围使用引号的方法。

(由 Mark Harrison 更新)添加了 dy 函数作为 dd 的别名。

CREATE OR REPLACE FUNCTION GetDate 
RETURN date IS today date;
BEGIN
RETURN(sysdate);
END;
/

CREATE OR REPLACE FUNCTION mm RETURN VARCHAR2 IS BEGIN RETURN('mm'); END;
/
CREATE OR REPLACE FUNCTION yy RETURN VARCHAR2 IS BEGIN RETURN('yyyy'); END;
/
CREATE OR REPLACE FUNCTION dd RETURN VARCHAR2 IS BEGIN RETURN('dd'); END;
/
CREATE OR REPLACE FUNCTION dy RETURN VARCHAR2 IS BEGIN RETURN('dd'); END;
/
CREATE OR REPLACE FUNCTION hh RETURN VARCHAR2 IS BEGIN RETURN('hh'); END;
/
CREATE OR REPLACE FUNCTION mi RETURN VARCHAR2 IS BEGIN RETURN('mi'); END;
/
CREATE OR REPLACE FUNCTION ss RETURN VARCHAR2 IS BEGIN RETURN('ss'); END;
/

CREATE OR REPLACE Function DateAdd(date_type IN varchar2, offset IN integer, date_in IN date )
RETURN date IS date_returned date;
BEGIN
date_returned := CASE date_type
    WHEN 'mm'   THEN add_months(date_in,TRUNC(offset))
    WHEN 'yyyy' THEN add_months(date_in,TRUNC(offset) * 12)
    WHEN 'dd'   THEN date_in + TRUNC(offset)
    WHEN 'hh'   THEN date_in + (TRUNC(offset) / 24)
    WHEN 'mi'   THEN date_in + (TRUNC(offset) /24/60)
    WHEN 'ss'   THEN date_in + (TRUNC(offset) /24/60/60)
    END;
RETURN(date_returned);
END;
/

CREATE OR REPLACE Function DateDiff( return_type IN varchar2, date_1 IN date, date_2 IN date)
RETURN integer IS number_return integer;
BEGIN
number_return := CASE return_type
    WHEN 'mm'   THEN ROUND(MONTHS_BETWEEN(TRUNC(date_2,'MM'),TRUNC(date_1, 'MM')))
    WHEN 'yyyy' THEN ROUND(MONTHS_BETWEEN(TRUNC(date_2,'YYYY'), TRUNC(date_1, 'YYYY')))/12
    WHEN 'dd'   THEN ROUND((TRUNC(date_2,'DD') - TRUNC(date_1, 'DD')))
    WHEN 'hh'   THEN (TRUNC(date_2,'HH') - TRUNC(date_1,'HH')) * 24
    WHEN 'mi'   THEN (TRUNC(date_2,'MI') - TRUNC(date_1,'MI')) * 24 * 60
    WHEN 'ss'   THEN (date_2 - date_1) * 24 * 60 * 60
    END;
RETURN(number_return);
END;
/
Run Code Online (Sandbox Code Playgroud)


小智 1

汤姆的文章很旧了。它仅讨论 DATE 类型。如果您使用 TIMESTAMP 类型,则日期算术将内置到 PL/SQL 中。

http://www.akadia.com/services/ora_date_time.html

DECLARE
ts_a timestamp;
ts_b timestamp;
diff interval day to second;
BEGIN
  ts_a := systimestamp;
  ts_b := systimestamp-1/24;
  diff := ts_a - ts_b;
  dbms_output.put_line(diff);
END;
+00 01:00:00.462000
Run Code Online (Sandbox Code Playgroud)

或者

DECLARE
ts_b timestamp;
ts_a timestamp;
date_part interval day to second;

BEGIN
  ts_a := systimestamp;
  date_part := to_dsinterval('0 01:23:45.678');
  ts_b := ts_a + date_part;
  dbms_output.put_line(ts_b);
END;

04-SEP-08 05.00.38.108000 PM
Run Code Online (Sandbox Code Playgroud)