INSERT INTO rehus.curriculumsfile (fileid, originalfilename, filename, path, curriculumid, userid, companyid) VALUES ((SELECT COALESCE(MAX(fileid), 0) + 1 FROM rehus.curriculumsfile WHERE curriculumid = $1 AND userid = $2 AND companyid = $3), $4, $5, $6, $1, $2, $3)
我正在尝试在上传结束时插入数据库文件记录。但我收到重复的密钥错误,因为select在多个并发访问中生成相同的ID。我该如何解决这个问题?为什么会发生这种情况?它是相同的查询,insert和select语句都应该在相同的“db status”下解析。
我知道序列或系列应该解决问题,但它们并不适合我。
答案 0 :(得分:0)
你必须忘记手动,关于并发,你不能同时拥有这两者。由你决定哪一个对你更重要。
如果您选择中断concurrency
,那么您可以在事务开始时lock the table,然后插入数据并最终提交(这将释放锁定)。然后将连续处理下一个交易,依此类推。
BEGIN;
LOCK TABLE rehus.curriculumsfile;
INSERT INTO rehus.curriculumsfile ... ;
...
COMMIT;
如果您选择不生成这些ID manually
,那么您可以依靠序列为您完成工作,然后如果您希望使用window function向用户显示连续的数字。< / p>
CREATE SEQUENCE curriculumsfile_fileid_seq;
ALTER TABLE
rehus.curriculumsfile
ALTER COLUMN
fileid
SET DEFAULT
NEXTVAL('curriculumsfile_fileid_seq');
然后使用COALESCE(MAX(fileid)+1, 0)
替换查询中的default
。
最后,当您查询数据时,请使用row_number()
动态构建编号。
SELECT
ROW_NUMBER() OVER (ORDER BY fileid) AS beautiful_fileid,
...
FROM
rehus.curriculumsfile;
或者如果您想要实现复合编号(例如userid
),那么您可以按它进行分区。
ROW_NUMBER() OVER (PARTITION BY userid ORDER BY fileid) AS beautiful_fileid