PostgreSQL'de bir zaman damgasını otomatik olarak nasıl güncellerim


133

MySQL'de CURRENT_TIMESTAMP kullanarak yapabildiğim gibi, yeni bir satır eklendiğinde kodun zaman damgasını otomatik olarak güncelleyebilmesini istiyorum.

Bunu PostgreSQL'de nasıl başarabilirim?

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

6
Bu arada, veri türünüz timestampSQL spesifikasyonu tarafından kısaltması olarak tanımlanır TIMESTAMP WITHOUT TIME ZONE. Postgres uzmanı David E. Wheeler'ın açıkladığı gibi, neredeyse kesinlikle istediğiniz şey bu değil . Diğer tür, TIMESTAMP WITH TIME ZONEmuhtemelen istediğiniz şeydir, tarih-saati UTC'ye ayarlamak için geçmiş saat dilimi fark bilgilerini kullanarak (ancak tür adına rağmen bu saat dilimi bilgilerini depolamadan).
Basil Bourque

3
Bunu tekrar öğrendikten sonra, varsayılan, işlev ve tetikleyici kullanarak bir satırın hem oluşturulma hem de değiştirilme tarihini günlüğe kaydetme hakkında ayrıntılı bir blog yazısı yazdım . Postgres'te kullanılmak üzere eksiksiz örnek SQL ve PL / pgSQL kodunu içerir.
Basil Bourque

Yanıtlar:


197

Sütunu ekleme sırasında doldurmak için bir DEFAULTdeğer kullanın :

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

İfadede bir değer sağlanarak bu sütunun değerinin açıkça üzerine yazılabileceğini unutmayın INSERT. Bunu önlemek istiyorsanız bir tetikleyiciye ihtiyacınız var .

Ayrıca, satır her güncellendiğinde bu sütunu güncellemeniz gerekirse de bir tetikleyiciye ihtiyacınız vardır ( EJ Brennan )

Sütun adları için ayrılmış sözcükler kullanmanın genellikle iyi bir fikir olmadığını unutmayın. Şundan farklı bir isim bulmalısıntimestamp


14
Postgres'in size (1) mevcut anın zamanını, (2) ifadenin başladığı zamanı ve (3) işlemin başladığı zamanı söyleyen işlevleri olduğunu unutmayın. Burada gösterilen örnek, cari işlemin başlangıcıdır. Diğer iki olasılığın aksine bunu isteyebilir veya istemeyebilirsiniz.
Basil Bourque

6
Ayrılmış sözcüklerle çakışan isimlerden kaçınmak konusunda iyi bir bonus. SQL spesifikasyonunun, sondaki bir alt çizgiyi asla ayrılmış bir sözcük olarak kullanmayacağına açıkça söz verdiğini unutmayın. Böylece timestampgirebilirsin timestamp_. Daha da iyisi gibi daha açıklayıcı bir isim olurdu row_created_.
Basil Bourque

İlk yarı, OP'nin sorduğu şey değil, ikinci yarı başka bir yanıta atıfta bulunmasına rağmen (ki bu doğru), ama yine de yanıltıcı. Bu cevap olarak kabul edilmemelidir.
Eric Wang

1
Türlerin Postgres belgelerinde öyle söylüyor. Varchar, kısıtlamayı kontrol etmek için ekstra CPU döngülerine sahiptir, bu TEXT'te olmaz.
Rahly

3
tek bir alanla değil, ancak tek bir alan içeren kullanışlı bir tablo görmedim. Bu kısıtlama alanların sayısı ile birleştirilir. Bir tablodaki tüm varchar'ları metne dönüştürdüğümü hatırlıyorum ve% 15 yazma artışı kazandım. Ayrıca, küçük performans cezası "HAYIR" performans cezası değildir.
Rahly

104

Kayıt değiştirildiğinde değişmesini istiyorsanız, bir ekleme tetikleyicisi ve olası bir güncelleme tetikleyicisi yazmanız gerekir. Bu makale bunu oldukça güzel bir şekilde açıklıyor:

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

Tetiği şu şekilde uygulayın:

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

2
Bu, en iyi cevaptır, IMO (yine de, bir varsayılan, ekleme için yeterlidir).
kik

2
Burada YENİ Neler Var?
Naveen


Bu, ilk INSERT'ler ve sonraki GÜNCELLEMELER (veri denetimi için iyidir) ile çalışacak daha eksiksiz bir çözümdür. Kabul edildiğinde, OP sadece ilkini sorar.
Pavel Lechev

5
@Naveen çok değil, sende yeni ne var?
Underyx

57

Zaman damgasını güncelleme, sadece değerler değiştiğinde

EJ'nin bağlantısına göre ve bu bağlantıdan bir if ifadesi ekleyin ( 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

Varsayılan değer olarak 'now ()' kullanılması otomatik olarak zaman damgası oluşturur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.