TinyTds :: Error:无法将值NULL插入列“ ID”

时间:2019-02-08 12:33:38

标签: ruby-on-rails ruby activerecord sql-server-2012 tiny-tds

我的Ruby on Rails系统正在从Oracle迁移到Microsoft SQL Server2012。第三方已经将后端数据库从Oracle转换为Microsoft SQL Server。我无法控制架构结构。这不能更改。

使用activerecord-sqlserver-adapter,tiny_tds和Freetds,我可以连接到新数据库。大多数数据库请求都能正常工作。

但是,许多表具有ID主键,这些主键由SQL Server自动递增,即PK IDENTITY(1,1)列。在SQL Server下,用于Oracle连接的相同代码失败,并显示以下错误:

  

TinyTds :: Error:无法将值NULL插入列“ ID”

我知道为什么要这样做,因为ID列确实是primary_key和IDENTITY(1,1)列,并且包含NOT NULL限制。那也行。

如果使用原始SQL执行语句,则插入表中的效果很好,当然我要从INSERT语句中排除ID列。

但是我花了几天的时间进行谷歌搜索,却找不到告诉Ruby on Rails不要尝试保存ID列的方法。

所以我有一个@book类的实例,其中包含

Library :: Book(id:整数,title:字符串,isbn:字符串...)

当我执行@ book.save时!它会产生上述错误。

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

TinyTds :: Error:无法将值NULL插入列“ ID”

而是诉诸于裸机SQL,我该如何做更多的Railsy并告诉它我要保存记录,但不尝试保存ID字段,因为它是自动递增的?如此有效地我试图保存

Library :: Book(标题:字符串,isbn:字符串...),如果有新的插入项 要么 Library :: Book(id:整数,title:字符串,isbn:字符串...)如果尝试更新条目。

由于受到限制,我正在使用: Ruby 2.3.3p222 Rails 4.0.13 活动记录(4.0.13) activerecord-sqlserver适配器(4.0.4) tiny_tds(1.0.2) Freetds 1.00.27

1 个答案:

答案 0 :(得分:1)

您可以使用ActiveRecord::Relation#find_or_initialize_by。假设您当时拥有足够的属性来唯一地标识记录。

那将解决您问题的最后一部分。但是听起来id列未设置为自动递增。您需要进行设置,以便当Rails发送null id时,数据库会正确设置它。

更新:要使列自动递增,您将需要运行迁移。然后,您可以这样做:

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

这很简陋,如果可能的话,我强烈建议更新此列。