Как обновить или вставить набор данных Sequel? - PullRequest
12 голосов
/ 19 марта 2012

Я только начал использовать Sequel в очень маленьком приложении Sinatra. Поскольку у меня есть только одна таблица БД, мне не нужно использовать модели.

Я хочу обновить запись, если она существует, или вставить новую запись, если ее нет. Я придумал следующее решение:

  rec = $nums.where(:number => n, :type => t)
  if $nums.select(1).where(rec.exists)
    rec.update(:counter => :counter + 1)
  else
    $nums.insert(:number => n, :counter => 1, :type => t)
  end

Где $nums - это DB[:numbers] набор данных.

Я считаю, что этот способ не самая элегантная реализация поведения "обновить или вставить".

Как это сделать?

Ответы [ 4 ]

17 голосов
/ 28 марта 2012

Вы, вероятно, не должны проверять перед обновлением / вставкой; потому что:

  1. Это дополнительный вызов БД.
  2. Это может привести к состоянию гонки.

Вместо этого вы должны проверить возвращаемое значение обновления:

rec = $nums.where(:number => n, :type => t)
if 1 != rec.update(:counter => :counter + 1)
  $nums.insert(:number => n, :counter => 1, :type => t)
end
11 голосов
/ 20 января 2016

Добавлено продолжение 4.25.0 (выпущено 31 июля 2015 г.) insert_conflict для Postgres v9.5 +
Продолжение 4.30.0 (выпущено 4 января 2016 г.) добавлено insert_conflict для SQLite

Это можно использовать для вставки или обновления строки, например:

DB[:table_name].insert_conflict(:update).insert( number:n, type:t, counter:c )
3 голосов
/ 19 марта 2012

Я полагаю, что вы не можете сделать это намного чище (хотя некоторые базы данных имеют определенный синтаксис upsert, который может быть поддерживается Sequel ).Вы можете просто обернуть то, что у вас есть, в отдельный метод и притвориться, что его не существует.:)

Всего пара предложений:

  • Заключить все в транзакцию.
  • Создать уникальный индекс для (number, type) полей.
  • Не 't использовать глобальные переменные.
1 голос
/ 05 июля 2012

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

...