Ruby on Rails+PostgreSQL:自定义序列的使用
假设我有一个名为 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 上:
- 要么有一种方法可以从 ActiveRecord 中排除属性
save
- 或者有一种方法可以在使用触发器插入之前更改列的值
- ,或者有一种方法可以在 RoR 内生成这些序列号
- 或任何其他方式,只要它有效:-)
谢谢进步。
Say I have a model called Transaction
which has a :transaction_code
attribute.
I want that attribute to be automatically filled with a sequence number which may differ from id
(e.g. Transaction with id=1
could have transaction_code=1000
).
I have tried to create a sequence on postgres and then making the default value for the transaction_code
column the nextval
of that sequence.
The thing is, if I do not assign any value to @transaction.transaction_code
on RoR, when I issue a @transaction.save
on RoR, it tries to do the following SQL:
INSERT INTO transactions (transaction_code) VALUES (NULL);
What this does is create a new row on the Transactions table, with transaction_code as NULL, instead of calculating the nextval of the sequence and inserting it on the corresponding column. Thus, as I found out, if you specify NULL to postgres, it assumes you really want to insert NULL into that column, regardless of it having a default value (I'm coming from ORACLE which has a different behavior).
I'm open to any solution on this, either if it is done on the database or on RoR:
- either there is a way to exclude attributes from ActiveRecord's
save
- or there is a way to change a column's value before insert with a trigger
- or there is a way to generate these sequence numbers within RoR
- or any other way, as long as it works :-)
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
目前,您可能会陷入在 ROR 模型中获取和分配序列的困境,如下所示:
我不是特别喜欢这个解决方案,因为我希望直接在 AR 中看到这一点......但它确实做到了诡计。
For the moment, you might be stuck fetching and assigning the sequence in your ROR model like this:
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.
如果您想要插入默认值到
INSERT
语句中的列中,您可以使用关键字DEFAULT
- 不带引号:或者您可以根据您的情况拼写出默认值
nextval(...)
。请参阅此处的手册。这种情况的触发器很简单。如果您想确保无论如何只输入序列中的数字,这实际上是我建议的。
附注:
如果您想将自己的(非连续)数字分配为“序列”,我在几天前的答案中为此编写了一个解决方案:
如何指定postgresql 序列
If you want to insert the default value in to a column in an
INSERT
statement, you can use the keywordDEFAULT
- no quotes:Or you could spell out the default,
nextval(...)
in your case. See the manual here.A trigger for that case is simple. That's actually what I would recommend if you want to make sure that only numbers from your sequence are entered, no matter what.
On a side note:
If you want to assign your own (non-sequential) numbers as 'sequence', I have written a solution for that in an answer a couple of days ago:
How to specify list of values for a postgresql sequence
我在使用 Rails7 时仍然遇到这个问题 - 我可以看到 Rails 在插入中生成 NULL,但是将列从
integer
更改为bigint
解决了这个问题。 - 然后 Rails 不会为我的排序列提供值,并且使用DEFAULT nextval('number_seq')
。I was still experiencing this issue with Rails7 - I could see that Rails was generating a NULL in the insert, but changing the column from
integer
tobigint
solved it. - Rails then does not supply a value for my sequenced column and theDEFAULT nextval('number_seq')
is used.