8

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

我试图在 postgres 上创建一个序列,然后为该序列的transaction_code列设置默认值nextval。问题是,如果我没有为@transaction.transaction_codeon RoR 分配任何值,当我发出@transaction.saveon RoR 时,它会尝试执行以下 SQL:

INSERT INTO transactions (transaction_code) VALUES (NULL);

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

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

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

提前致谢。

4

2 回答 2

6

For the moment, you might be stuck fetching and assigning the sequence in your ROR model like this:

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

I'm not particularily fond of this solution, since I'd like to see this corrected in AR directly... but it does do the trick.

于 2012-07-30T23:38:21.240 回答
2

如果要在语句中的列中插入默认值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();

附带说明:如果您想将自己的(非顺序)数字分配为“序列”,我已经在几天前的答案中为此编写了一个解决方案:
如何为 postgresql 序列指定值列表

于 2011-10-19T22:38:53.317 回答