Как получить быстрые вставки SQL с MAX () + 1, чтобы всегда увеличиваться между каждым вызовом? - PullRequest
0 голосов
/ 19 ноября 2018

У меня есть конечная точка REST-ish, которая создает объект day и устанавливает для его свойства order значение maximum order is +1.У меня возникла проблема, когда вызов этой конечной точки в быстрой последовательности приводит к тому, что некоторые из days имеют тот же order.Как мне решить эту проблему?

SQL-запрос похож на это.

insert into "days" ("order", "program_id") values (
    (select max(days.order)+1
    from "days"
    where "days"."program_id" = '5'), '5')
    returning *

И в результате получается что-то вроде

{"program_id": 5, "id ": 147," order ": 38}

{" program_id ": 5," id ": 150," order ": 38}

{" program_id ": 5,"id ": 148," order ": 38}

{" program_id ": 5," id ": 149," order ": 38}

{" program_id ": 5,"id ": 151," order ": 39}

{" program_id ": 5," id ": 152," order ": 40}

{" program_id ": 5,"id ": 153," order ": 41}

Если это поможет, я работаю в Node (Express) и использую Knex и Objection для создания своих запросов для базы данных Postgres.Код JavaScript выглядит следующим образом.

json.order = knex.select(knex.raw('max(days.order)+1'))
                .from('days')
                .where('days.program_id', json.program_id);

return await Days
             .query(trx)
             .returning('*')
             .insert(json);

Я также использую max+1, так как я хочу, чтобы значения порядка увеличивались на основе program.Так что days из program будет иметь уникальный orders, но возможно иметь days разных programs с одинаковыми order.

Спасибо!

1 Ответ

0 голосов
/ 19 ноября 2018

Возможно, вы могли бы добавить select ... for update блокировку к подзапросу, в котором вы вычисляете max+1:

json.order = knex.select(knex.raw('max(days.order)+1'))
                .forUpdate() // <-------- lock rows 
                .from('days')
                .where('days.program_id', json.program_id);

Так что после этого никакое другое параллельное соединение не сможет прочитать те строки, которые используются для вычисления max, до этоготранзакция заканчивается.

...