Триггер таблицы, указывающий, что две записи были объединены - PullRequest
0 голосов
/ 05 мая 2020

У меня есть несколько простых триггеров в таблице, которые работают для аудита изменений в записи путем записи в таблицу в любое время, когда происходит INSERT, UPDATE или DELETE. Когда запись вставляется в Users, создается копия в Users_History с полем Status, заполненным значением 'INSERT'. То же самое сделано для UPDATE и DELETE.

DELIMITER $$
CREATE TRIGGER Users_History_Insert AFTER INSERT ON Audit
FOR EACH ROW BEGIN  
    INSERT INTO Users_History select *, 'INSERT' from Users where ID = NEW.ID;
END$$
DELIMITER ;

DELIMITER $$
CREATE TRIGGER Users_History_Delete BEFORE DELETE ON Audit
FOR EACH ROW BEGIN  
    INSERT INTO Users_History select *, 'DELETE' from Users where ID = OLD.ID;
END$$
DELIMITER ;

DELIMITER $$
CREATE TRIGGER Users_History_Update AFTER UPDATE ON Audit
FOR EACH ROW BEGIN  
    INSERT INTO Users_History select *, 'UPDATE' from Users where ID = NEW.ID;
END$$
DELIMITER ;

У нас есть функция, в которой две записи Users могут быть объединены друг с другом. Фактически, все значения одной записи перезаписываются значениями другой записи, а неизмененная запись удаляется.

Если бы у вас была такая таблица:

| ID | Name  |  email         |
| 1  | Billy | bill@mail.com  |
| 2  | Bill  | bill2@mail.com |

И я хотел чтобы объединить запись 2 в 1, я бы получил следующий результат.

| ID | Name |  email          |
| 1  | Bill | bill2@mail.com  |

Я хотел бы создать триггер, который будет иметь это в Users_History, где 2 - это запись, из которой слита.

| Users_ID | Name | Email          | Status   |
| 1        | Bill | bill2@mail.com | MERGED:2 |

В нынешнем виде у нас будет две записи, UPDATE и DELETE

UPDATE `Users_To`
SET `Name` = `Users_From`.`Name`, `email` = `Users_From`.`email`
FROM `Users` AS `Users_To`
CROSS JOIN `Users` AS `Users_From`
WHERE `Users_To`.`ID` = 1 AND `Users_From`.`ID` = 2;

DELETE FROM `Users` WHERE `ID` = 2;

Я не могу придумать, как это сделать в SQL, это возможно? Насколько я понимаю, триггерам ничего не известно о предложениях JOIN или WHERE, влияющих на запись.

1 Ответ

0 голосов
/ 05 мая 2020

Ваш запрос UPDATE имеет недостаток и правильно

UPDATE `Users` AS `Users_To` CROSS JOIN `Users` AS `Users_From`
SET `Users_To`.`Name` = `Users_From`.`Name`, `Users_To`.`email` = `Users_From`.`email`
WHERE `Users_To`.`ID` = 1 AND `Users_From`.`ID` = 2;
DELETE FROM `Users` WHERE `ID` = 2;

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

В этом случае возьмите другой идентификатор в вашем случае 2 и добавьте его в текст.

Это работает, пока у вас есть только 2 строки, задействованные в вашем запросе на обновление.

И я не знаю вашу таблицу, но если у вас есть ограничение UNIQUE, у вас возникнут проблемы с обновлением.

DELIMITER $$
DROP TRIGGER IF EXISTS Users_History_Update;
CREATE TRIGGER Users_History_Update AFTER UPDATE ON users
FOR EACH ROW BEGIN  
    SELECT Count(*) INTO @number FROM Users WHERE `email` = NEW.`email`;
    IF @number > 1 THEN
        SELECT `ID` INTO @id FROM Users WHERE `email` = NEW.`email` AND `ID` <> NEW.`ID`;
        INSERT INTO Users_History VALUES (OLD.`ID`,OLD.`Name` ,OLD.`email`, CONCAT('MERGED:',@id));
    ELSE
        INSERT INTO Users_History VALUES (OLD.`ID`,OLD.`Name` ,OLD.`email`, 'UPDATE');
    END IF;
END$$
DELIMITER ;
...