Sự khác biệt giữa now () và current_timestamp


45

Trong PostgreSQL, tôi sử dụng now()current_timestampchức năng và tôi thấy không có sự khác biệt:

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

Tui bỏ lỡ điều gì vậy?

Câu trả lời:


54

Không có sự khác biệt. Ba trích dẫn từ hướng dẫn:

1)

Các hàm tiêu chuẩn SQL này đều trả về các giá trị dựa trên thời gian bắt đầu của giao dịch hiện tại:
... ...
CURRENT_TIMESTAMP

2)

transaction_timestamp()tương đương với CURRENT_TIMESTAMP, nhưng được đặt tên để phản ánh rõ ràng những gì nó trả về.

3)

now()là một PostgreSQL truyền thống tương đương với transaction_timestamp().

Nhấn mạnh đậm của tôi. CURRENT_TIMESTAMP, transaction_timestamp()now()làm chính xác như vậy. CURRENT_TIMESTAMPlà một số lẻ cú pháp cho một hàm, không có cặp dấu ngoặc đơn. Đó là theo tiêu chuẩn SQL.

Nếu bạn không khai báo bí danh cột cho lệnh gọi hàm trong câu lệnh SQL, thì bí danh sẽ mặc định là tên của hàm. Trong nội bộ, SQL tiêu chuẩn CURRENT_TIMESTAMPđược triển khai với now(). Lên đến Postgres 9.6 hiển thị trong tên cột kết quả là "bây giờ", nhưng đã thay đổi thành "current_timestamp" trong Postgres 10.

transaction_timestamp() cũng làm như vậy, nhưng cái này là một hàm Postgres thích hợp, vì vậy bí danh mặc định luôn là "Transaction_timestamp".

Đừng không nhầm lẫn giữa một trong những chức năng với đặc biệt liên tục đầu vào'now' . Đó chỉ là một trong một số cách viết tắt công chứng cho các giá trị ngày / thời gian / dấu thời gian cụ thể, trích dẫn hướng dẫn:

... sẽ được chuyển đổi thành giá trị ngày / giờ thông thường khi đọc. (Cụ thể nowvà các chuỗi liên quan được chuyển đổi thành giá trị thời gian cụ thể ngay khi chúng được đọc.) Tất cả các giá trị này cần được đặt trong dấu ngoặc đơn khi được sử dụng làm hằng số trong các lệnh SQL.

Nó có thể thêm vào sự nhầm lẫn rằng (tối thiểu Postgres 12) bất kỳ số lượng khoảng trắng và dấu ngoặc (và dấu đầu dòng {[( )]}) nào được cắt bớt từ các giá trị đầu vào đặc biệt đó. Vì vậy 'now()'::timestamptz- hoặc chỉ 'now()'khi không yêu cầu phân loại kiểu rõ ràng - cũng hợp lệ và xảy ra để đánh giá cùng dấu thời gian như hàm now() trong hầu hết các ngữ cảnh . Nhưng đó là các hằng số và thường không phải là những gì bạn muốn làm mặc định cột chẳng hạn.

db <> fiddle ở đây Fiddle SQL

Các lựa chọn thay thế đáng chú ý là statement_timestamp()clock_timestamp(). Hướng dẫn sử dụng:

statement_timestamp()trả về thời gian bắt đầu của câu lệnh hiện tại (cụ thể hơn là thời gian nhận thông báo lệnh mới nhất từ ​​máy khách). [...]
clock_timestamp()trả về thời gian hiện tại thực tế và do đó giá trị của nó thay đổi ngay cả trong một lệnh SQL.

Lưu ý: statement_timestamp()STABLEnhư trên (luôn trả về cùng một giá trị trong cùng một lệnh SQL). Nhưng clock_timestamp()nhất thiết là chỉ VOLATILE. Sự khác biệt có thể là đáng kể.


Nhưng, nó có tạo ra sự khác biệt cho tối ưu hóa truy vấn không? Bây giờ () sẽ được thực thi cho mỗi hàng trong : where items.createddate > now()?
santiago arizti

3
@santiagoarizti: Số now()được xác định STABLEvì nó ước tính cùng giá trị (thời gian bắt đầu của giao dịch hiện tại) trong cùng một giao dịch. Tôi ví dụ của bạn, chỉ now()được thực hiện một lần (trái ngược clock_timestamp()với ví dụ).
Erwin Brandstetter

3

Ngoài ra, chúng không có sự khác biệt về chức năng khi bạn sử dụng chúng đúng cách, chúng được chọn khác nhau:

'now()'recongnized (giống như 'today'hoặc 'now'):

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

'CURRENT_TIMESTAMP'đưa ra lỗi hài hước từ các cạnh tối

Lưu ý: Kể từ phiên bản PostgreSQL 7.2, 'hiện tại' không còn được hỗ trợ dưới dạng hằng số ngày / giờ

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

'transaction_timestamp()'chỉ không được thu lại dưới dạng dấu thời gian với giá trị tz:

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

Xin đừng hỏi tại sao bạn lại chọn 'now()' as timestamp. Tôi đã thấy where timestamp_column = 'now()'thay vì where timestamp_column = now()mã người, vì vậy nghĩ rằng sự làm rõ này sẽ là sự thật buồn cười và bổ sung tốt cho câu trả lời của Erwin.


Đây là một sự hiểu lầm. Chuỗi đầu vào'now()' trông tương tự như chức năng now()trên bề mặt, nhưng không liên quan trực tiếp đến mặt khác. 'now'là một hằng số đánh giá thời gian bắt đầu của giao dịch hiện tại . Parens Trailing được bỏ qua. Nỗ lực để đúc các dây 'CURRENT_TIMESTAMP'hoặc 'transaction_timestamp()'để timestamptrong thời trang tương tự thất bại, bởi vì đó chỉ là vô nghĩa. Không liên quan đến các chức năng tương ứng.
Erwin Brandstetter
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.