Laravel делает автоинкрементный код/записи и будет сбрасываться ежедневно

Я пытаюсь сделать код автоинкремента с датой, и он сбросит код на днях.

У меня есть эта миграция.

public function up()
{
    Schema::create('records', function (Blueprint $table) {
        $table->id();
        //other codes here...
    });
}

Затем я добавляю столбец, который автоматически увеличивает 5 цифр, используя

ALTER TABLE id ADD my_id AS RIGHT('00000' + CAST(id AS VARCHAR(5)) , 5) PERSISTED

У меня есть этот запрос на моем контроллере

public function get_records(Request $request){
    $records = DB::table('records')->select(
        'records.my_id',
        //other codes here...
    )
    ->get();
    $recordlist = [];
    $currentMonth = Carbon::now()->format('mm');
    $currentDay = Carbon::now()->format('dd');
    foreach($records as $data):
        $data->CODE = 'Z' . $currentMonth . $currentDay . '-' .$data->my_id;
        $recordlist[] = $data;
    endforeach;
    return recordlist;

    // OUTPUT -->  CODE: 'Z0331-0001'
}

Я хотел бы, чтобы мой вывод был похож на ..

today is 03/31

CODE:
Z0331-00001
Z0331-00002
Z0331-00003
.....
Z0331-00010
Z0331-00011
Z0331-00012
.....
Z0331-00100
Z0331-00101
Z0331-00102

//The other day(04/01)..
CODE:
Z0401-00001
Z0401-00002
Z0401-00003
.....and so on

Я только что придумал эту транзакцию.

Я просто добавляю таблицу,

ALTER TABLE records DROP COLUMN my_id

ALTER TABLE records ADD my_id VARCHAR(5) NOT NULL

Тогда мой запрос..

$createdrecord = //last created record ex(CODE: 'Z0330-00265' created_at: '03/30(yesterday)' )
$today = Carbon::now();
foreach($records as $data){
    if ($today != $createdrecord){
        $data->my_id = '00000';
    }else{
        $data->my_id += 1;
    }
}

Я думаю, что это будет хорошо, но мой код не работает..

Спасибо за помощь.

Вы хотите написать собственный генератор последовательности, в идеале реализованный в виде хранимой процедуры. См. ответ NoOorZ24. Вашей таблице нужны my_id и my_id_date. Когда вам понадобится новый идентификатор, генератор последовательности предоставит вам его автоматически. Единственным сложным кодом будет добавление строки последовательности для дня, когда ее еще нет.

gview 31.03.2023 10:23

Вы не указали, какую БД вы используете. Если это mysql, я готов поделиться скелетом кода, который я реализовал. Важным моментом в последовательности является то, что вы блокируете строку. поэтому у вас есть параллелизм, но вы не подвержены гонке, когда одна и та же последовательность # может быть выделена 2x или более.

gview 31.03.2023 10:26

Я использую SqlDbx. Вот мой пример таблицы, которую я использовал с автоинкрементом (некоторые данные скрыты)

Newbee 31.03.2023 10:46

Это инструмент администратора, а не rdbms! Какую реляционную базу данных вы используете? Это MySQL? Постгрескл? Оракул? SQL-сервер......

gview 31.03.2023 10:54

Извините, это MySql.

Newbee 31.03.2023 11:00
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
5
171
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вам нужна дополнительная таблица, в которой вы храните счетчики. Он должен иметь 2 столбца:

  • дата
  • прилавок

Каждый раз, когда вы создаете record, вы должны проверять, есть ли что-то в таблице счетчиков на текущую дату.

Если он пустой - используйте ID = 1 и сохраните его в таблице счетчиков.

Если он не пуст, используйте счетчик + 1 и увеличивайте счетчик.

Проблема в том, что данные еще не добавлены. Итак, код начинается с 00000, а мой счетчик по-прежнему равен NULL.

Newbee 31.03.2023 10:50

Кажется, вы не понимаете здесь идею. Эта таблица, о которой он говорит, является таблицей последовательности. Счетчик используется для отслеживания последнего выделенного идентификатора. Каждый раз, когда вам нужен новый идентификатор, вы выбираете значение из этой таблицы и увеличиваете его на 1. Вы используете полученное значение для обновления my_id вашей таблицы. Как я уже упоминал, важно, чтобы вы заблокировали строку последовательности, чтобы она была невосприимчива к условиям гонки. Как он заявил, если строки еще не существует, вы создаете ее в своем коде, устанавливаете для нее значение 1 и используете 1 в качестве своего идентификатора. Ключом этой таблицы вы сделаете столбец даты.

gview 31.03.2023 10:59

Спасибо за объяснение. Кажется, я понял эту идею. Извините, я не совсем хорошо понимаю английский.

