Как автоматически обновить метку времени в PostgreSQL


134

Я хочу, чтобы код мог автоматически обновлять отметку времени при вставке новой строки, как я могу это сделать в 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. Как объяснил эксперт Postgres Дэвид Уиллер, это почти наверняка не то, что вам нужно . Другой тип, TIMESTAMP WITH TIME ZONEвероятно, то, что вы хотите, используя любую переданную информацию о смещении часового пояса для настройки даты и времени на UTC (но фактически не сохраняя информацию о часовом поясе, несмотря на имя типа).
Basil Bourque

3
Узнав об этом еще раз, я написал подробное сообщение в блоге о регистрации даты и времени создания и изменения строки с использованием значений по умолчанию, функции и триггера. Включает полный пример кода SQL и PL / pgSQL для использования в Postgres.
Basil Bourque

Ответы:


198

Чтобы заполнить столбец во время вставки, используйте 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операторе. Если вы хотите предотвратить это, вам нужен триггер .

Вам также понадобится триггер, если вам нужно обновлять этот столбец всякий раз, когда обновляется строка (как упоминалось EJ Brennan )

Обратите внимание, что использование зарезервированных слов для имен столбцов обычно не является хорошей идеей. Вы должны найти другое имя, чемtimestamp


14
Имейте в виду, что в Postgres есть функции, которые сообщают вам (1) время фактического текущего момента, (2) время запуска оператора и (3) время начала транзакции. Показанный здесь пример - начало текущей транзакции. Вы можете захотеть или не захотеть этого в отличие от двух других возможностей.
Basil Bourque

6
Хороший бонус в том, чтобы избегать имен, которые противоречат зарезервированным словам. Обратите внимание, что спецификация SQL явно обещает никогда не использовать завершающее подчеркивание в качестве зарезервированного слова. Так что вы можете превратиться timestampв timestamp_. Еще лучше было бы более описательное имя, например, как row_created_.
Basil Bourque

Первая половина - это совсем не то, о чем спрашивал ОП, хотя вторая половина ссылалась на другой ответ (который правильный), но это все еще вводит в заблуждение. Это не следует принимать в качестве ответа.
Эрик Ван

1
Об этом говорится в документации типов Postgres. У Varchar есть дополнительные циклы ЦП для проверки ограничения, чего не происходит в TEXT.
Rahly

3
не с одним полем, но я никогда не видел полезной таблицы с одним полем. Это ограничение усугубляется количеством полей. Я помню, как изменил все varchar в таблице на текст и получил улучшение письма на 15%. Кроме того, небольшое снижение производительности не означает «НЕТ» ухудшения производительности.
Rahly

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, так и с любыми последующими UPDATE (подходит для аудита данных). Конечно, ОП запрашивает только первое.
Павел Лечев

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.