好的,我通常不会回答我自己的问题,但经过一番修补,我已经明确地知道Oracle如何存储DATE减法的结果。
当您减去2个日期时,该值不是NUMBER数据类型(正如您所相信的Oracle 11.2 SQL Reference manual)。 DATE减法的内部数据类型号为14,这是一个未记录的内部数据类型(NUMBER为internal datatype number 2)。然而,它实际上存储为2个独立的二进制补码,其中前4个字节用于表示天数,最后4个字节用于表示秒数。
导致正整数差的DATE减法的示例:
select date '2009-08-07' - date '2008-08-08' from dual;
结果是:
DATE'2009-08-07'-DATE'2008-08-08'
---------------------------------
364
select dump(date '2009-08-07' - date '2008-08-08') from dual;
DUMP(DATE'2009-08-07'-DATE'2008
-------------------------------
Typ=14 Len=8: 108,1,0,0,0,0,0,0
回想一下,结果表示为2个独立的二进制补码有4个字节的数字。由于在这种情况下没有小数点(完全为364天和0小时),最后4个字节全为0,可以忽略。对于前4个字节,因为我的CPU有一个小端的架构,字节是相反的,应该被读取为1,108或0x16c,这是小数364。
导致负整数差的DATE减法的例子:
select date '1000-08-07' - date '2008-08-08' from dual;
结果是:
DATE'1000-08-07'-DATE'2008-08-08'
---------------------------------
-368160
select dump(date '1000-08-07' - date '2008-08-08') from dual;
DUMP(DATE'1000-08-07'-DATE'2008-08-0
------------------------------------
Typ=14 Len=8: 224,97,250,255,0,0,0,0
再次,由于我使用的是一个小端机,所以这些字节是相反的,应该被读取为255,250,97,224,这对应于11111111 11111010 01100001 11011111.现在由于这是二进制补码签名的二进制数字编码,所以我们知道这个数字是由于最左边的二进制数字是1,所以要将其转换成十进制数,我们必须反转2的补码(减1,然后进行补码),结果为:00000000 00000101 10011110 00100000,等于-368160为怀疑。
导致十进制差的DATE减法的例子:
select to_date('08/AUG/2004 14:00:00', 'DD/MON/YYYY HH24:MI:SS'
- to_date('08/AUG/2004 8:00:00', 'DD/MON/YYYY HH24:MI:SS') from dual;
TO_DATE('08/AUG/200414:00:00','DD/MON/YYYYHH24:MI:SS')-TO_DATE('08/AUG/20048:00:
--------------------------------------------------------------------------------
.25
这两个日期之间的差异是0.25天或6小时。
select dump(to_date('08/AUG/2004 14:00:00', 'DD/MON/YYYY HH24:MI:SS')
- to_date('08/AUG/2004 8:00:00', 'DD/MON/YYYY HH24:MI:SS')) from dual;
DUMP(TO_DATE('08/AUG/200414:00:
-------------------------------
Typ=14 Len=8: 0,0,0,0,96,84,0,0
现在这个时候,由于差异是0天和6个小时,所以预期前4个字节为0.对于最后4个字节,我们可以反转它们(因为CPU是小端),得到84,96 = 01010100 01100000 base 2 = 21600,十进制。将21600秒转换为小时可以让您6小时,这是我们预期的差异。
希望这可以帮助任何人想知道如何实际存储DATE减法。