我的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
答案 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
这很简陋,如果可能的话,我强烈建议更新此列。