Значение автоматического увеличения для столбца, не являющегося первичным ключом

В моей MariaDB у меня есть две таблицы project и issue, таблица issue содержит все проблемы, созданные для всех проектов.

create table if not exists Project(
  id integer PRIMARY KEY auto_increment,
  `name` varchar(200) NOT NULL
 );

 create table if not exists Issue(
  id integer PRIMARY KEY AUTO_INCREMENT,
  project_id integer,
   issue_number integer,
   content text,
    FOREIGN KEY (project_id)
        REFERENCES Project(id)
   );

issue_number указан для каждого проекта и всегда начинается с 1, как можно увеличить его на 1 и решить проблемы с одновременной вставкой?

Я не могу использовать select max(issue_number) + 1 from Issue where project_id=X для определения нового значения, поскольку оно может устареть.

Что именно вы подразумеваете под «может быть устаревшим»?

Progman 13.04.2024 12:38
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
104
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете вычислить поле issue_number, хранить его не нужно:

SELECT 
   id, 
   project_id, 
   row_number() over (partition by project_id order by id) as issue_number,
   content 
FROM Issue;

или вы можете сохранить его, когда вам часто понадобится фактическое значение issue_number....

Ответ принят как подходящий

Вы можете создать таблицу «последовательности» для хранения следующего номера выпуска для каждого проекта.

create table sequencing (
  project_id int primary key not null,
  next_number int
);

insert into sequencing (project_id, next_number) values (1234, 1);

Вы можете использовать оптимистическую блокировку или пессимистическую блокировку для устранения состояния гонки. В приведенной ниже последовательности используется пессимистическая блокировка. Решение «Оптимистическая блокировка» немного отличается (здесь не показано).

При добавлении нового выпуска вы сделаете:

  1. Запустите транзакцию базы данных.
  2. Получите следующий номер выпуска для проекта и заблокируйте строку.
  3. Увеличьте номер следующего выпуска проекта.
  4. Вставьте проблему с вновь полученным номером проблемы.
  5. Зафиксируйте транзакцию и снимите блокировку.

В SQL это будет выглядеть так:

start transaction;

select next_number -- save this number in app as "n"
from sequencing 
where project_id = 1234
for update;

update sequencing
set next_number = next_number + 1
where project_id = 1234;

insert into issue (..., issue_number) values (..., n); -- use "n" here

commit;

Обязательно получите следующий номер внутри транзакции.

Rick James 20.04.2024 19:37

Другие вопросы по теме