Różnica między now () a bieżącym znacznikiem czasu


45

W PostgreSQL używam now()i current_timestampfunkcji i nie widzę różnicy:

# SELECT now(), current_timestamp;
              now               |              now               
--------------------------------+--------------------------------
 04/20/2014 19:44:27.215557 EDT | 04/20/2014 19:44:27.215557 EDT
(1 row)

Czy coś brakuje?

Odpowiedzi:


54

Nie ma różnicy. Trzy cytaty z instrukcji:

1)

Te standardowe funkcje SQL zwracają wszystkie wartości w oparciu o czas rozpoczęcia bieżącej transakcji:
... ...
CURRENT_TIMESTAMP

2)

transaction_timestamp()jest równoważne CURRENT_TIMESTAMP, ale ma nazwę, która wyraźnie odzwierciedla to, co zwraca.

3)

now()jest tradycyjnym odpowiednikiem PostgreSQL transaction_timestamp().

Odważny nacisk moje. CURRENT_TIMESTAMP, transaction_timestamp()I now()robić dokładnie to samo. CURRENT_TIMESTAMPjest składniową osobliwością funkcji, która nie ma końcowej pary nawiasów. Jest to zgodne ze standardem SQL.

Jeśli nie zadeklarujesz aliasu kolumny dla wywołania funkcji w instrukcji SQL, domyślnym aliasem jest nazwa funkcji. Wewnętrznie CURRENT_TIMESTAMPimplementowany jest standardowy SQL now(). Do Postgres 9.6, który pojawia się w wynikowej nazwie kolumny , która była „teraz”, ale zmieniła się na „current_timestamp” w Postgres 10.

transaction_timestamp() robi to samo, ale ta jest prawidłową funkcją Postgres, więc domyślnym aliasem zawsze był „znak_transakcji”.

Nie należy mylić żadnej z tych funkcji ze specjalną stałą wejściową'now' . To tylko jeden z kilku skrótów notacyjnych dla określonych wartości daty / godziny / znacznika czasu, cytując instrukcję:

... które zostaną odczytane podczas odczytu do zwykłych wartości daty / godziny. (W szczególności nowpowiązane ciągi znaków są konwertowane na określoną wartość czasu, gdy tylko zostaną odczytane.) Wszystkie te wartości muszą być ujęte w pojedyncze cudzysłowy, gdy są używane jako stałe w poleceniach SQL.

Może to zwiększyć zamieszanie, że (do co najmniej Postgres 12) dowolna liczba początkowych i końcowych spacji i nawiasów ( {[( )]}) jest przycinana z tych specjalnych wartości wejściowych. Tak więc 'now()'::timestamptz- lub tylko 'now()'tam, gdzie nie jest wymagany rzut typu jawnego - jest również poprawny i now() w większości kontekstów dokonuje oceny według tego samego znacznika czasu co funkcja . Ale są to stałe i zazwyczaj nie są to, na przykład, domyślne kolumny.

db <> skrzypce tutaj
Stare skrzypce SQL

Ważnymi alternatywami są statement_timestamp()i clock_timestamp(). Instrukcja:

statement_timestamp()zwraca czas rozpoczęcia bieżącej instrukcji (dokładniej czas otrzymania ostatniej wiadomości polecenia od klienta). [...]
clock_timestamp()zwraca aktualny aktualny czas, a zatem jego wartość zmienia się nawet w ramach jednego polecenia SQL.

Uwaga: statement_timestamp()jest STABLEjak powyżej (zawsze zwraca tę samą wartość w ramach tego samego polecenia SQL). Ale clock_timestamp()koniecznie jest tylko VOLATILE. Różnica może być znacząca.


ale czy to wpływa na optymalizację zapytań? zostanie teraz wykonane () dla każdego wiersza w where items.createddate > now():?
santiago arizti

3
@santiagoarizti: Nie. now()Zdefiniowano, STABLEponieważ ocenia się na tę samą wartość (czas rozpoczęcia bieżącej transakcji) w ramach tej samej transakcji. I twój przykład now()jest wykonywany tylko raz (w przeciwieństwie do clock_timestamp()na przykład).
Erwin Brandstetter

3

Oprócz tego, że nie mają różnicy funkcjonalnej, gdy używasz ich prawidłowo, są one rzutowane inaczej:

'now()'rozpoznany (tak jak 'today'lub 'now'):

b=# select 'now()'::timestamptz;
          timestamptz
-------------------------------
 2016-12-09 16:31:35.942243+00
(1 row)

'CURRENT_TIMESTAMP'daje zabawny błąd z ciemnych krawędzi

Uwaga: Począwszy od wersji 7.2 PostgreSQL, „bieżący” nie jest już obsługiwany jako stała daty / czasu

b=# select 'CURRENT_TIMESTAMP'::timestamptz;
ERROR:  date/time value "current" is no longer supported
LINE 1: select 'CURRENT_TIMESTAMP'::timestamptz;
               ^

i nie 'transaction_timestamp()'jest po prostu ponownie interpretowany jako znacznik czasu o wartości tz:

b=# select 'transaction_timestamp()'::timestamptz;
ERROR:  invalid input syntax for type timestamp with time zone: "transaction_timestamp()"
LINE 1: select 'transaction_timestamp()'::timestamptz;
               ^

Nie pytaj, dlaczego chcesz rzucić 'now()' as timestamp. Widziałem where timestamp_column = 'now()'zamiast where timestamp_column = now()w kodzie ludzi, więc pomyślałem, że to wyjaśnienie byłoby zabawnym faktem i dobrym dodatkiem do odpowiedzi Erwina.


To nieporozumienie. Ciąg wejściowy'now()' wygląda podobnie do funkcji now()na powierzchni, ale nie jest bezpośrednio związane inaczej. 'now'jest stałą oceną czasu rozpoczęcia bieżącej transakcji . Końcowe pareny są ignorowane. Próba oddania ciągi 'CURRENT_TIMESTAMP'lub 'transaction_timestamp()'aby timestampw podobny sposób zawiedzie, bo to po prostu bzdura. Żadne z nich nie jest powiązane z odpowiednimi funkcjami.
Erwin Brandstetter
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.