TinyTds :: Error: невозможно вставить значение NULL в столбец 'ID' - PullRequest
0 голосов
/ 08 февраля 2019

Моя система Ruby on Rails переходит от Oracle к Microsoft SQL Server 2012. Внутренняя база данных уже преобразована третьей частью из Oracle в Microsoft SQL Server.У меня нет контроля над структурой схемы.Это невозможно изменить.

Используя activerecord-sqlserver-adapter, tiny_tds и Freetds, я могу подключиться к новой базе данных.Большинство запросов к БД работают хорошо.

Однако многие таблицы имеют идентификаторы первичных ключей, которые автоматически увеличиваются SQL Server, другими словами, столбцы PK IDENTITY (1,1).Тот же код, который работал с соединениями Oracle, завершается с ошибкой в ​​SQL Server со следующей ошибкой:

TinyTds :: Ошибка: невозможно вставить значение NULL в столбец 'ID'

Я знаю, почему это происходит, поскольку столбец ID действительно является ключом primary_key и столбцом IDENTITY (1,1) и содержит ограничение NOT NULL.Это хорошо.

Вставка в таблицу работает нормально, если используются необработанные операторы SQL, где, конечно, я исключаю столбец ID из оператора INSERT.

Однако я потратил несколько дней на поиски в Google и не могу найти способ сказать Ruby on Rails не пытаться сохранять столбец ID.

Итак, у меня есть экземпляр класса @book,который содержит

Library :: Book (id: целое число, заголовок: строка, isbn: строка ...)

Когда я делаю @ book.save!он генерирует вышеуказанную ошибку.

@book = Library::Book.new( .. )
:
:
@book.save!

TinyTds :: Error: Невозможно вставить значение NULL в столбец 'ID'

Скорее, что прибегать к голому методу SQL,как мне сделать что-то более Railsy и сказать, что я хочу сохранить запись, но не пытаться сохранить поле идентификатора, поскольку оно автоматически увеличивается?Поэтому эффективно я пытаюсь сохранить

Library :: Book (title: string, isbn: string ...), если новая запись вставки или Library :: Book (id: integer, title: string, isbn:строка ...) при попытке обновить запись.

Из-за наложенных ограничений я использую: Ruby 2.3.3p222 Rails 4.0.13 activerecord (4.0.13) activerecord-sqlserver-adapter (4.0.4)tiny_tds (1.0.2) Freetds 1.00.27

1 Ответ

0 голосов
/ 08 февраля 2019

Вы можете использовать ActiveRecord :: Relation # find_or_initialize_by .Это предполагает, что у вас достаточно атрибутов, известных на тот момент, чтобы однозначно идентифицировать запись.

Это решит последнюю часть вашего вопроса.Но похоже, что для столбца id не установлено автоматическое увеличение.Вам нужно установить это так, чтобы при отправке Rails идентификатора null БД установила его правильно.

Обновление: чтобы сделать автоинкремент столбца, вам потребуется запустить миграцию.Затем вы можете сделать:

Alter table books modify column id int(11) auto_increment;

Обновление: если мы не можем изменить базу данных, мы можем сделать:

class Book

  private

  def create_or_update(*args, &block)
    self.id ||= Book.maximum(:id) + 1
    super
  rescue ActiveRecord::RecordNotUnique
    self.id = nil
    retry
  end
end

Это довольно неудобно, и я настоятельно рекомендую обновить столбец, если это возможно.

...