同一 INSERT 期间另一列中序列列的参考值
Posted
技术标签:
【中文标题】同一 INSERT 期间另一列中序列列的参考值【英文标题】:Reference value of serial column in another column during same INSERT 【发布时间】:2012-09-08 02:58:10 【问题描述】:我有一个带有 SERIAL 主键的表,还有一个 ltree 列,我希望它的值是这些主键的串联。例如
id | path
----------
1 1
2 1.2
3 1.2.3
4 1.4
5 1.5
我很好奇是否有办法在一个查询中进行这样的插入,例如
INSERT INTO foo (id, ltree) VALUES (DEFAULT, THIS.id::text)
我可能在这里超出了范围,并试图在一个查询中完成我应该在两个查询中执行的操作(在事务中分组)。
【问题讨论】:
这条路径看起来不太可查询.. 我的路径值基于此:***.com/a/607379/39529 PostgreSQL 具有递归、公用表表达式,比您的路径解决方案/解决方法更容易和更快。 【参考方案1】:您可以使用 CTE 从序列中检索值一次并重复使用它:
WITH cte AS (
SELECT nextval('foo_id_seq') AS id
)
INSERT INTO foo (id, ltree)
SELECT id, '1.' || id
FROM cte;
CTE with a data-modifying command 需要 Postgres 9.1 或更高版本。
如果您不确定序列的名称,请使用
pg_get_serial_sequence()
改为:
WITH i AS (
SELECT nextval(pg_get_serial_sequence('foo', 'id')) AS id
)
INSERT INTO foo (id, ltree)
SELECT id, '1.' || id
FROM i;
如果表名“foo”在数据库中的所有模式中可能不是唯一的,请对其进行模式限定。如果任何名称的拼写不标准,则必须双引号:
pg_get_serial_sequence('"My_odd_Schema".foo', 'id')
快速测试表明@Mark's idea 和lastval()
可能也可以工作:
INSERT INTO foo (ltree) VALUES ('1.' || lastval());
您可以将id
排除在查询之外,serial
列将被自动分配。没有区别。
行之间不应存在竞争条件。我quote the manual:
currval
返回
nextval
在当前会话中为此序列最近获得的值。 (如果nextval
有 在本次会议中从未为此序列调用过。)因为这是 返回一个会话本地值,它给出一个可预测的答案是否 或者自当前会话以来没有其他会话执行nextval
做了。此函数需要序列的
USAGE
或SELECT
权限。
lastval
返回当前会话中
nextval
最近返回的值。此函数与currval
相同,除了 将序列名称作为它所引用的参数 序列nextval
最近应用于当前会话。 如果尚未调用nextval
,则调用lastval
是错误的 当前会话。此函数需要
USAGE
或SELECT
对上次使用的序列的权限。
我的大胆强调。
但是,作为@Bernard commented,它毕竟可以失败:不能保证填充默认值(并且在过程中调用nextval()
)之前 调用lastval()
来填充第二列ltree
。所以坚持第一个解决方案和nextval()
以确保。
【讨论】:
是否保证会先调用nextval()
来查找下一个主键,这样lastval()
就不会报错?
您的第二个建议会在 PostgreSQL 9.5 上引发 55000 ERROR: lastval is not yet defined in this session
。
@Bernard:感谢您的纠正,我相应地更新了。添加了一种在不知道序列名称的情况下的方法。【参考方案2】:
这在我的测试中有效:
INSERT INTO foo (id, ltree) VALUES (DEFAULT, (SELECT last_value from foo_id_seq));
我认为如果两个 INSERT 同时发生,则存在竞争条件,因为这引用了最后一个序列值,而不是当前行。我个人更倾向于这样做(伪代码):
my $id = SELECT nextval('foo_id_seq');
INSERT INTO foo (id, ltree) VALUES ($id, '$id');
【讨论】:
以上是关于同一 INSERT 期间另一列中序列列的参考值的主要内容,如果未能解决你的问题,请参考以下文章