currval尚未定义此会话,如何获得多会话序列?

MUY*_*ium 29 postgresql database-design auto-increment postgresql-8.4

我的目标是在表中插入新行时自动插入主键字段.

如何在PostgreSQL中获得从一个会话到另一个会话的序列?

 doubleemploi@hanbei:/home/yves$ psql -d test
 Mot de passe : 
 psql (8.4.13)
 Saisissez « help » pour l''aide.

 test=> create sequence test001 start 10;
 CREATE SEQUENCE
 test=> select currval('test001');
 ERREUR:  la valeur courante (currval) de la séquence « test00 » n''est pas encore définie dans cette session
 --- current value not yet defined this session (???)
 test=> select setval('test001', 10);
 setval 
 --------
      10
 (1 ligne)

 test=> select currval('test00');
  currval 
 ---------
       10
 (1 ligne)

 test=> \q
 test@hanbei:/home/yves$ psql -d test
 Mot de passe : 
 psql (8.4.13)
 Saisissez « help » pour l''aide.

 test=> select currval('test001');
 ERREUR:  la valeur courante (currval) de la séquence « test00 » n''est pas encore définie dans cette session
Run Code Online (Sandbox Code Playgroud)

Mat*_*sOl 89

currval将返回在当前会话中序列生成的最后一个值.因此,如果另一个会话为序列生成新值,您仍然可以检索由您的会话生成的最后一个值,从而避免错误.

但是,要获得任何会话的最后生成值,您可以使用以上内容:

SELECT last_value FROM your_sequence_name;
Run Code Online (Sandbox Code Playgroud)

请注意,如果其他会话使用的值与未公开(或中止)的事务并且您使用此值作为参考,则可能会出错.一般人们只需要currval甚至回归setval.

  • 动作有趣的是,为什么在官方文档中甚至没有提到"SELECT*FROM sequence"的可能性? (3认同)

Erw*_*ter 15

这可能比你想象的要简单......

我的目标是在表中插入新行时自动插入主键字段.

只需设置列的默认值:

ALTER TABLE tbl ALTER COLUMN tbl_id SET DEFAULT nextval('my_seq'::regclass);
Run Code Online (Sandbox Code Playgroud)

或者更简单,创建具有serial主键类型的表格开头:

CREATE TABLE tbl(
  tbl_id serial PRIMARY KEY
 ,col1 txt
  -- more columns
);
Run Code Online (Sandbox Code Playgroud)

它创建一个专用序列并自动设置tbl_id的默认值.

这种方式tbl_id被分配从附加序列的下一个值,如果自动你不提它INSERT.适用于任何会话,并发或不兼容.

INSERT INTO tbl(col1) VALUES ('foo');
Run Code Online (Sandbox Code Playgroud)

如果你想让新的tbl_id回来做一些事情:

INSERT INTO tbl(col1) VALUES ('foo') RETURNING tbl_id;
Run Code Online (Sandbox Code Playgroud)


Kem*_*hou 8

对于这个问题,我将给出一个实际的答案。我的程序和psql终端都使用我的数据库服务器;因此有多个会话。目前我在我的psql终端中:

fooserver=> select currval('fusion_id_seq');
ERROR:  currval of sequence "fusion_id_seq" is not yet defined in this session
fooserver=> select nextval('fusion_id_seq');
 nextval 
---------
  320032
(1 row)

fooserver=> select currval('fusion_id_seq');
 currval 
---------
  320032
(1 row)
Run Code Online (Sandbox Code Playgroud)

看来您只能在自己的会话中看到这些值。这也将影响另一个会话的周期。这可能与服务器的多线程隔离不同的会话有关。计数器(在psql中为串行)是一个共享库。我认为,只要正确锁定计数器以确保只有一个线程(会话)可以递增计数器(原子操作),那么该会话就应该能够获取计数器的当前值。但是我在这里可能是错的(不是数据库服务器编写专家)。