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?

JohnMerlino
źródło

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.

Erwin Brandstetter
źródło
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.

Vao Tsun
źródło
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