postgresql Postgres序列的last_value字段未按预期工作

brtdzjyr  于 2023-11-18  发布在  PostgreSQL
关注(0)|答案(5)|浏览(191)

我在postgres中有一个表,它的主键是用一个序列(我们称之为“a_seq”)来分配的。这个序列是用来递增值并插入当前值作为被插入记录的主键。
我用于序列的代码:

CREATE SEQUENCE public.a_seq
    INCREMENT 1
    START 1
    MINVALUE 1
    MAXVALUE 9223372036854775807
    CACHE 1;

ALTER SEQUENCE public.AssembleTable_RowId_seq OWNER TO postgres;

字符串
我试图从磁盘复制一个文件,并将有关复制文件的信息插入到表中。磁盘中有同名文件,因此我使用此查询从序列中检索“last_value”:

SELECT last_value FROM a_seq;


重命名文件“_”,然后将其插入数据库,以便该文件的文件名和主键(id)是一致的,如:

id | fileName                         
1  | 1_asd.txt


但是当我插入记录时,id总是比从查询中获取的“last_value”大1个值,所以表看起来像这样:

id | fileName                         
2  | 1_asd.txt


我已经多次尝试执行上面的select查询来检查它是否增加了值,但它没有。
在插入之前,如何获得将被分配给记录的值?
注意:我使用MATLAB,这是用于插入的代码:

colnames = {'DataType'         , ...
            'FilePath'         , ...
            'FileName'         , ...
            'FileVersion'      , ...
            'CRC32Q'           , ...
            'InsertionDateTime', ...
            'DataSource'       };

data = {FileLine{5}  ,... % DataType
        tempPath     ,... % FilePath
        FileLine{1}  ,... % FileName
        FileLine{2}  ,... % FileVersion
        FileLine{3}  ,... % CRC32Q
        FileLine{4}  ,... % InsertionDateTime
        FileLine{6}  ,... % DataSource};

data_table = cell2table(data, 'VariableNames', colnames);
datainsert(conn , 'CopiedFiles' , colnames , data_table);

hof1towb

hof1towb1#

更新

我相信你会发生什么:当你select last_value-你得到最后使用的序列值,当你insert行,id的默认值是nextval,它将值滚动一个以上。

previous我相信你在中间步骤的某个地方有一个额外的nextval。如果你在一个语句中这样做,它会像你期望的那样工作,例如:

t=# create table so12(s int default nextval('s'), t text);
CREATE TABLE
t=# insert into so12(t) select last_value||'_abc.txt' from s;
INSERT 0 1
t=# select * from so12;
 s |     t
---+-----------
 1 | 1_abc.txt
(1 row)

字符串

update 2正如Nick巴恩斯所注意到的,进一步的(初始化1)迭代将给予错误的结果,因此您需要使用他提出的CASE逻辑

0aydgbwb

0aydgbwb2#

这是Postgres实现序列的方式中的一个怪癖;作为事务数据库中固有的非事务对象,它们的行为有点奇怪。
当你第一次调用nextvalue()时,它不会 * 影响你在a_seq.last_value中看到的数字。但是,它会 * 翻转a_seq.is_called标志:

test=# create sequence a_seq;
test=# select last_value, is_called from a_seq;
 last_value | is_called
------------+-----------
          1 | f

test=# select nextval('a_seq');
 nextval
---------
       1

test=# select last_value, is_called from a_seq;
 last_value | is_called
------------+-----------
          1 | t

字符串
所以如果你需要序列中的下一个值,

SELECT
  last_value + CASE WHEN is_called THEN 1 ELSE 0 END
FROM a_seq


请注意,如果两个进程同时执行此操作,则会严重损坏,因为无法保证您将在下一次nextval()调用中实际收到此值。在这种情况下,如果您确实需要filename来匹配id,则需要使用trigger生成它,或者在知道id是什么后使用UPDATE生成它。
但根据我的经验,最好避免数据和键之间的任何依赖关系,如果你只需要一个唯一的filename,我会创建一个独立的filename_seq

kognpnkq

kognpnkq3#

当执行INSERT语句时没有id的值- Postgres自动从序列中使用next_val获取它。变量colnames中的列列表没有id,所以PG从序列中获取下一个值。为了解决这个问题,您可以将id添加到colnames

t3psigkw

t3psigkw4#

为了避免数据和密钥之间的任何依赖关系,请尝试:

CREATE SEQUENCE your_sequence
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
ALTER TABLE your_sequence
OWNER TO postgres;

字符串

ffscu2ro

ffscu2ro5#

看看你发布的内容,要选择x_seqlast_value,你必须像表ie那样调用它:

select last_value from xscheme.x_seq;

字符串

相关问题