简体   繁体   中英

MySQL - trigger on before insert + if data already exists + enum column

I am working on a trigger that I though is quite easy and should work but it is not working.

Here is the (abstract) table structure:

PK_id    |    FK1_id    |    FK2_id    |    status
1        |    12        |    15        |    'ok'

status column is defined as enum('ok', 'ok_2', 'not_ok') NUT NULL with no default value.

The trigger should verify that a combination of both FKx_id values already exists and if yes it should set the status to 'ok_2', otherwise to 'ok' and if the status is set in the INSERT INTO it is not touched.

The trigger I have right now (only body!):

BEGIN
    DECLARE cnt INT;
    SET cnt = (SELECT COUNT(*) FROM `table` WHERE `FK1_id` = NEW.FK1_id AND `FK2_id` = NEW.FK2_id);
    IF cnt > 0 AND NEW.status IS NULL THEN 
        SET NEW.status = 'ok_2';
    ELSEIF NEW.status IS NULL THEN
        SET NEW.status = 'ok';
    END IF;
END

Unfortunately this trigger sets the status always to 'ok' - please notice that the status is not part of the INSERT query (thus considered as NULL ). I have previously tried this trigger body with the same result:

BEGIN
    IF (SELECT COUNT(*) FROM `table` WHERE `FK1_id` = NEW.FK1_id AND `FK2_id` = NEW.FK2_id) > 0 AND NEW.status IS NULL THEN 
        SET NEW.status = 'ok_2';
    ELSEIF NEW.status IS NULL THEN
        SET NEW.status = 'ok';
    END IF;
END

and also this (with the very same result):

BEGIN
    IF EXISTS(SELECT * FROM `table` WHERE `FK1_id` = NEW.FK1_id AND `FK2_id` = NEW.FK2_id LIMIT 1) AND NEW.status IS NULL THEN 
        SET NEW.status = 'ok_2';
    ELSEIF NEW.status IS NULL THEN
        SET NEW.status = 'ok';
    END IF;
END

Can anyone tell me why the first condition is never met even if I am inserting the same FKx_id combination that is already present in the table?

EDIT : I switched the condition and the result is also the same - no 'ok_2' status set:

BEGIN
    DECLARE cnt INT;
    SET cnt = (SELECT COUNT(*) FROM `table` WHERE `FK1_id` = NEW.FK1_id AND `FK2_id` = NEW.FK2_id);
    IF cnt = 0 AND NEW.status IS NULL THEN 
        SET NEW.status = 'ok';
    ELSEIF NEW.status IS NULL THEN
        SET NEW.status = 'ok_2';
    END IF;
END

Got it.

The problem was this declaration of the status column:

status enum('ok', 'ok_2', 'not_ok') NOT NULL

which leads into status being pre-filled with the first enum's value if the status is not set in the INSERT statement. So the solution is next trigger body:

BEGIN
    DECLARE cnt INT;
    SET cnt = (SELECT COUNT(*) FROM `table` WHERE `FK1_id` = NEW.FK1_id AND `FK2_id` = NEW.FK2_id);
    IF cnt = 0 THEN 
        SET NEW.status = 'ok';
    ELSEIF NEW.status = 'ok' THEN
        SET NEW.status = 'ok_2';
    END IF;
END

Now if I do this insert for the first time

INSERT INTO table (FK_1, FK_2) VALUES (100, 150)

the status is 'ok' , if I insert this for the second time

INSERT INTO table (FK_1, FK_2) VALUES (100, 150)

the status is 'ok_2' and if I set the status explicitly like this:

INSERT INTO table (FK_1, FK_2, status) VALUES (100, 150, 'not_ok')

the status is 'not_ok' .

so, when working with enums that have no default value while are set as NOT NULL - do not expect them to be NULL on insert when omitted. The will be pre-filled probably with the first enums's value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM