@lexstile

Как создать порядковый номер для заказа конкретного заведения?

Есть таблица orders - заказы с привязкой к проекту (заведению).
Хочется, чтобы был порядковый номер заказа в срезе заведения.
Как можно реализовать данный механизм? (как я понял, получение количества перед созданием не дает 100% гарантии, что порядковые номера не совпадут - например, когда одномоментно создается несколько заказов).

Основная проблема - это постоянно увеличивающийся номер заказа, т. е. в срезе одного заведения будут заказы с номерами (id) №3, №10, №34... (неудобно).
63a2d4fb3a1a5994563501.png
  • Вопрос задан
  • 183 просмотра
Решения вопроса 4
@psiklop
Если блокировать таблицу не совпадут.
LOCK TABLES orders WRITE
тут получаем максимальный номер
пишем новый заказ
UNLOCK TABLES
Ответ написан
Adamos
@Adamos
Порядковый номер, небось, еще и сбрасываться должен каждый год?
Например, можно сделать два запроса: INSERT, при котором id таки назначится нормальным авто-инкрементом, и UPDATE, который заполнит отдельное поле number значением
SELECT count(id) + 1 
  FROM orders 
  WHERE id < :currentId AND project_id = 2 AND created_at >= '2022-01-01'
Никакие гонки это не запутают.
А если этот number нужен только в одном месте, его можно таким запросом получать динамически и не хранить нигде вообще.
Ответ написан
Комментировать
@Akina
Сетевой и системный админ, SQL-программист.
Пример реализации.
-- рабочая таблица
CREATE TABLE orders (
  id INT AUTO_INCREMENT PRIMARY KEY,
  project_id INT,
  project_number INT
  );

-- опорная таблица для генерации номеров в разрезе проектов
CREATE TABLE generate_project_number (
  project_id INT,
  project_number INT AUTO_INCREMENT,
  PRIMARY KEY (project_id, project_number)
  ) ENGINE = MyISAM;

-- триггер-генератор
CREATE TRIGGER generate_project_number
BEFORE INSERT ON orders
FOR EACH ROW
BEGIN
  -- вставить хапись в опорную таблицу для генерации номера
  INSERT INTO generate_project_number (project_id) VALUES (NEW.project_id);
  -- вставить сгенерированный номер в рабочую таблицу
  SET NEW.project_number = LAST_INSERT_ID();
  -- почистить опорную таблицу от лишних записей
  DELETE FROM generate_project_number 
  WHERE project_id = NEW.project_id
    AND project_number < NEW.project_number;
END

DEMO fiddle
Ответ написан
Комментировать
mayton2019
@mayton2019
Bigdata Engineer
Откажитесь от порядкового номера. Создайте код типа номер заведения + дата-время. И это будет коробочное решение вашей проблемы.

Все трюки с блокировкой таблицы могут параллизовать ваш бизнес. А зачем вам это надо?
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы