【问题标题】:Is there a function in MySQL to not allow the selection of a value directly after a value already selected from an ENUM data type in the database?MySQL 中是否有一个函数不允许在已经从数据库中的 ENUM 数据类型中选择一个值之后直接选择一个值?
【发布时间】:2019-04-01 19:24:42
【问题描述】:

是否有代码不允许将已保存的值直接插入表中。该字段是一个 ENUM。

在任何地方都找不到代码

ENUM 没有可用的

时隙 ENUM('09:00','09:30','10:00') 09:00 已保存

'09:30' 不应该被允许插入到表中 '10:00' 应该插入正常

【问题讨论】:

    标签: mysql time enums triggers


    【解决方案1】:

    据我所知,没有默认功能可以执行您想要的操作。

    我认为您将不得不使用 ENUM 索引进行一些检查。 ENUM 值映射到数字索引。您可以在 ENUM 列上选择 column_name+0,这将为您提供 ENUM 的索引值,而不是 ENUM 值。 MySQL ENUM Doc

    在您的情况下,ENUM 索引看起来像这样:

    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 语句中的子查询,以将此新值的索引与之前值的索引进行比较。

    编辑(2019 年 4 月 2 日): 经过几次 cmet,我认为以下内容可能会让您更接近您的需求。我无法测试这个查询,但它应该很接近。

           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。我们将其存储在临时表中并从插入访问临时表.

    【讨论】:

    • 感谢您的回复。我只是在如何将其放入案例陈述中遇到了一些麻烦
    • 插入预订 (facility_id,booking_date,time_slot,member_id) 值 (6,'2020-07-04','12:00',2) WHERE 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='time_slot' AND table_schema = 'mylescoop' 我已经尝试过,不知道如何链接 where 子句
    • 我在上面的答案中添加了一个新的 SQL sn-p,这可能会有所帮助。
    • 感谢回复,非常清晰易懂,能否将其集成到触发器中。这样临时表将存储一个值,其中触发器在插入预订之前被激活。因此,然后运行一条错误消息。因为这将允许更精简的数据库,因为它会在每次插入表时自动检查这一点
    • 我不明白为什么不能。不过,您可能需要考虑创建一个存储过程/函数。这样,无论是否创建了新记录,您都可以轻松地让函数/过程返回,因此您可以使用该值通知用户成功/失败。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多