我在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
我尝试多次执行上面的选择查询以检查它是否增加了值,但它没有 知道如何在插入之前获得将被记录到记录的值吗?
注意:我使用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);
答案 0 :(得分:3)
<强>更新强>
我认为对您而言:当您select last_value
时 - 您获得上次使用的序列值,当您insert
行时,{{1}的默认值}是id
,它将值滚动一个......
<强>前强>
我相信你在中间步骤中有一个额外的nextval
。如果你在一个声明中这样做,它会按预期工作,例如:
nextval
<强> UPDATE2 强>
正如Nick Barnes所注意到的那样,进一步(然后是initial1)迭代会给出错误的结果,你需要使用heis建议的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)
逻辑
答案 1 :(得分:2)
这是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或UPDATE
生成它,一旦您知道了什么id
是。
但根据我的经验,最好避免数据和密钥之间存在任何依赖关系。如果您只需要一个独特的filename
,我就会创建一个独立的filename_seq
。
答案 2 :(得分:1)
执行INSERT
语句而没有id
的值时 - Postgres会使用next_val
自动从序列中获取它。变量colnames
中的列列表没有id
,因此PG从序列中获取下一个值。要解决此问题,您可以将ID添加到colnames
。
答案 3 :(得分:1)
为避免数据与密钥之间存在任何依赖关系,请尝试:
CREATE SEQUENCE your_sequence
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
ALTER TABLE your_sequence
OWNER TO postgres;