2016-01-23 4 views
0

Я не знаю, если это возможно, но я хочу, чтобы отслеживать изменения в таблице 1.Mysql Триггеры: Отслеживание изменений

В базе данных следующие две таблицы существует:

CREATE TABLE IF NOT EXISTS `db`.`table1` (
    `idtable1` INT NOT NULL AUTO_INCREMENT, 
    `A` VARCHAR(45) NULL, 
    `B` VARCHAR(45) NULL, 
    `C` VARCHAR(45) NULL, 
    PRIMARY KEY (`idtable1`)) 
ENGINE = InnoDB 


CREATE TABLE IF NOT EXISTS `db`.`table2history` (
    `idtable2history` INT NOT NULL AUTO_INCREMENT, 
    `columnName` ENUM('A', 'B', 'C') NULL, 
    `columnPrimaryKey` INT NULL, 
    `columnNewValue` VARCHAR(45) NULL, 
    `changetimestamp` DATETIME NULL, 
    PRIMARY KEY (`idtable2history`)) 
ENGINE = InnoDB 

Если следующие инструкции выполняются:

UPDATE table1 SET A="ABC", B="XYZ" WHERE idtable1=50; 

Триггер "ПЕРЕД UPDATE" следует выполнить:

INSERT INTO table2history (idtable2history, columnName, columnPrimaryKey, columnNewValue, changetimestamp) 
VALUES (NULL, "A", "50", "ABC", NOW()); 

INSERT INTO table2history (idtable2history, columnName, columnPrimaryKey, columnNewValue, changetimestamp) 
VALUES (NULL, "B", "50", "XYZ", NOW()); 

Если следующие инструкции выполняются:

UPDATE table1 SET A="123", B="456", C="789" WHERE idtable1=20; 

Триггер "ПЕРЕД UPDATE" следует выполнить:

INSERT INTO table2history (idtable2history, columnName, columnPrimaryKey, columnNewValue, changetimestamp) 
VALUES (NULL, "A", "20", "123", NOW()); 

INSERT INTO table2history (idtable2history, columnName, columnPrimaryKey, columnNewValue, changetimestamp) 
VALUES (NULL, "B", "20", "456", NOW()); 

INSERT INTO table2history (idtable2history, columnName, columnPrimaryKey, columnNewValue, changetimestamp) 
VALUES (NULL, "C", "20", "789", NOW()); 

Вы знаете, интеллектуальное решение для Эта проблема?

+0

Да, этого можно достичь. что ты уже испробовал? – Shadow

+0

создайте копию таблицы с тремя полями больше. временную метку, тип, в котором вы храните вставку, удаление или обновление и поле для имени пользователя. Создайте 3 тигра на INSERT, UPDATE, DELETE, где поместите строку отверстий в новую таблицу и добавьте временную метку, тип и пользователь. так что вы можете откатываться каждый раз и посмотреть, какое изменение –

+0

Благодарю вас за ответы. @ bernd-buffen Спасибо за возможное решение. Но я должен был реализовать его точно так, как описано выше. –

ответ

0

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

IF NOT (NEW.A <=> OLD.A) THEN 
    INSERT INTO table2history (idtable2history, columnName, columnPrimaryKey, columnNewValue, changetimestamp) 
    VALUES (NULL, "A",NEW.idtable1, NEW.A, NOW()); 
END IF; 

IF NOT (NEW.B <=> OLD.B) THEN 
... 

Тест IF NOT (expr1 <=> expr2) использует нулевое безопасное сравнение равенства («космический корабль») оператор <=>, который, в отличие от правильного сравнения равенств, будет учитывать значения NULL, а сравнение ненулевых значений с NULL с обеих сторон должно быть FALSE вместо NULL, а ведущий NOT инвертирует тест ... так что если старое значение не совпадает с новым значением для строки, INSERT выполняется запрос, иначе ничего не происходит, поскольку значение не изменилось.

OLD и NEW - это специальные псевдонимы для старых и новых версий ряда. Они одинаково действительны и содержат одинаковые значения для BEFORE UPDATE и AFTER UPDATE, но триггер, который фактически изменяетNEW Изображение работает только в триггере BEFORE. BEFORE, NEW означает «то, что строка будет обновлена,» и AFTER, NEW означает «то, что строка была обновлена.»

Вы, вероятно, на самом деле хотите, чтобы написать этот триггер AFTER UPDATE, просто потому, что вы, возможно, позже вы захотите добавить другой BEFORE UPDATE триггер, который делает проверку предлагаемого обновления, так как только один триггер для каждого времени может быть определена (до MySQL 5.7), и это позволит оставить этот триггер в одиночку.

Пуск должен проходить через каждый столбец, который вы отслеживаете, используя статические запросы, по одному для каждого столбца, поскольку триггеры не поддерживают использование подготовленных операторов и динамического SQL. Запись (генерирование) тела триггера путем итерации по столбцам со сценарием позволит вам немного времени на ввод текста, но теперь вы можете записать его вручную, и приведенный выше пример должен делать именно то, что вы намереваетесь.

Ваше тело триггера будет выглядеть так, как будто он много работает, но сервер будет работать через все это очень быстро.

Смежные вопросы