2017-02-22 46 views
0

У меня есть база данных MySQL с таблицей inventory с несколькими триггерами, настроенными для захвата изменений во второй таблице inventory_history. Я обновляю два поля (как в одном запросе, так и в двух отдельных запросах), и триггер последовательно работает только в одном из двух полей (qty, но не на last_sale).Триггер MySQL работает в одном поле, а не во втором поле, в той же таблице

Вот хлопотно запрос:

UPDATE inventory SET last_sale = 321, qty = 0 WHERE id = 123; 

С другой стороны, эти комбинации запросов не работают либо:

UPDATE inventory SET last_sale = 321 WHERE id = 123; 
UPDATE inventory SET qty = 0 WHERE id = 123; 

Вот таблица конструкции и триггеры:

CREATE TABLE `inventory` (
    `serial_no` varchar(255) DEFAULT NULL, 
    `qty` mediumint(9) DEFAULT NULL, 
    `partid` mediumint(9) unsigned DEFAULT NULL, 
    `last_sale` mediumint(9) unsigned DEFAULT NULL, 
    `date_created` timestamp NULL DEFAULT CURRENT_TIMESTAMP, 
    `id` mediumint(9) unsigned NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY (`id`), 
    KEY `partid` (`partid`), 
    KEY `date_created` (`date_created`), 
    KEY `last_sale` (`last_sale`), 
    KEY `last_rma` (`last_return`), 
    KEY `last_purchase` (`last_purchase`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

CREATE TABLE `inventory_history` (
    `date` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    `inventory_id` mediumint(9) unsigned NOT NULL, 
    `field_changed` enum('serial_no','qty','partid','last_sale','new') NOT NULL, 
    `changed_from` varchar(255) NOT NULL, 
    KEY `inventory_id` (`inventory_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

CREATE TRIGGER `inv_new` AFTER INSERT ON `inventory` 
FOR EACH ROW BEGIN 
    SET 
    @id = NEW.id, 
    @userid = NEW.userid, 
    @date = now(); 

    INSERT INTO inventory_history VALUES (@date,@userid, @id, 'new', 'new'); 
END 
// 
DELIMITER ; 
DROP TRIGGER IF EXISTS `inv_update`; 
DELIMITER // 
CREATE TRIGGER `inv_update` AFTER UPDATE ON `inventory` 
FOR EACH ROW BEGIN 
    SET @userid = OLD.userid; 
    SET @inv_id = OLD.id; 

    IF (OLD.serial_no <> NEW.serial_no) THEN 
    INSERT INTO inventory_history VALUES (now(), @userid, @inv_id, 'serial_no', OLD.serial_no); 
    END IF; 

    IF (OLD.qty <> NEW.qty) THEN 
    INSERT INTO inventory_history VALUES (now(), @userid, @inv_id, 'qty', OLD.qty); 
    END IF; 

    IF (OLD.partid <> NEW.partid) THEN 
    INSERT INTO inventory_history VALUES (now(), @userid, @inv_id, 'partid', OLD.partid); 
    END IF; 

    IF (OLD.last_sale <> NEW.last_sale) THEN 
    INSERT INTO inventory_history VALUES (now(), @userid, @inv_id, 'last_sale', OLD.last_sale); 
    END IF; 
END 
// 
DELIMITER ; 

Итак, снова работает триггер qty, но last_sale этого не делает.

+0

странно, похоже, проблем с кодом не возникает, –

ответ

0

Через несколько дней, оказывается простой, но глубокое объяснение (не всегда?).

Заявление триггера я выше был:

IF (OLD.last_sale <> NEW.last_sale) THEN 
    INSERT INTO inventory_history VALUES (now(), @userid, @inv_id, 'last_sale', OLD.last_sale); 
    END IF; 

Проблема с этим утверждением является то, что он не отражает изменения значений от NULL к 0, например. Он только фиксирует значение для другого значения. Поэтому мне нужно было добавить второе заявление для NULL сценариев:

IF (OLD.last_sale IS NULL AND NEW.last_sale IS NOT NULL) THEN 
    INSERT INTO inventory_history VALUES (now(), @userid, @inv_id, 'last_sale', OLD.last_sale); 
    END IF; 

И весь мир правильно. :)

0

Я не могу воспроизвести проблему:

mysql> DROP TABLE IF EXISTS `inventory_history`, `inventory`; 
Query OK, 0 rows affected (0.00 sec) 

mysql> CREATE TABLE `inventory` (
    -> `serial_no` varchar(255) DEFAULT NULL, 
    -> `qty` mediumint(9) DEFAULT NULL, 
    -> `partid` mediumint(9) unsigned DEFAULT NULL, 
    -> `last_sale` mediumint(9) unsigned DEFAULT NULL, 
    -> `date_created` timestamp NULL DEFAULT CURRENT_TIMESTAMP, 
    -> `id` mediumint(9) unsigned NOT NULL AUTO_INCREMENT, 
    -> PRIMARY KEY (`id`), 
    -> KEY `partid` (`partid`), 
    -> KEY `date_created` (`date_created`), 
    -> KEY `last_sale` (`last_sale`) 
    ->) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
Query OK, 0 rows affected (0.00 sec) 

mysql> CREATE TABLE `inventory_history` (
    -> `date` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    -> `inventory_id` mediumint(9) unsigned NOT NULL, 
    -> `field_changed` enum('serial_no', 'qty', 'partid', 'last_sale', 'new') NOT NULL, 
    -> `changed_from` varchar(255) NOT NULL, 
    -> KEY `inventory_id` (`inventory_id`) 
    ->) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
Query OK, 0 rows affected (0.01 sec) 

mysql> DELIMITER // 

mysql> CREATE TRIGGER `inv_new` AFTER INSERT ON `inventory` 
    -> FOR EACH ROW 
    -> BEGIN 
    -> DECLARE `_id` MEDIUMINT UNSIGNED DEFAULT NEW.`id`; 
    -> DECLARE `_date` TIMESTAMP DEFAULT NOW(); 
    -> INSERT INTO `inventory_history` VALUES (`_date`, `_id`, 'new', 'new'); 
    -> END// 
Query OK, 0 rows affected (0.00 sec) 

mysql> DELIMITER ; 

mysql> DROP TRIGGER IF EXISTS `inv_update`; 
Query OK, 0 rows affected, 1 warning (0.00 sec) 

mysql> DELIMITER // 

mysql> CREATE TRIGGER `inv_update` AFTER UPDATE ON `inventory` 
    -> FOR EACH ROW 
    -> BEGIN 
    -> DECLARE `_inv_id` MEDIUMINT UNSIGNED DEFAULT OLD.`id`; 
    -> 
    -> IF (OLD.`serial_no` <> NEW.`serial_no`) THEN 
    ->  INSERT INTO `inventory_history` VALUES (NOW(), `_inv_id`, 'serial_no', OLD.`serial_no`); 
    -> END IF; 
    -> 
    -> IF (OLD.`qty` <> NEW.`qty`) THEN 
    ->  INSERT INTO `inventory_history` VALUES (NOW(), `_inv_id`, 'qty', OLD.`qty`); 
    -> END IF; 
    -> 
    -> IF (OLD.`partid` <> NEW.`partid`) THEN 
    ->  INSERT INTO `inventory_history` VALUES (NOW(), `_inv_id`, 'partid', OLD.`partid`); 
    -> END IF; 
    -> 
    -> IF (OLD.`last_sale` <> NEW.`last_sale`) THEN 
    ->  INSERT INTO `inventory_history` VALUES (NOW(), `_inv_id`, 'last_sale', OLD.`last_sale`); 
    -> END IF; 
    -> END// 
Query OK, 0 rows affected (0.00 sec) 

mysql> DELIMITER ; 

mysql> INSERT INTO `inventory` 
    -> (`serial_no`, `qty`, `partid`, `last_sale`) 
    -> VALUES 
    -> ('1', 0, 0, 321); 
Query OK, 1 row affected (0.00 sec) 

mysql> SELECT 
    -> `serial_no`, 
    -> `qty`, 
    -> `partid`, 
    -> `last_sale`, 
    -> `date_created`, 
    -> `id` 
    -> FROM 
    -> `inventory`; 
+-----------+------+--------+-----------+---------------------+----+ 
| serial_no | qty | partid | last_sale | date_created  | id | 
+-----------+------+--------+-----------+---------------------+----+ 
| 1   | 0 |  0 |  321 | 2016-11-15 00:00:51 | 1 | 
+-----------+------+--------+-----------+---------------------+----+ 
1 row in set (0.00 sec) 

mysql> SELECT 
    -> `date`, 
    -> `inventory_id`, 
    -> `field_changed`, 
    -> `changed_from` 
    -> FROM 
    -> `inventory_history`; 
+---------------------+--------------+---------------+--------------+ 
| date    | inventory_id | field_changed | changed_from | 
+---------------------+--------------+---------------+--------------+ 
| 2016-11-15 00:00:51 |   1 | new   | new   | 
+---------------------+--------------+---------------+--------------+ 
1 row in set (0.00 sec) 

mysql> UPDATE `inventory` 
    -> SET `last_sale` = 0, `qty` = 321 
    -> WHERE `id` = 1; 
Query OK, 1 row affected (0.00 sec) 
Rows matched: 1 Changed: 1 Warnings: 0 

mysql> SELECT 
    -> `date`, 
    -> `inventory_id`, 
    -> `field_changed`, 
    -> `changed_from` 
    -> FROM 
    -> `inventory_history`; 
+---------------------+--------------+---------------+--------------+ 
| date    | inventory_id | field_changed | changed_from | 
+---------------------+--------------+---------------+--------------+ 
| 2016-11-15 00:00:51 |   1 | new   | new   | 
| 2016-11-15 00:00:51 |   1 | qty   | 0   | 
| 2016-11-15 00:00:51 |   1 | last_sale  | 321   | 
+---------------------+--------------+---------------+--------------+ 
3 rows in set (0.00 sec) 

mysql> SELECT 
    -> `serial_no`, 
    -> `qty`, 
    -> `partid`, 
    -> `last_sale`, 
    -> `date_created`, 
    -> `id` 
    -> FROM 
    -> `inventory`; 
+-----------+------+--------+-----------+---------------------+----+ 
| serial_no | qty | partid | last_sale | date_created  | id | 
+-----------+------+--------+-----------+---------------------+----+ 
| 1   | 321 |  0 |   0 | 2016-11-15 00:00:51 | 1 | 
+-----------+------+--------+-----------+---------------------+----+ 
1 row in set (0.00 sec)