Newbee 31.03.2023 11:20
Ответ принят как подходящий

ОБНОВЛЯТЬ В процессе попытки ответить на этот вопрос мы установили, что у Автора MS Sql Server 2008, а не MySQL, как было заявлено изначально.

Поскольку в MS Sql Server есть объекты Sequence, эта идея может быть реализована с использованием схемы именования последовательностей, где последовательности именуются по дате.

  1. Найдите последовательность с именем «SEQ_YYYY-MM-DD». Имя объекта последовательности не может начинаться с цифры, поэтому вы можете использовать префикс SEQ_, чтобы обойти это. Например:
select count(*) as count_of from sys.sequences where name = "SEQ_2023_04_04"
  1. Если не найдено, создайте его на День
create sequence SEQ_2023_04_04 START WITH 1 AS INT
  1. Теперь вы можете использовать последовательность для генерации порядковых номеров
SELECT NEXT VALUE FOR SEQ_2023_04_04

Примечание:

Я оставляю детали PHP этих запросов вам. Например, чтобы узнать, какое имя последовательности для текущего дня в вашем коде, вы можете использовать

$seq = 'SEQ_' . date('Y_m_d');

Я опустил Schema здесь, так как я не знаю, что вы на самом деле делаете, но имена схем, возможно, придется ссылаться в этих запросах по мере необходимости. Вы должны убедиться, что понимаете понятия базы данных и схемы сервера MS Sql.


Это реализация MySQL идеи, предложенной NoOoZ24, поэтому не забудьте дать ему голос/кредит.

Сначала вам нужна таблица последовательности:

CREATE table sequence (id DATE PRIMARY KEY, counter int unsigned DEFAULT 1);

Вот хранимая процедура MySQL, которая будет действовать как ваш генератор последовательности:

DELIMITER //
CREATE PROCEDURE `getSequenceCounter`(
    IN p_date DATE
)
BEGIN
  DECLARE v_id DATE;
  DECLARE v_counter INT DEFAULT 0;
  DECLARE v_errorMsg VARCHAR(256);

  DECLARE EXIT HANDLER FOR SQLEXCEPTION, SQLWARNING
  BEGIN
    ROLLBACK;
    RESIGNAL;
  END;

  START TRANSACTION;
  IF NOT EXISTS(
    SELECT *
    FROM sequence
    WHERE id = p_date
  ) THEN    
    INSERT INTO sequence (id) values (CURDATE());
  END IF;

  SELECT id, counter
  INTO v_id, v_counter
  FROM sequence
  WHERE id = p_date
  FOR UPDATE;

  UPDATE sequence SET counter = counter + 1
  WHERE id = v_id;
  COMMIT;
  SELECT v_counter as counter;
END;
//
DELIMITER ;

Из командной строки вы можете запустить этот sproc, используя CALL:

call getSequenceCounter(CURDATE());

Глядя на код, вы должны заметить, что он создаст строку последовательности для даты, если она не существует, и вернет вам начальное значение, которое будет равно 1.

call getSequenceCounter(CURDATE());
+---------+
| counter |
+---------+
|       1 |
+---------+

Запустите его снова, и вы увидите следующее значение и так далее.

В последний раз я смотрел, что нет способа вызвать хранимую процедуру mysql из Eloquent, поэтому вам придется использовать DB::select или построить запрос. Обе эти техники показаны в ответах на этот вопрос.

Спасибо. Я все еще пытаюсь понять это, используя указанную вами процедуру sql, и пытаюсь выполнить ее в своей транзакции БД. Но у меня возникли некоторые ошибки при создании этого table sequence , поэтому я не могу начать с таблицы с образцом последовательности таблиц.

Newbee 03.04.2023 04:54

Вы уверены, что ваша база данных MySQL, а не SQL Server? Из окна SQL вашего инструмента, что вы получаете, когда запускаете SELECT @@version

gview 03.04.2023 17:52

Мне очень жаль, но я даю вам версию sql, которую я использую в phpMyadmin. Это Microsoft SQL Server 2008 R2 (RTM). Спасибо и извините еще раз.

Newbee 04.04.2023 00:56

Эта версия SQL Server прекращает свое существование везде, кроме Azure, и даже с Azure она прекращает свое существование в июле этого года. Вы должны посмотреть на обновление как можно скорее.

gview 04.04.2023 22:19

Это означает, что я не могу сделать/любой возможный способ добиться результата в моей проблеме, используя мой текущий sql?

Newbee 04.04.2023 23:42

Я показал пошаговый метод использования объекта последовательности сервера sql. Это еще проще и не требует имитации последовательности, так как sql server имеет последовательности как объекты. Смотрите обновления, которые я сделал в верхней части моего ответа.

gview 05.04.2023 00:12

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