Szukaj…


Generowanie dat bez komponentu czasu

Wszystkie DATE mają składnik czasu; jednak zwyczajowo przechowuje się daty, które nie muszą zawierać informacji o czasie, a godziny / minuty / sekundy są ustawione na zero (tj. północ).

Użyj literału ANSI DATE (używając formatu daty ISO 8601 ):

SELECT DATE '2000-01-01' FROM DUAL;

Konwertuj go z literału ciągu za pomocą TO_DATE() :

SELECT TO_DATE( '2001-01-01', 'YYYY-MM-DD' ) FROM DUAL;

(Więcej informacji na temat modeli formatu daty można znaleźć w dokumentacji Oracle.)

lub:

SELECT TO_DATE(
         'January 1, 2000, 00:00 A.M.',
         'Month dd, YYYY, HH12:MI A.M.',
         'NLS_DATE_LANGUAGE = American'
       )
FROM   DUAL;

(Jeśli konwertujesz terminy specyficzne dla języka, takie jak nazwy miesięcy, dobrą praktyką jest włączenie trzeciego parametru nlsparam do funkcji TO_DATE() i określenie języka, którego należy się spodziewać).

Generowanie dat za pomocą składnika czasu

Konwertuj go z literału ciągu za pomocą TO_DATE() :

SELECT TO_DATE( '2000-01-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS' ) FROM DUAL;

Lub użyj literału TIMESTAMP :

CREATE TABLE date_table(
  date_value DATE
);

INSERT INTO date_table ( date_value ) VALUES ( TIMESTAMP '2000-01-01 12:00:00' );

Oracle niejawnie rzuci TIMESTAMP na DATE podczas przechowywania go w kolumnie DATE tabeli; jednak możesz jawnie CAST() wartość na DATE :

SELECT CAST( TIMESTAMP '2000-01-01 12:00:00' AS DATE ) FROM DUAL;

Format daty

W Oracle typ danych DATE nie ma formatu; gdy Oracle wyśle DATE do programu klienckiego (SQL / Plus, SQL / Developer, Toad, Java, Python itp.), wyśle 7- lub 8-bajtowe reprezentujące datę.

DATE która nie jest przechowywana w tabeli (tj. Generowana przez SYSDATE i mająca „typ 13” przy użyciu polecenia DUMP() ) ma 8 bajtów i strukturę (liczby po prawej stronie są wewnętrzną reprezentacją 2012-11-26 16:41:09 ):

BYTE VALUE                           EXAMPLE
---- ------------------------------- --------------------------------------
1    Year modulo 256                 220
2    Year multiples of 256           7   (7 * 256 + 220 = 2012)
3    Month                           11
4    Day                             26
5    Hours                           16
6    Minutes                         41
7    Seconds                         9
8    Unused                          0

DATE przechowywana w tabeli („typ 12” przy użyciu polecenia DUMP() ) ma 7 bajtów i strukturę (liczby po prawej stronie są wewnętrzną reprezentacją 2012-11-26 16:41:09 ):

BYTE VALUE                           EXAMPLE
---- ------------------------------- --------------------------------------
1    ( Year multiples of 100 ) + 100 120
2    ( Year modulo 100 ) + 100       112 ((120-100)*100 + (112-100) = 2012)
3    Month                           11
4    Day                             26
5    Hours + 1                       17
6    Minutes + 1                     42
7    Seconds + 1                     10

Jeśli chcesz, aby data miała określony format, musisz przekonwertować ją na coś, co ma format (np. Ciąg znaków). Klient SQL może to zrobić pośrednio lub można jawnie przekonwertować wartość na ciąg za pomocą TO_CHAR( date, format_model, nls_params ) .

Konwertowanie dat na ciąg

Użyj TO_CHAR( date [, format_model [, nls_params]] ) :

(Uwaga: jeśli nie podano modelu formatu, wówczas jako domyślny model formatu zostanie użyty parametr sesji NLS_DATE_FORMAT ; może być inny dla każdej sesji, więc nie należy na nim polegać. Dobrą praktyką jest zawsze określanie modelu formatu).

CREATE TABLE table_name (
  date_value DATE
);

INSERT INTO table_name ( date_value ) VALUES ( DATE '2000-01-01' );
INSERT INTO table_name ( date_value ) VALUES ( TIMESTAMP '2016-07-21 08:00:00' );
INSERT INTO table_name ( date_value ) VALUES ( SYSDATE );

Następnie:

SELECT TO_CHAR( date_value, 'YYYY-MM-DD' ) AS formatted_date FROM table_name;

Wyjścia:

FORMATTED_DATE
--------------
2000-01-01
2016-07-21
2016-07-21

I:

SELECT TO_CHAR(
         date_value,
         'FMMonth d yyyy, hh12:mi:ss AM',
         'NLS_DATE_LANGUAGE = French'
       ) AS formatted_date
