新分配的序列不起作用

时间:2012-05-11 06:59:07

标签: ruby-on-rails ruby-on-rails-3 postgresql activerecord rails-postgresql

在PostgreSQL中,我创建了一个新表,并为id列分配了一个新序列。如果我从PostgreSQL控制台插入一条记录它可以工作,但是当我尝试从Rails导入一个记录时,它会引发一个异常,它无法找到相关的序列。

这是表格:

\d+ user_messages;
                                                  Table "public.user_messages"
   Column    |            Type             |                         Modifiers                          | Storage  | Description 
-------------+-----------------------------+------------------------------------------------------------+----------+-------------
 id          | integer                     | not null default nextval('new_user_messages_id'::regclass) | plain    | 

但是当我尝试使用Rails使用的SQL查询获取序列时,它返回NULL:

select pg_catalog.pg_get_serial_sequence('user_messages', 'id');
 pg_get_serial_sequence 
------------------------

(1 row)

Rails引发的错误是:

UserMessage.import [UserMessage.new]
NoMethodError: undefined method `split' for nil:NilClass
    from /app/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.3/lib/active_record/connection_adapters/postgresql_adapter.rb:910:in `default_sequence_name'

仅当我使用ActiveRecord扩展程序导入批量记录时才会出现此问题,单个记录通过ActiveRecord保存。

我该如何解决?

1 个答案:

答案 0 :(得分:6)

我认为您的问题是您手动设置所有这些,而不是使用serial列。当您使用serial列时,PostgreSQL将创建序列,设置适当的默认值,并确保序列归所讨论的表和列所有。来自fine manual

  

pg_get_serial_sequence(table_name, column_name)
  获取serial或bigserial列使用的序列的名称

但您没有使用serialbigserial,因此pg_get_serial_sequence无效。

您可以通过以下方式解决此问题:

alter sequence new_user_messages_id owned by user_messages.id

我不确定这是否是一个完整的解决方案而且有人(喜欢Erwin)可能会填补缺失的部分。

使用serial作为id列的数据类型,可以为您节省一些麻烦。这将为你创建和连接序列。

例如:

=> create sequence seq_test_id;
=> create table seq_test (id integer not null default nextval('seq_test_id'::regclass));
=> select pg_catalog.pg_get_serial_sequence('seq_test','id');
 pg_get_serial_sequence 
------------------------

(1 row)
=> alter sequence seq_test_id owned by seq_test.id;
=> select pg_catalog.pg_get_serial_sequence('seq_test','id');
 pg_get_serial_sequence 
------------------------
 public.seq_test_id
(1 row)