Làm cách nào để tự động cập nhật dấu thời gian trong PostgreSQL


132

Tôi muốn mã có thể tự động cập nhật dấu thời gian khi một hàng mới được chèn như tôi có thể làm trong MySQL bằng cách sử dụng CURRENT_TIMESTAMP.

Làm thế nào tôi có thể đạt được điều này trong PostgreSQL?

CREATE TABLE users (
    id serial not null,
    firstname varchar(100),
    middlename varchar(100),
    lastname varchar(100),
    email varchar(200),
    timestamp timestamp
)

6
Nhân tiện, kiểu dữ liệu của bạn timestampđược xác định bởi đặc tả SQL là tên viết tắt của TIMESTAMP WITHOUT TIME ZONE. Đó gần như chắc chắn không phải là điều bạn muốn, như David E. Wheeler, chuyên gia của Postgres giải thích . Loại khác, TIMESTAMP WITH TIME ZONEcó thể là những gì bạn muốn, sử dụng bất kỳ thông tin bù múi giờ nào đã qua để điều chỉnh thời gian ngày thành UTC (nhưng không thực sự lưu trữ thông tin múi giờ đó mặc dù tên loại).
Basil Bourque

3
Sau khi học lại điều này một lần nữa, tôi đã viết một bài đăng trên blog chi tiết về việc ghi lại thời gian ngày của cả việc tạo và sửa đổi hàng bằng cách sử dụng mặc định, chức năng và kích hoạt. Bao gồm ví dụ hoàn chỉnh mã SQL và PL / pgSQL để sử dụng trong Postgres.
Basil Bourque

Câu trả lời:


197

Để điền cột trong khi chèn, sử dụng một DEFAULTgiá trị:

CREATE TABLE users (
  id serial not null,
  firstname varchar(100),
  middlename varchar(100),
  lastname varchar(100),
  email varchar(200),
  timestamp timestamp default current_timestamp
)

Lưu ý rằng giá trị cho cột đó có thể được ghi đè rõ ràng bằng cách cung cấp một giá trị trong INSERTcâu lệnh. Nếu bạn muốn ngăn chặn rằng bạn cần một kích hoạt .

Bạn cũng cần một trình kích hoạt nếu bạn cần cập nhật cột đó bất cứ khi nào hàng được cập nhật (như được đề cập bởi EJ Brennan )

Lưu ý rằng sử dụng các từ dành riêng cho tên cột thường không phải là một ý tưởng tốt. Bạn nên tìm một cái tên kháctimestamp


14
Xin lưu ý rằng Postgres có các chức năng cho bạn biết (1) thời gian của thời điểm hiện tại thực tế, (2) thời gian tuyên bố bắt đầu và (3) thời gian giao dịch bắt đầu. Ví dụ hiển thị ở đây là bắt đầu giao dịch hiện tại. Bạn có thể hoặc không muốn điều đó trái ngược với hai khả năng khác.
Basil Bourque

6
Điểm thưởng tốt về việc tránh các tên va chạm với các từ dành riêng. Lưu ý rằng đặc tả SQL hứa hẹn sẽ không bao giờ sử dụng dấu gạch dưới dưới dạng từ dành riêng. Vì vậy, bạn có thể làm cho timestampvào timestamp_. Thậm chí tốt hơn sẽ là một tên mô tả nhiều hơn như row_created_.
Basil Bourque

Nửa đầu không phải là những gì OP yêu cầu, mặc dù nửa sau đề cập đến câu trả lời khác (đúng), nhưng nó vẫn gây hiểu nhầm. Điều này không nên được chấp nhận là câu trả lời.
Eric Wang

1
Nói như vậy trong tài liệu Postgres của các loại. Varchar có các chu kỳ CPU bổ sung để kiểm tra các ràng buộc, điều này không xảy ra trên TEXT.
Rahly

3
không phải với một trường duy nhất, nhưng tôi chưa bao giờ thấy một bảng hữu ích với một trường duy nhất. Ràng buộc này được gộp bởi số lượng các trường. Tôi nhớ đã thay đổi tất cả các varchar trong một bảng thành văn bản và đã cải thiện 15% viết. Ngoài ra, hình phạt hiệu suất nhỏ không phải là hình phạt hiệu suất "KHÔNG".
Rahly

104

Bạn sẽ cần phải viết một trình kích hoạt chèn và có thể là một trình kích hoạt cập nhật nếu bạn muốn nó thay đổi khi bản ghi được thay đổi. Bài viết này giải thích nó khá độc đáo:

http://www.revsys.com/blog/2006/aug/04/automatically-updating-a-timestamp-column-in-postgresql/

CREATE OR REPLACE FUNCTION update_modified_column()   
RETURNS TRIGGER AS $$
BEGIN
    NEW.modified = now();
    RETURN NEW;   
END;
$$ language 'plpgsql';

Áp dụng kích hoạt như thế này:

CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON customer FOR EACH ROW EXECUTE PROCEDURE  update_modified_column();

2
Đây là câu trả lời tốt nhất, IMO (mặc dù, mặc định là đủ để chèn).
kik

2
Có gì mới ở đây?
Naveen


Đây là một giải pháp hoàn chỉnh hơn sẽ hoạt động với các INSERT ban đầu cũng như mọi CẬP NHẬT tiếp theo (tốt cho kiểm toán dữ liệu). Cấp, OP chỉ yêu cầu trước đây.
Pavel Lechev

5
@Naveen không nhiều, có gì mới với bạn?
Underyx

57

Cập nhật dấu thời gian, chỉ khi các giá trị thay đổi

Dựa trên liên kết của EJ và thêm câu lệnh if từ liên kết này ( https://stackoverflow.com/a/3084254/1526023 )

CREATE OR REPLACE FUNCTION update_modified_column()
RETURNS TRIGGER AS $$
BEGIN
   IF row(NEW.*) IS DISTINCT FROM row(OLD.*) THEN
      NEW.modified = now(); 
      RETURN NEW;
   ELSE
      RETURN OLD;
   END IF;
END;
$$ language 'plpgsql';

9

Sử dụng 'now ()' làm giá trị mặc định sẽ tự động tạo dấu thời gian.

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.