FROM   table_name;

Wyjścia:

FORMATTED_DATE
-----------------------------
Janvier   01 2000, 12:00:00 AM
Juillet   21 2016, 08:00:00 AM
Juillet   21 2016, 19:08:31 PM

Ustawianie domyślnego modelu formatu daty

Gdy Oracle niejawnie konwertuje z DATE na ciąg lub odwrotnie (lub gdy TO_CHAR() lub TO_DATE() są jawnie wywoływane bez modelu formatu), parametr sesji NLS_DATE_FORMAT zostanie użyty jako model formatu w konwersji. Jeśli literał nie pasuje do modelu formatu, zgłoszony zostanie wyjątek.

Możesz przejrzeć ten parametr za pomocą:

SELECT VALUE FROM NLS_SESSION_PARAMETERS WHERE PARAMETER = 'NLS_DATE_FORMAT';

Możesz ustawić tę wartość w ramach bieżącej sesji, używając:

ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';

(Uwaga: nie zmienia to wartości dla innych użytkowników).

Jeśli polegasz na NLS_DATE_FORMAT aby zapewnić maskę formatu w TO_DATE() lub TO_CHAR() , nie powinieneś być zaskoczony, gdy Twoje zapytania się zepsują, jeśli ta wartość zostanie kiedykolwiek zmieniona.

Zmiana sposobu wyświetlania dat przez SQL / Plus lub SQL Developer

Kiedy SQL / Plus lub SQL Developer wyświetlają daty, wykonają niejawną konwersję na ciąg przy użyciu domyślnego modelu formatu daty (patrz przykład Ustawianie domyślnego modelu formatu daty ).

Możesz zmienić sposób wyświetlania daty, zmieniając parametr NLS_DATE_FORMAT .

Arytmetyka daty - różnica między datami w dniach, godzinach, minutach i / lub sekundach

W wyroczni różnicę (w dniach i / lub ich ułamkach) między dwoma DATE można znaleźć, odejmując:

SELECT DATE '2016-03-23' - DATE '2015-12-25' AS difference FROM DUAL;

Zwraca liczbę dni między dwiema datami:

DIFFERENCE
----------
        89

I:

SELECT TO_DATE( '2016-01-02 01:01:12', 'YYYY-MM-DD HH24:MI:SS' )
         - TO_DATE( '2016-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS' )
         AS difference
FROM   DUAL

Zwraca ułamek dni między dwiema datami:

DIFFERENCE
----------
    1.0425

Różnicę w godzinach, minutach lub sekundach można znaleźć, mnożąc tę liczbę odpowiednio przez 24 , 24*60 lub 24*60*60 .

Poprzedni przykład można zmienić, aby uzyskać dni, godziny, minuty i sekundy między dwiema datami, używając:

SELECT TRUNC( difference                       ) AS days,
       TRUNC( MOD( difference * 24,       24 ) ) AS hours,
       TRUNC( MOD( difference * 24*60,    60 ) ) AS minutes,
       TRUNC( MOD( difference * 24*60*60, 60 ) ) AS seconds
FROM   (
  SELECT TO_DATE( '2016-01-02 01:01:12', 'YYYY-MM-DD HH24:MI:SS' )
         - TO_DATE( '2016-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS' )
         AS difference
  FROM   DUAL

);

(Uwaga: TRUNC() jest używane zamiast FLOOR() do prawidłowej obsługi różnic ujemnych).

Wyjścia:

DAYS HOURS MINUTES SECONDS
---- ----- ------- -------
   1     1       1      12

Poprzedni przykład można również rozwiązać, przekształcając różnicę liczbową w interwał za pomocą NUMTODSINTERVAL() :

SELECT EXTRACT( DAY    FROM difference ) AS days,
       EXTRACT( HOUR   FROM difference ) AS hours,
       EXTRACT( MINUTE FROM difference ) AS minutes,
       EXTRACT( SECOND FROM difference ) AS seconds
FROM   (
  SELECT NUMTODSINTERVAL(
           TO_DATE( '2016-01-02 01:01:12', 'YYYY-MM-DD HH24:MI:SS' )
             - TO_DATE( '2016-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS' ),
           'DAY'
         ) AS difference
  FROM   DUAL
);

Arytmetyka daty - różnica między datami w miesiącach lub latach

Różnicę w miesiącach między dwiema datami można znaleźć za pomocą MONTHS_BETWEEN( date1, date2 ) :

SELECT MONTHS_BETWEEN( DATE '2016-03-10', DATE '2015-03-10' ) AS difference FROM DUAL;

Wyjścia:

DIFFERENCE
----------
        12

Jeśli różnica obejmuje część miesięcy, zwróci ułamek miesiąca na podstawie 31 dni w każdym miesiącu:

