假设我有一个名为Transaction
的模型,它具有:transaction_code
属性。
我希望该属性自动填充可能与id
不同的序列号(例如,与id=1
的交易可能有transaction_code=1000
)。
我尝试在postgres上创建一个序列,然后将transaction_code
列的默认值设为该序列的nextval
。
问题是,如果我没有在RoR上为@transaction.transaction_code
分配任何值,当我在RoR上发出@transaction.save
时,它会尝试执行以下SQL:
INSERT INTO transactions (transaction_code) VALUES (NULL);
这样做是在Transactions表上创建一个新行,其中transaction_code为NULL,而不是计算序列的nextval并将其插入相应的列。因此,正如我所知,如果你为postgres指定NULL,它假定你真的想要在该列中插入NULL,无论它是否具有默认值(我来自ORACLE,它具有不同的行为)。
我对此有任何解决方案,无论是在数据库上还是在RoR上:
save
提前致谢。
答案 0 :(得分:6)
目前,您可能会陷入困境并在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中看到这个问题......但它确实可以解决这个问题。
答案 1 :(得分:2)
如果您想将默认值插入INSERT
语句中的列,则可以使用关键字DEFAULT
- 无引号:
INSERT INTO mytable (col1, col2) VALUES (105, DEFAULT);
或者您可以在您的情况下拼出默认值nextval(...)
。请参阅manual here。
该案例的触发器很简单。如果您想确保只输入序列中的数字,无论如何都是这样的话,这实际上就是我推荐的。
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();
旁注:
如果你想把你自己的(非连续的)数字指定为'序列',我几天前在答案中写了一个解决方案:
How to specify list of values for a postgresql sequence