在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保存。
我该如何解决?
答案 0 :(得分:6)
我认为您的问题是您手动设置所有这些,而不是使用serial
列。当您使用serial
列时,PostgreSQL将创建序列,设置适当的默认值,并确保序列归所讨论的表和列所有。来自fine manual:
pg_get_serial_sequence(table_name, column_name)
获取serial或bigserial列使用的序列的名称
但您没有使用serial
或bigserial
,因此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)