programing

Oracle에서 날짜 빼기 - 숫자 또는 구간 데이터 유형?

easyjava 2023. 6. 8. 22:41
반응형

Oracle에서 날짜 빼기 - 숫자 또는 구간 데이터 유형?

Oracle DATE 및 INTERVAL 데이터 유형의 내부 작업에 대해 질문이 있습니다.Oracle 11.2 SQL Reference에 따르면 2개의 DATE 데이터 유형을 빼면 NUMBER 데이터 유형이 됩니다.

필기 시험에서 이것은 사실로 나타납니다.

CREATE TABLE test (start_date DATE);
INSERT INTO test (start_date) VALUES (date'2004-08-08');
SELECT (SYSDATE - start_date) from test;

NUMBER 데이터 유형을 반환합니다.

하지만 이제 당신이 한다면,

SELECT (SYSDATE - start_date) DAY(5) TO SECOND from test;

INTERVAL 데이터 유형이 표시됩니다.즉, Oracle은 날짜 빼기에서 숫자를 Interval 유형으로 변환할 수 있습니다.

이제 괄호 안에 NUMBER 데이터 유형을 직접 입력할 수 있습니다('SYSDATE - start_date' 대신).

SELECT (1242.12423) DAY(5) TO SECOND from test;

그러나 다음과 같은 오류가 발생합니다.

ORA-30083: syntax error was found in interval value expression

그래서 제 질문은: 여기서 무슨 일이 일어나고 있는가 하는 것입니다.날짜를 빼면 숫자가 나와야 하는 것 같습니다(SELECT 문 #1 참조). 간격 유형에 자동으로 캐스팅할 수 없습니다(SELECT 문 #3 참조).하지만 Oracle은 원시 번호(SELECT 문 #2)를 넣는 대신 DATE 뺄셈 표현을 사용하면 어떻게든 그렇게 할 수 있을 것 같습니다.

감사해요.

좋아요, 저는 보통 제 질문에 대답하지 않지만, 약간 수정한 후에 Oracle이 날짜 빼기 결과를 저장하는 방법을 확실히 알게 되었습니다.

날짜 2개를 빼면 값이 NUMBER 데이터 유형이 아닙니다(Oracle 11.2 SQL Reference 매뉴얼에서 설명하는 것처럼).DATE 감산의 내부 데이터 유형 번호는 14이며, 이는 문서화되지 않은 내부 데이터 유형입니다(NUMBER는 내부 데이터 유형 번호 2).그러나 실제로는 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개의 별도 2개의 보완 부호가 있는 4바이트 숫자로 표시됩니다.이 경우 소수점 이하(364일 및 0시간 정확)가 없으므로 마지막 4바이트는 모두 0이므로 무시할 수 있습니다.처음 4바이트의 경우 CPU에 리틀 엔디언 아키텍처가 있기 때문에 바이트가 반대로 표시되며 1,108 또는 0x16c(10진수 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로 판독되어야 하며, 이는 111111111101001100001 11011111에 해당합니다.이제 이것은 2의 보완 부호화된 이진 숫자 인코딩이므로, 가장 왼쪽의 이진 숫자가 1이기 때문에 숫자가 음수임을 알 수 있습니다.이 값을 십진수로 변환하려면 2의 보어를 반대로 해야 합니다(1을 뺀 다음 보어를 수행합니다). 0000000000000101 1001111000000은 의심스러운 대로 -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 = 010101001000 base 2 = 21600을 소수점으로 얻을 수 있습니다.21600초를 시간으로 환산하면 우리가 예상했던 6시간의 차이가 납니다.

날짜 빼기가 실제로 어떻게 저장되는지 궁금했던 사람들에게 도움이 되기를 바랍니다.

날짜 함수가 숫자를 반환하지 않지만 간격을 반환하기 때문에 구문 오류가 발생합니다.

SQL> SELECT DUMP(SYSDATE - start_date) from test;

DUMP(SYSDATE-START_DATE)
-------------------------------------- 
Typ=14 Len=8: 188,10,0,0,223,65,1,0

먼저 NUMTODS 간격 함수를 사용하여 예제의 숫자를 간격으로 변환해야 합니다.

예:

SQL> SELECT (SYSDATE - start_date) DAY(5) TO SECOND from test;

(SYSDATE-START_DATE)DAY(5)TOSECOND
----------------------------------
+02748 22:50:04.000000

SQL> SELECT (SYSDATE - start_date) from test;

(SYSDATE-START_DATE)
--------------------
           2748.9515

SQL> select NUMTODSINTERVAL(2748.9515, 'day') from dual;

NUMTODSINTERVAL(2748.9515,'DAY')
--------------------------------
+000002748 22:50:09.600000000

SQL>

NUMTODSINTERVAL() 함수가 있는 역캐스트를 기준으로 하면 반올림이 일부 번역에서 손실된 것으로 보입니다.

몇 가지 요점:

  • 다른 날짜에서 날짜를 빼면 숫자가 되고, 다른 날짜에서 타임스탬프를 빼면 간격이 됩니다.

  • Oracle은 타임스탬프 연산을 수행할 때 내부적으로 타임스탬프를 날짜로 변환합니다.

  • 간격 상수는 날짜 또는 타임스탬프 산술에 사용할 수 없습니다.

Oracle 11gR2 SQL 참조 날짜/시간 매트릭스

extract() 함수를 사용하여 간격 값에서 시간/분/초를 검색합니다.아래 예제에서는 두 개의 타임스탬프 열에서 시간을 가져오는 방법을 참조하십시오.이것이 도움이 되길 바랍니다!

INS_TS, MAIL_SENT_TS, extract(INS_TS에서 (INS_TS - MAIL_SENT_TS에서 한 시간)hourDiffMAIL_NTFCTN;

TIMIFF(STR_TO_DATE('07:15 PM', '%h:%i %p'), STR_TO_DATE('9:58 AM', '%h:%i %p')를 선택합니다.

언급URL : https://stackoverflow.com/questions/9322935/subtracting-dates-in-oracle-number-or-interval-datatype

반응형