2014-11-12 1 views
0
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) 

Я пытаюсь вставить в записи файла базы данных по мере завершения загрузки. Но я получаю дублированные ключевые эры, потому что выбор генерирует один и тот же идентификатор в нескольких параллельных доступах. Как я могу решить эту проблему? И почему это происходит? Это тот же запрос, как операторы insert, так и select должны быть разрешены под тем же «статусом db».Вручную создать идентификатор таблицы PostgreSQL с одновременным доступом

Я знаю, что последовательности или серии должны решить проблему, но они на самом деле не работают для меня.

+0

Возможный дубликат: http://stackoverflow.com/questions/18614303/insert-into-postgres-sql – Claudix

+1

Почему последовательности не работают для вас ... –

+0

У меня есть составные ключи и нужны?! следовать последовательности, подобной (1, 1), (1, 2), (1, 3); (2, 1), (2, 2) и т. Д. –

ответ

0

Либо вы должны забыть о вручную, либо о одновременно, вы не можете иметь и другое. Вам решать, какой из них важнее для вас.

Если вы решите разорвать concurrency, то вы можете lock the table в начале транзакции, а затем вставить данные и, наконец, совершить (который отпустит блокировку). Затем следующая транзакция будет обработана и так далее, последовательно.

BEGIN; 

LOCK TABLE rehus.curriculumsfile; 

INSERT INTO rehus.curriculumsfile ... ; 

... 

COMMIT; 

Если вы не генерировать эти идентификаторы manually, то вы можете рассчитывать на последовательностях, чтобы сделать работу для вас, а затем, если вы хотите использовать window function, чтобы отобразить порядковые номера для пользователей.

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 
Смежные вопросы