SELECT MONTHS_BETWEEN( DATE '2015-02-15', DATE '2015-01-01' ) AS difference FROM DUAL;

Wyjścia:

DIFFERENCE
----------
 1.4516129

Ponieważ MONTHS_BETWEEN zakłada 31 dni w miesiącu, kiedy może być mniej dni w miesiącu, może to skutkować różnymi wartościami różnic obejmujących granice między miesiącami.

Przykład:

SELECT MONTHS_BETWEEN( DATE'2016-02-01', DATE'2016-02-01' - INTERVAL '1' DAY ) AS "JAN-FEB",
       MONTHS_BETWEEN( DATE'2016-03-01', DATE'2016-03-01' - INTERVAL '1' DAY ) AS "FEB-MAR",
       MONTHS_BETWEEN( DATE'2016-04-01', DATE'2016-04-01' - INTERVAL '1' DAY ) AS "MAR-APR",
       MONTHS_BETWEEN( DATE'2016-05-01', DATE'2016-05-01' - INTERVAL '1' DAY ) AS "APR-MAY"
FROM   DUAL;

Wynik:

JAN-FEB FEB-MAR MAR-APR APR-MAY
------- ------- ------- -------
0.03226 0.09677 0.03226 0.06452

Różnicę w latach można znaleźć, dzieląc różnicę miesiąca przez 12.

Wyodrębnij rok, miesiąc, dzień, godzinę, minutę lub drugi składnik daty

Składniki roku, miesiąca lub dnia typu danych DATE można znaleźć za pomocą EXTRACT( [ YEAR | MONTH | DAY ] FROM datevalue )

SELECT EXTRACT (YEAR  FROM DATE '2016-07-25') AS YEAR,
       EXTRACT (MONTH FROM DATE '2016-07-25') AS MONTH,
       EXTRACT (DAY   FROM DATE '2016-07-25') AS DAY
FROM DUAL;

Wyjścia:

YEAR MONTH DAY
---- ----- ---
2016     7  25

Składniki czasu (godziny, minuty lub sekundy) można znaleźć:

Na przykład:

SELECT EXTRACT( HOUR   FROM CAST( datetime AS TIMESTAMP ) ) AS Hours,
       EXTRACT( MINUTE FROM CAST( datetime AS TIMESTAMP ) ) AS Minutes,
       EXTRACT( SECOND FROM CAST( datetime AS TIMESTAMP ) ) AS Seconds
FROM   (
  SELECT TO_DATE( '2016-01-01 09:42:01', 'YYYY-MM-DD HH24:MI:SS' ) AS datetime FROM DUAL
);

Wyjścia:

HOURS MINUTES SECONDS
----- ------- -------
    9      42       1

Strefy czasowe i czas letni

Typ danych DATE nie obsługuje stref czasowych ani zmian czasu letniego.

Zarówno:

DATE można zapisać jako uniwersalny czas koordynowany (UTC) i przekonwertować na bieżącą strefę czasową sesji w następujący sposób:

SELECT FROM_TZ(
         CAST(
           TO_DATE( '2016-01-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS' )
           AS TIMESTAMP
         ),
         'UTC'
       )
       AT LOCAL AS time
FROM   DUAL;

Jeśli uruchomisz ALTER SESSION SET TIME_ZONE = '+01:00'; następnie dane wyjściowe to:

TIME
------------------------------------
2016-01-01 13:00:00.000000000 +01:00

i ALTER SESSION SET TIME_ZONE = 'PST'; następnie dane wyjściowe to:

TIME
------------------------------------
2016-01-01 04:00:00.000000000 PST

Skokowe sekundy

Oracle nie obsługuje sekund przestępnych . Więcej informacji 2019397.2 notatce My Oracle Support 2019397.2 i 730795.1 .

Pierwsze dzień tygodnia

Możesz użyć TO_CHAR( date_value, 'D' ) aby uzyskać dzień tygodnia.

Jest to jednak zależne od parametru sesji NLS_TERRITORY :

ALTER SESSION SET NLS_TERRITORY = 'AMERICA';        -- First day of week is Sunday
SELECT TO_CHAR( DATE '1970-01-01', 'D' ) FROM DUAL;

Wyjścia 5

ALTER SESSION SET NLS_TERRITORY = 'UNITED KINGDOM'; -- First day of week is Monday
SELECT TO_CHAR( DATE '1970-01-01', 'D' ) FROM DUAL;

Wyjścia 4

Aby to zrobić niezależnie od ustawień NLS , możesz skrócić datę do północy bieżącego dnia (aby usunąć ułamki dni) i odjąć datę obciętą do początku bieżącego izo-tygodnia (który zawsze zaczyna się w poniedziałek):

SELECT TRUNC( date_value ) - TRUNC( date_value, 'IW' ) + 1 FROM DUAL


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow