Может CURRENT_TIMESTAMP
быть использован как PRIMARY KEY
?
Есть ли вероятность, что два или более разных INSERT, получат одинаковые CURRENT_TIMESTAMP
?
Может CURRENT_TIMESTAMP
быть использован как PRIMARY KEY
?
Есть ли вероятность, что два или более разных INSERT, получат одинаковые CURRENT_TIMESTAMP
?
Ответы:
Согласно документации , точность CURRENT_TIMESTAMP
составляет микросекунды. Таким образом, вероятность столкновения низкая, но возможная.
Теперь представьте ошибку, которая случается очень редко и вызывает ошибки базы данных. Насколько сложно это отладить? Это гораздо хуже, чем ошибка, которая, по крайней мере, является детерминированной.
Более широкий контекст: вы, вероятно, хотите избежать этих маленьких нюансов с последовательностями, что особенно раздражает, если вы привыкли к MySQL.
Кроме того, если вы используете транзакции (большинство веб-платформ, особенно Java, делают!), То временные метки внутри транзакции будут одинаковыми! Демонстрация:
postgres=# begin;
BEGIN
postgres=# select current_timestamp;
current_timestamp
-------------------------------
2018-08-06 02:41:42.472163+02
(1 Zeile)
postgres=# select current_timestamp;
current_timestamp
-------------------------------
2018-08-06 02:41:42.472163+02
(1 Zeile)
Увидимся? Два выбора, точно такой же результат. Я не печатаю так быстро. ;-)
-
Если вы хотите легко идентификаторы, избегая использования последовательностей, то сгенерируйте некоторое значение хеш-функции из реальных идентификаторов записей. Например, если в вашей базе данных есть люди, и вы знаете, что их дата рождения, девичья фамилия и настоящее имя матери однозначно идентифицируют их, тогда используйте
md5(mother_name || '-' || given_name || '-' birthday);
как идентификатор Кроме того, вы можете использовать CreationDate
столбец, после чего индексируете таблицу, но это не ключ (который является идентификатором).
Ps В общем, это очень хорошая практика, чтобы сделать вашу БД настолько детерминированной, насколько это возможно. Т.е. одна и та же операция должна создать точно такое же изменение в БД . Любой ID на основе отметки времени не выполняет эту важную функцию. Что если вы хотите что-то отладить или смоделировать? Вы воспроизводите операцию, и один и тот же объект будет создан с другим идентификатором ... за ним действительно нетрудно следить, и это экономит много рабочих часов.
Ps2. Любой, кто проверяет ваш код в будущем, не будет иметь лучшего мнения относительно идентификаторов, генерируемых метками времени, по причинам, изложенным выше.
INSERT
несколько строк, они все получают одинаково current_timestamp
. И тогда у вас есть триггеры ...
Не совсем, потому что CURRENT_TIMESTAMP может предоставить два одинаковых значения для двух последующих INSERT (или одного INSERT с несколькими строками).
Вместо этого используйте основанный на времени UUID: uuid_generate_v1mc () .
Строго говоря: Нет. Потому CURRENT_TIMESTAMP
что это функция, и только один или несколько столбцов таблицы могут образовывать PRIMARY KEY
ограничение.
Если вы хотите создать PRIMARY KEY
ограничение для столбца со значением по умолчанию CURRENT_TIMESTAMP
, то ответ: да, вы можете . Ничто не мешает вам делать это, как ничто не мешает вам стрелять яблоками из головы вашего сына. Вопрос все еще не будет иметь смысла, пока вы не определите его цель. Какие данные должны содержать столбец и таблица? Какие правила вы пытаетесь реализовать?
Как правило, эта идея связана нарваться дублирующие ключевыми ошибками , так как CURRENT_TIMESTAMP
это STABLE
функция , возвращающая то же значение для той же самой транзакции (время начала транзакции). Несколько INSERT в одной транзакции обязательно столкнутся - как и другие ответы, уже показанные. Руководство:
Поскольку эти функции возвращают время начала текущей транзакции, их значения не изменяются во время транзакции. Это считается особенностью: цель состоит в том, чтобы позволить одной транзакции иметь согласованное представление о «текущем» времени, так чтобы несколько модификаций в одной транзакции имели одинаковую отметку времени.
Метки времени Postgres реализованы в виде 8-байтовых целых чисел, представляющих до 6 дробных цифр (микросекундное разрешение).
Если вы создаете таблицу, которая должна содержать не более одной строки в микросекунду, и это условие не изменится (что-то с именем sensor_reading_per_microsecond
), то это может иметь смысл. Дублирующиеся строки должны вызывать ошибку нарушения дублирующего ключа. Это экзотическое исключение. И тип данных timestamptz
(не timestamp
), вероятно, будет предпочтительнее. Увидеть:
Я все еще предпочел бы использовать суррогатный серийный первичный ключ вместо этого. И добавьте UNIQUE
ограничение на столбец отметки времени. Меньше возможных осложнений, не опираясь на детали реализации СУБД.
sensor_reading_per_microsecond
может столкнуться, если вы не можете абсолютно гарантировать, что синхронизация каждого чтения идеально синхронизирована относительно предыдущего; отклонение на микросекунду (что часто не невозможно) нарушает схему. В общем, я бы до сих пор полностью этого избегал. (Имейте в виду, как вы указали, в таком случае результирующее столкновение может быть желательным!)