如何在插入之前检索列的实际默认值

时间:2014-06-10 01:49:45

标签: sql postgresql

我在postgres数据库中有一个表,在我描述时看起来像这样。

                                  Table "public.statistical_outputs"
      Column       |           Type           |                            Modifiers                             
-------------------+--------------------------+------------------------------------------------------------------
 id                | bigint                   | not null default nextval('statistical_outputs_id_seq'::regclass)

如果我使用像

这样的语句,我想知道将在id列中插入什么值
insert into statistical_outputs VALUES (DEFAULT);

我尝试过像

这样的事情
select nextval('id') from statistical_outputs;

但它不起作用。

可能相关的问题:

postgresql sequence nextval in schema

PostgreSQL nextval and currval in same query

这些问题可能与以下内容重复:

Get the default values of table columns in Postgres?

然而,克里斯给出的答案是我想要的,而不必查看信息模式(我认为我尝试但不起作用)。

2 个答案:

答案 0 :(得分:3)

无法直接执行您想要的操作 - 您无法预览该值。

想象:

regress=> CREATE TABLE crazy (blah integer, rand float4 default random());
CREATE TABLE
regress=> insert into crazy(blah, rand) values (1, DEFAULT);
INSERT 0 1
regress=> select * from crazy;
 blah |   rand   
------+----------
    1 | 0.932575
(1 row)

random()是一个volatile函数,每次返回一个不同的值。因此,任何预览该值的尝试都只能获得与要插入的值不同的值。

nextval也是如此,因为并发事务可以影响该值 - 即使您直接读取当前序列位置,PostgreSQL会尝试阻止您这样做(因为它会产生错误的结果)。使用random而不是nextval来考虑此问题更为明显。

因此,使用volatile默认值,您所能做的就是:

  • 自行评估默认表达式,然后提供insert中的值,即调用SELECT nextval('statistical_outputs_id_seq')然后INSERT INTO ... VALUES (..., 'the value from nextval()');

  • 使用RETURNING获取生成的值

我建议后者。前者在一般情况下很烦人和困难,因为默认可以是任意表达。

RETURNING的示例:

regress=> insert into crazy(blah, rand) values (1, DEFAULT) RETURNING rand;
   rand   
----------
 0.975092
(1 row)

INSERT 0 1

答案 1 :(得分:0)

sequence列的默认值将根据事务及其与MVCC当前状态的关系而有所不同。

也就是说,它将取决于您何时首次获得序列的值,以及当前涉及该序列的其他事务。即默认会随着时间的推移而变化,主要取决于其他交易如何使用sequence

确定默认值的最接近的方法(同样,这将随时间变化)是选择序列的currval(理解它在理论上可能是另一个之后要调用nextval并更改它的事务,尽管调用currval的有用性将取决于您想要对该值做什么。)

编辑以回复评论:

@Craig Ringer指出,首先拨打currval需要拨打nextval,这是一个公平的点。