Как работает функция upsert в Rails? - PullRequest
1 голос
/ 08 ноября 2019

Поскольку upsert является «более новой» функцией, которая была реализована в Rails ActiveRecord, за ней не так много документации. Я понимаю концепцию, стоящую за этим, поскольку ее цель - вставить новую запись, если это новая запись, и обновить существующие записи, если она найдена в базе данных.

Так, например, когда я вызываю: Model.upsert(name: 'a', number: 1), ActiveRecord ищет предварительно существующую запись с именем: 'a' или ранее существующую запись с номером: 1?

Например, прямо сейчас, когда я пытаюсь обновить модель с именем aиспользуя Model.upsert(name: 'a', number: 1), я получаю NotNullViolation, потому что в идентификаторе есть нулевое значение, которое я не указываю. Могу ли я обновить модель с помощью upsert без указания идентификатора в качестве параметра?

1 Ответ

3 голосов
/ 08 ноября 2019

Реализация будет отличаться в зависимости от целевой базы данных. Postgres, например, изначально поддерживает upserts через INSERT ... ON CONFLICT UPDATE . Вы должны обратиться к документации вашей базовой базы данных для подробностей. В общем, однако, ActiveRecord попытается использовать все уникальные индексы в таблице, чтобы определить, конфликтует ли существующая запись или нет. Как минимум, это означает, что ваш первичный ключ, хотя это может означать и другие. Если вы используете Postgres или SQLite, вы можете передать :unique_by для подтверждения, чтобы явно указать, какие поля следует использовать, чтобы определить, существует ли соответствующая запись ( doc ). Обратите внимание, что если вы используете это и попытаетесь вставить запись, которая конфликтует с другой записью по уникальному ключу, не указанному в unique_by, ваша база данных выдаст исключение.

Я получу NotNullViolation, потому чтов идентификаторе есть нулевое значение, которое я не указываю.

Нет, конечно, нет - вы должны указать все поля, которые будут вставлены во время вставки при выполнении upsert, потому что, очевидно, если запись не существует и должна быть вставлена, она должна содержатьвсе необходимые поля. Если у вас есть поля, указанные как ненулевые, вы не можете попытаться их удалить, когда вставленное значение будет нулевым!

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

...