Есть ли функция в MySQL, чтобы не разрешать выбор значения непосредственно после значения, уже выбранного из перечисляемого типа данных в базе данных?

#mysql #time #enums #triggers

#mysql #время #перечисления #триггеры

Вопрос:

Есть ли код, чтобы не разрешать вставлять значение непосредственно после значения, которое уже сохранено, в таблицу. Поле является ENUM.

Нигде не могу найти код

Нет доступных для ENUM

Временной интервал(’09:00′,’09:30′,’10:00′) 09:00 сохранено уже

’09:30′ не должно быть разрешено вставлять в таблицу ’10:00′ должно вставляться нормально

Ответ №1:

Нет функции по умолчанию, о которой я знаю, чтобы делать то, что вы хотите.

Я думаю, вам придется выполнить некоторые проверки, используя индекс перечисления. Значения ENUM сопоставляются числовому индексу. Вы можете выбрать column_name 0 в столбце ПЕРЕЧИСЛЕНИЯ, и это даст вам значение индекса перечисления, а не само значение перечисления. MySQL ENUM Doc

В вашем случае индекс ПЕРЕЧИСЛЕНИЯ выглядел бы примерно так:

 NULL -> NULL
0 -> ''
1 -> '9:00'
2 -> '9:30'
3 -> '10:00'
  

Например, если у вас есть 1 запись с временным интервалом, установленным на ‘9:00’, и вы ‘ВЫБИРАЕТЕ временной интервал 0 ИЗ таблицы’, ваш результат для записи будет равен 1. Если бы значение столбца было ‘9:30’, индекс был бы равен 2 и т.д.

Вы можете найти потенциальный индекс входящего значения, используя что-то вроде этого:

     SELECT FIND_IN_SET('new_value', REPLACE(SUBSTRING(column_type,6, LENGTH(column_type) - 6), ''', '') ) AS enum_options
      FROM information_schema.columns
     WHERE column_name='your_enum_column'
       AND table_schema = 'your_schema';
  

Если результат этого равен любому из значений индекса (или значение индекса 1) любого из значений, уже имеющихся в таблице, вы не хотите разрешать эту новую запись. Вы можете использовать приведенный выше запрос в качестве подзапроса внутри оператора case, чтобы сравнить индекс этого нового значения с индексами ваших предыдущих значений.

РЕДАКТИРОВАТЬ (4/2/2019): После пары комментариев я думаю, что следующее может приблизить вас к тому, что вам нужно. Я не смог протестировать этот запрос, но он должен быть близок.

        CREATE TEMPORARY TABLE booking_conflicts AS (
            SELECT MAX(
                       IF(
                          FIND_IN_SET( 
                           (SELECT FIND_IN_SET('12:00', REPLACE(SUBSTRING(column_type,6, LENGTH(column_type) - 6), ''', '') )
                              FROM information_schema.columns
                             WHERE column_name='your_enum_column'
                               AND table_name = 'booking'
                               AND table_schema = 'your_schema'),
                            CONCAT(time_slot 0, ',', time_slot 1)
                           ) > 0,
                           1,
                           0) AS is_time_conflict
              FROM booking
             WHERE facility_id = 6
               AND booking_date = '2020-07-04'
       );

       INSERT INTO bookings 
                   (facility_id,booking_date,time_slot,member_id) 
       VALUES (6,'2020-07-04','12:00',2)
        WHERE (SELECT is_time_conflict FROM booking_conflicts) = 0;
  

Что это делает, так это получение всех использованных временных интервалов с этой даты для этого объекта и сравнение их с новым временным интервалом, который вы пытаетесь использовать. Если индекс нового временного интервала равен индексу ранее использованного time_slot или ранее использованного time_slot 1, то запрос вернет 1, в противном случае 0. Мы сохраняем это во временной таблице и получаем доступ к временной таблице из вставки.

Комментарии:

1. Спасибо за ответ. У меня просто возникли небольшие проблемы с тем, как я мог бы вписать это в оператор case

2. Вставить в значения бронирований (facility_id,booking_date, time_slot, member_id) (6,’2020-07-04′,’12:00′,2) ГДЕ ВЫБЕРИТЕ FIND_IN_SET(‘new_value’, ЗАМЕНИТЬ(ПОДСТРОКА(column_type,6, ДЛИНА(column_type) — 6), ‘», «) ) КАК enum_options ИЗ information_schema.columns, ГДЕ column_name=’time_slot’ И table_schema = ‘mylescoop’, что я уже пробовал, не уверен, как связать предложение where

3. Я добавляю новый фрагмент SQL к приведенному выше ответу, который может быть полезен.

4. Спасибо за ответ, очень четкий и понятный, можно ли это интегрировать в триггер? Чтобы временная таблица хранила значение, при котором триггер активируется перед вставкой в заказы. Таким образом, тогда запускается сообщение об ошибке. Поскольку это позволило бы создать более оптимизированную базу данных, поскольку она автоматически проверяла бы это каждый раз, когда в таблице происходит вставка

5. Я не понимаю, почему этого не могло быть. Хотя, возможно, вы захотите рассмотреть возможность создания хранимой процедуры / функции вместо этого. Таким образом, вы могли бы легко заставить функцию / процедуру возвращать, была ли создана новая запись или нет, так что вы можете использовать это значение для уведомления пользователя об успехе / сбое.