Bagaimana cara saya memperbarui cap waktu secara otomatis di PostgreSQL

132

Saya ingin kode dapat secara otomatis memperbarui cap waktu ketika baris baru dimasukkan seperti yang dapat saya lakukan di MySQL menggunakan CURRENT_TIMESTAMP.

Bagaimana saya bisa mencapai ini di PostgreSQL?

CREATE TABLE users (
    id serial not null,
    firstname varchar(100),
    middlename varchar(100),
    lastname varchar(100),
    email varchar(200),
    timestamp timestamp
)
Harun
sumber
6
Omong-omong, tipe data Anda timestampdidefinisikan oleh spesifikasi SQL sebagai singkatan dari TIMESTAMP WITHOUT TIME ZONE. Itu hampir pasti bukan yang Anda inginkan, seperti dijelaskan oleh pakar Postgres David E. Wheeler . Jenis yang lain, TIMESTAMP WITH TIME ZONEmungkin yang Anda inginkan, menggunakan informasi offset zona waktu yang dilewati untuk menyesuaikan tanggal-waktu ke UTC (tetapi tidak benar-benar menyimpan info zona waktu tersebut terlepas dari nama jenisnya).
Basil Bourque
3
Setelah mempelajarinya lagi, saya menulis posting blog terperinci tentang mencatat waktu pembuatan dan modifikasi baris menggunakan default, fungsi, dan pemicu. Termasuk contoh lengkap kode SQL dan PL / pgSQL untuk digunakan di Postgres.
Basil Bourque

Jawaban:

197

Untuk mengisi kolom selama menyisipkan, gunakan DEFAULTnilai:

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

Perhatikan bahwa nilai untuk kolom itu dapat secara eksplisit ditimpa dengan memberikan nilai dalam INSERTpernyataan. Jika Anda ingin mencegahnya, Anda memang perlu pemicu .

Anda juga perlu pemicu jika Anda perlu memperbarui kolom itu setiap kali baris diperbarui (sebagai disebutkan oleh EJ Brennan )

Perhatikan bahwa menggunakan kata yang dipesan untuk nama kolom biasanya bukan ide yang baik. Anda harus menemukan nama yang berbeda daritimestamp

seekor kuda tanpa nama
sumber
14
Ketahuilah bahwa Postgres memiliki fungsi untuk memberi tahu Anda (1) waktu saat aktual saat ini, (2) waktu pernyataan dimulai, dan (3) waktu transaksi dimulai. Contoh yang ditunjukkan di sini adalah mulai dari transaksi saat ini. Anda mungkin atau mungkin tidak ingin itu bertentangan dengan dua kemungkinan lainnya.
Basil Bourque
6
Poin bonus yang bagus tentang menghindari nama yang bertabrakan dengan kata-kata yang dipesan. Perhatikan bahwa spesifikasi SQL secara eksplisit berjanji untuk tidak pernah menggunakan garis bawah trailing sebagai kata yang dilindungi undang-undang. Jadi Anda bisa membuatnya timestampmenjadi timestamp_. Bahkan yang lebih baik adalah nama yang lebih deskriptif seperti row_created_.
Basil Bourque
Babak pertama bukanlah apa yang diminta OP sama sekali, meskipun bagian kedua mengacu pada jawaban lain (yang benar), tetapi masih menyesatkan. Ini tidak boleh diterima sebagai jawaban.
Eric Wang
1
Mengatakan demikian dalam dokumentasi jenis Postgres. Varchar memiliki siklus CPU tambahan untuk memeriksa kendala, yang tidak terjadi pada TEXT.
Rahly
3
tidak dengan satu bidang, tapi saya belum pernah melihat tabel yang berguna dengan satu bidang. Batasan ini diperparah dengan jumlah bidang. Saya ingat mengubah semua varchar dalam tabel menjadi teks dan mendapatkan peningkatan penulisan 15%. Juga, penalti kinerja kecil bukan penalti kinerja "TIDAK".
Rahly
104

Anda harus menulis pemicu yang disisipkan, dan kemungkinan pemicu pembaruan jika Anda ingin mengubahnya ketika catatan diubah. Artikel ini menjelaskannya dengan cukup baik:

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';

Terapkan pemicu seperti ini:

CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON customer FOR EACH ROW EXECUTE PROCEDURE  update_modified_column();
EJ Brennan
sumber
2
Ini adalah jawaban terbaik, IMO (walaupun, standar sudah cukup untuk dimasukkan).
kik
2
Apa yang BARU di sini?
Naveen
Ini adalah solusi yang lebih lengkap yang akan bekerja dengan INSERT awal serta setiap UPDATE berikutnya (baik untuk audit data). Memang, OP hanya meminta yang pertama.
Pavel Lechev
5
@ Tidak banyak, apa yang baru dengan Anda?
Underyx
57

Memperbarui cap waktu, hanya jika nilainya berubah

Berdasarkan tautan EJ dan tambahkan pernyataan if dari tautan ini ( 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';
Jim Yu
sumber
9

Menggunakan 'now ()' sebagai nilai default secara otomatis menghasilkan cap waktu.

Parichay Mo
sumber