Oracle中与SQL Server/Sybase DateDiff相当的函数是什么?

5
我们现在使用NHibernate连接到不同的数据库,根据软件安装位置的不同。因此,我正在将许多SQL存储过程移植到Oracle。
SQL Server有一个很好的函数叫做DateDiff,它需要一个日期部分、开始日期和结束日期。
日期部分的例子包括天、周、月、年等等...
那么Oracle的等效函数是什么呢?
我没有找到一个,所以我必须创建自己的版本吗?
(Mark Harrison更新)有几个很好的答案解释了Oracle日期运算。如果你需要一个Oracle datediff(),请参考Einstein的答案。(我需要这个来保持一些SQL脚本在Sybase和Oracle之间兼容。)注意,这个问题同样适用于Sybase。

请看这里:http://asktom.oracle.com/tkyte/Misc/DateDiff.html(如果该链接仍然失效,请使用下面的链接) http://asktom.oracle.com/pls/asktom/ASKTOM.download_file?p_file=6551242712657900129 - John Smithers
没有任何链接有效。 - Ariagna Bandala Salazar
4个回答

5
我从几年前的一篇老Tom文章中借鉴了大部分内容,并修复了该文章中的一些错误并进行了清理。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;
/

大家好,你们所有的案例都对我有很大的帮助,只是想要获得周数的差异我一直没有成功。我已经将总天数除以7,但是我没有像在SQL Server中那样获得相同的结果,你们能帮我实现相同的结果吗? - Ariagna Bandala Salazar

4

JohnLavoie - 您不需要那个。在Oracle中,DATE实际上是日期和时间数据类型。DATE和TIMESTAMP之间唯一的区别是DATE精确到秒,而TIMESTAMP精确到微秒。因此,Ask Tom的文章对于TIMESTAMP列也是完全有效的。


1

Tom的文章非常老旧。它只讨论了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

或者

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

0
你可以在Oracle中编写一个函数来实现这个功能。
function        datediff( p_what in varchar2, p_d1 in date, p_d2 in date) return number as  l_result    number; 
BEGIN
      select (p_d2-p_d1) * 
             decode( upper(p_what), 'SS', 24*60*60, 'MI', 24*60, 'HH', 24, NULL ) 
       into l_result from dual; 

      return l_result; 
END;

并像这样使用:

DATEDIFF('YYYY-MM-DD', SYSTIMESTAMP, SYSTIMESTAMP)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接