【问题标题】:TinyTds::Error: Cannot insert the value NULL into column 'ID'TinyTds::Error: 无法将值 NULL 插入“ID”列
【发布时间】:2019-02-09 04:05:15
【问题描述】:

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

使用 activerecord-sqlserver-adapter、tiny_tds 和 Freetds 我可以连接到新数据库。大多数数据库请求运行良好。

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

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

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

如果使用原始 SQL 执行语句,插入表工作正常,当然我从 INSERT 语句中排除 ID 列。

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

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

Library::Book(id: integer, title: string, isbn: string ...)

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

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

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

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

Library::Book(title: string, isbn: string ...) 如果一个新的插入条目 或者 Library::Book(id: integer, title: string, isbn: string ...) 如果尝试更新条目。

由于施加的限制,我正在使用: 红宝石 2.3.3p222 导轨 4.0.13 活动记录(4.0.13) activerecord-sqlserver-适配器 (4.0.4) tiny_tds (1.0.2) Freetds 1.00.27

【问题讨论】:

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


    【解决方案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
    

    这很麻烦,如果可能,我强烈建议更新该列。

    【讨论】:

    • 谢谢汤姆。这就是我一直试图找到的,一种告诉 Rails ID 列是自动递增类型的方法。我找不到执行此操作的语句或语法。我在模型中有 self.primary_key="id" 。我是否需要修改它或在其他地方定义自动增量属性?我看到的一些建议在我的环境中似乎不受支持。
    • @user321321 我通过迁移更新了我的答案以更改列行为
    • 嗨,汤姆。 Microsoft SQL Server 表是固定的,并且具有这样定义的 ID。我无法改变它。 [ID] [数字](18, 0) IDENTITY(1,1) 非空。上面的迁移会修改数据库的结构吗?
    • @user321321 如果不允许修改数据库,我添加了一种覆盖 Rails 行为的方法。
    • 为什么不self.id ||= Book.maximum(:id).to_i + 1 看起来更简洁一些
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    • 2020-10-21
    • 2013-07-06
    • 2011-12-13
    • 2016-07-05
    • 1970-01-01
    相关资源
    最近更新 更多