Як автоматично оновлювати часову позначку в PostgreSQL


132

Я хочу, щоб код міг автоматично оновлювати часову марку, коли вставляється новий рядок, як це можна зробити в MySQL за допомогою CURRENT_TIMESTAMP.

Як я зможу досягти цього в PostgreSQL?

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

6
До речі, ваш тип даних timestampвизначається специфікацією SQL як абревіатура TIMESTAMP WITHOUT TIME ZONE. Це майже точно не те, що ви хочете, як пояснив експерт з постгресу Девід Е. Уілер . Інший тип - TIMESTAMP WITH TIME ZONEце, мабуть, те, що ви хочете, використовуючи будь-яку інформацію про зміщення часового поясу, щоб змінити дату часу на UTC (але насправді не зберігає інформацію про цей часовий пояс, незважаючи на назву типу).
Василь Бурк

3
Після того, як ще раз дізнався про це, я написав докладний пост у блозі про реєстрацію дати та часу створення та модифікації рядка, використовуючи за замовчуванням, функцією та тригером. Включає повний приклад SQL та PL / pgSQL-код для використання в Postgres.
Василь Бурк

Відповіді:


197

Щоб заповнити стовпчик під час вставки, використовуйте DEFAULTзначення:

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

Зауважте, що значення для цього стовпця явно можна перезаписати, подавши значення в INSERTоператорі. Якщо ви хочете запобігти, вам потрібен тригер .

Вам також потрібен тригер, якщо вам потрібно оновлювати цей стовпець щоразу, коли рядок оновлюється (як згадує Е. Дж. Бренан )

Зауважте, що використання зарезервованих слів для назв стовпців зазвичай не є хорошою ідеєю. Ви повинні знайти інше ім'я, ніж теtimestamp


14
Майте на увазі, що Postgres має функції повідомляти вам (1) час фактичного поточного моменту, (2) час запуску заяви і (3) час початку транзакції. Наведений тут приклад - початок поточної транзакції. Ви можете чи не хочете цього, на відміну від двох інших можливостей.
Василь Бурк

6
Хороший бонусний бал про уникнення імен, які стикаються із зарезервованими словами. Зауважте, що специфікація SQL явно обіцяє ніколи не використовувати зворотний підкреслення як зарезервоване слово. Так що ви можете зробити timestampв timestamp_. Ще краще було б більш описовою назвою sucha як row_created_.
Василь Бурк

Перша половина - це не те, що запитувала ОП, навіть якщо друга половина посилалася на іншу відповідь (яка є правильною), але вона все одно вводить в оману. Це не слід сприймати як відповідь.
Ерік Ван

1
Так сказано в документації Postgres про типи. У Varchar є додаткові цикли процесора, щоб перевірити наявність обмежень, що не відбувається в TEXT.
Ралі

3
не з одним полем, але я ніколи не бачив корисної таблиці з одним полем. Це обмеження ускладнюється кількістю полів. Я пам'ятаю, як змінив усі варшари в таблиці на текстові та отримав 15% покращення в написанні. Крім того, невеликий штрафний показник - це не "НІ".
Рахлі

104

Вам потрібно буде написати тригер вставки та можливий тригер оновлення, якщо ви хочете, щоб він змінився, коли запис змінено. Ця стаття пояснює це досить непогано:

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

Застосувати тригер так:

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

2
Це найкраща відповідь, IMO (хоча для вставки достатньо за замовчуванням).
kik

2
Що тут НОВОГО?
Naveen


Це більш повне рішення, яке б працювало з початковими INSERT, а також з усіма наступними оновленнями (корисно для аудиту даних). Зрозуміло, ОП просить лише колишнього.
Павло Лечев

5
@Naveen не так багато, що нового у вас?
Underyx

57

Оновлення часової позначки, лише якщо значення змінилися

На основі посилання EJ та додайте вислів if із цього посилання ( 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

Використовуючи "зараз ()" як значення за замовчуванням, автоматично генерується часова марка.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.