Ruby on rails RubyonRails+;PostgreSQL:自定义序列的使用

Ruby on rails RubyonRails+;PostgreSQL:自定义序列的使用,ruby-on-rails,postgresql,activerecord,save,rails-postgresql,Ruby On Rails,Postgresql,Activerecord,Save,Rails Postgresql,假设我有一个名为Transaction的模型,它有一个:Transaction\u code属性。 我希望该属性自动填充一个序列号,该序列号可能不同于id(例如id=1的交易可能有Transaction\u code=1000) 我尝试在postgres上创建一个序列,然后将transaction\u code列的默认值设置为该序列的nextval。 问题是,如果我没有为RoR上的@transaction.transaction\u code赋值,当我在RoR上发出@transaction.sa

假设我有一个名为
Transaction
的模型,它有一个
:Transaction\u code
属性。 我希望该属性自动填充一个序列号,该序列号可能不同于
id
(例如
id=1
的交易可能有
Transaction\u code=1000

我尝试在postgres上创建一个序列,然后将
transaction\u code
列的默认值设置为该序列的
nextval
。 问题是,如果我没有为RoR上的
@transaction.transaction\u code
赋值,当我在RoR上发出
@transaction.save
时,它会尝试执行以下SQL操作:

插入事务(事务代码)值(空)

这样做的目的是在Transactions表上创建一个新行,事务代码为NULL,而不是计算序列的nextval并将其插入到相应的列中。因此,正如我所发现的,如果您为postgres指定NULL,那么它假设您真的想在该列中插入NULL,而不管它是否具有默认值(我来自具有不同行为的ORACLE)

我对这方面的任何解决方案都持开放态度,无论是在数据库上还是在RoR上:

  • 或者有一种方法可以从ActiveRecord中排除属性
    保存
  • 或者有一种方法可以在使用触发器插入之前更改列的值
  • 或者有一种方法可以在RoR中生成这些序列号
  • 或者任何其他方式,只要有效:-)

提前感谢。

如果您想
insert
语句的列中插入默认值,可以使用关键字
default
-无引号:

INSERT INTO mytable (col1, col2) VALUES (105, DEFAULT);
或者您可以在您的案例中拼写默认值,
nextval(…)
。看


对于这种情况,触发器很简单。如果您想确保只输入序列中的数字,不管发生什么情况,我建议您这样做

CREATE OR REPLACE FUNCTION trg_myseq()
  RETURNS trigger AS
$BODY$
BEGIN

NEW.mycol := nextval('my_seq');
RETURN NEW;

END;
$BODY$
  LANGUAGE plpgsql VOLATILE;

CREATE TRIGGER myseq
  BEFORE INSERT
  ON mytable
  FOR EACH ROW
  EXECUTE PROCEDURE trg_myseq();
旁注: 如果您想将自己的(非顺序的)数字指定为“顺序”,我在几天前的回答中已经为此写了一个解决方案:

目前,您可能无法在ROR模型中获取和分配序列,如下所示:

before_create :set_transaction_code_sequence

def set_transaction_code_sequence
  self.transaction_code = self.class.connection.select_value("SELECT nextval('transaction_code_seq')")
end

我并不特别喜欢这个解决方案,因为我希望看到这个问题在AR中得到纠正。。。但它确实起到了作用。

谢谢欧文的回答。问题是,在ActiveRecord的save方法中,您不能在INSERT中“发送”关键字DEFAULT(这将解决这个问题,是的)。我更喜欢在Ruby on Rails应用程序中100%编码的解决方案,而不是在数据库中编程,这将使我无法在需要时无缝迁移到另一个DBMS。@Ricardo:“无缝迁移到另一个DBMS”是一个很好的幻想,但它与现实没有多大关系,对不起。触发器的一大缺点是您无法在Heroku共享数据库上使用它。这确实会创建一个到DB的额外查询,理想情况下,我希望能够在一个查询中插入序列值。