DROP DATABASE IF EXISTS T;

CREATE DATABASE T;

USE T;

CREATE TABLE A (I4 INT, C255 CHAR(255), D DATETIME, F DECIMAL(12,4));
CREATE TABLE H (ColumnName CHAR(255), OldValue CHAR(255), NewValue CHAR(255), Time DATETIME, Type INT);

INSERT INTO A VALUES (1234, 'abcdefg', NOW(), 123456.789);

DELIMITER $$

CREATE TRIGGER A_BU BEFORE UPDATE ON A FOR EACH ROW 
BEGIN
  #Not happens
  INSERT INTO H
  SELECT Details.ColumnName,
         Details.OldValue,
         Details.NewValue,
         NOW() Time,
         1 Type
  FROM
  (
    SELECT '' ColumnName, '' OldValue, '' NewValue UNION
    SELECT 'I4' ColumnName,   OLD.I4,   NEW.I4   UNION
    SELECT 'C255' ColumnName, OLD.C255, NEW.C255 UNION
    SELECT 'D' ColumnName,    OLD.D,    NEW.D    UNION
    SELECT 'F' ColumnName,    OLD.F,    NEW.F    UNION
    SELECT '' ColumnName, '' OldValue, '' NewValue
  ) AS Details
  WHERE IFNULL(Details.OldValue, '') <> IFNULL(Details.NewValue, '')
  ;
  
  #Happens
  INSERT INTO H
  SELECT Details.ColumnName,
         Details.OldValue,
         Details.NewValue,
         NOW() Time,
         2 Type
  FROM
  (
    SELECT '' ColumnName, '' OldValue, '' NewValue UNION
    SELECT 'I4' ColumnName,   OLD.I4,   NEW.I4   UNION
    SELECT 'C255' ColumnName, OLD.C255, NEW.C255 UNION
    SELECT 'D' ColumnName,    OLD.D,    NEW.D    UNION
    SELECT 'F' ColumnName,    OLD.F,    NEW.F    UNION
    SELECT '' ColumnName, '' OldValue, '' NewValue
  ) AS Details
  #WHERE IFNULL(Details.OldValue, '') <> IFNULL(Details.NewValue, '')
  ;
        
  #ERROR
  INSERT INTO H
  SELECT Details.ColumnName,
         Details.OldValue,
         Details.NewValue,
         NOW() Time,
         3 Type
  FROM
  (
    SELECT '' ColumnName, '' OldValue, '' NewValue UNION
    SELECT 'I4' ColumnName,   OLD.I4 OldValue,   NEW.I4 NewValue   UNION
    SELECT 'C255' ColumnName, OLD.C255 OldValue, NEW.C255 NewValue UNION
    SELECT 'D' ColumnName,    OLD.D OldValue,    NEW.D NewValue    UNION
    SELECT 'F' ColumnName,    OLD.F OldValue,    NEW.F NewValue    UNION
    SELECT '' ColumnName, '' OldValue, '' NewValue
  ) AS Details
  WHERE IFNULL(Details.OldValue, '') <> IFNULL(Details.NewValue, '')
  ;

  END $$
   
DELIMITER ;

SELECT * FROM H;
UPDATE A SET I4 = 4321, C255 = 'gfedcba', D = NOW() - INTERVAL 1 YEAR, F = 0.123456789;
SELECT * FROM H;

