【问题标题】:How to retrieve the actual default value for a column before insertion如何在插入之前检索列的实际默认值
【发布时间】:2014-06-10 01:49:45
【问题描述】:

我的 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?

但是,Chris 给出的答案是我想要的答案,而无需查看信息架构(我想我尝试过但没有奏效)。

【问题讨论】:

标签: sql postgresql


【解决方案1】:

没有办法直接做你想做的事——你不能预览值。

想象一下:

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 试图阻止您这样做(因为它会产生错误的结果)。用randomnextval 考虑这个问题更明显。

因此,使用 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

【讨论】:

  • 谢谢。我想我想要的是:SELECT nexval('statistical_outputs_id_seq') 但是这会返回一个错误 -> HINT: No function matches the given name and argument types. You might need to add explicit type casts.
  • 我不打算在insert 语句中使用检索到的nextval 值。我的问题是我正在使用Insert... (DEFAULT),但是它返回了一个错误,即 id 已经存在......所以我试图找出它试图作为诊断插入的id 的值。
  • 哎呀,你为什么不这么说?!请在 dba.stackexchange.com 上发布一个带有该详细信息的 新问题,并在此处的评论中发布指向它的链接。我去看看。
  • 对不起。我想如果我找到了这个问题的答案,我将能够更好地诊断我的 postgres 插入问题。我仍然很好奇如何检索nextval() 值。但是同意,也许这对 dba 来说是一个更好的问题;我会移动它。
  • 我把它打错了nexval 而不是nextval,你复制了错字;-)。如果要对序列重新编号,请使用setval。请参阅手册。
【解决方案2】:

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

也就是说,这一切都取决于你什么时候第一次获得序列的值,以及当前还有哪些其他交易涉及该序列。即 默认 将随时间变化,很大程度上取决于其他事务如何使用该sequence

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

根据评论进行编辑:

@Craig Ringer 指出,调用currval 首先需要调用nextval,这是公平的。

【讨论】:

  • 您实际上不能这样做,因为在您获取会话中的序列之前,不会定义currval。试试看。你会得到ERROR: currval of sequence "xxx" is not yet defined in this session
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多