English 中文(简体)
Ruby on Rails 和 MSSQL Server: 正在尝试插入具有 newid() 默认值的行。
原标题:
  • 时间:2009-01-23 01:44:32
  •  标签:

这个问题几个月前在另一个论坛上发布过,没有得到任何答案……当时还没有SO!

我在RoR中迈出了第一步。我买了一本介绍Ruby和Ruby On Rails的书,示例在MySQL上正确运行,所以我决定将它们重写为MS-SQL作为一个好的练习(因为MS-SQL是我们的标准数据库)...但结果却变成了一个噩梦。

我有一张表格,含有2个字段。

Tbl_People
----------
id_People        primary key, newid() default value,
namePeople       string

我有一个ODBC连接到数据库。我可以列出记录,但是……我不能在表中插入任何内容。 Ruby生成的INSERT字符串如下:

INSERT INTO Tbl_People (id_People, namePeople) VALUES( newid , GRONDIER, Philippe )

由于字符串“newid”无法插入到唯一标识符/主键字段id_People中,该请求将被拒绝。逻辑上,返回的错误是:

DBI::DatabaseError: 37000 (8169) [Microsoft] [ODBC SQL Server Driver][SQL Server]Conversion failed when converting from a character string to uniqueidentifier

这似乎是一个如此明显的大问题,以至于我感觉漏掉了通常在每个RoR培训文件中都以粗体字写出的东西,如不要尝试通过RoR进行INSERTs,uniqueIdentifier对RoR而言是中文,或者RoR与MS SQL Server不兼容...

有什么想法吗?

问题回答

我不是Ruby的人,所以请记住这一点。在我看来,大多数东西在MySQL->MSSQL翻译中都是无用的。

所以,您的ID类型是“uniqueidentifier”。两种情况应该发生之一:

你应该将NEWID()作为第一个参数传入。不是字符串newid,而是函数NEWID()。

b)不要在第一个参数中传递。由于有默认值,只需插入到NamePeople列中即可。

根据用途,如果您正在处理分布式数据,我只会使用uniqueidentifier主键,并针对大多数关键引用使用良好的INT IDENTITY列。

请查看此帖子,虽然是不同的数据库类型,但本质上是同样的问题,如何隐藏RoR中的默认字段,以避免生成无效插入。

EDIT @wayne-conrad pointed out the old link was dead. I believe the content was that which is found here, http://inodes.org/2008/01/11/rails-activerecord-mysql-guids-and-the-rename_column-bug/

下面是关键的摘录。

The comments section of the page also references a project intended to remedy the problem https://github.com/cch1/uuid_primary_key/tree/master (links don t fail me now!)

 # HACK (JF) - This is too evil to even blog about
  # When we use guid as a primary key we usually rename the original  id 
  # field to  integer_id . We need to hide this from rails so it doesn t
  # mess with it. WARNING: This means once you use usesguid anywhere you can
  # never access a column in any table anywhere called  integer_id 

class ActiveRecord::Base
  private
    alias :original_attributes_with_quotes :attributes_with_quotes

    def attributes_with_quotes(include_primary_key = true, include_readonly_attributes = true)
      quoted = original_attributes_with_quotes(include_primary_key = true, include_readonly_attributes = true)
      quoted.delete( integer_id )
      quoted
    end
end




相关问题
热门标签