2017-02-22 3 views
0

Ich habe eine MySQL-Datenbank mit einer Tabelle inventory mit mehreren Triggern eingerichtet, um Änderungen in einer zweiten Tabelle inventory_history zu erfassen. Ich aktualisiere zwei der Felder (sowohl in einer einzigen Abfrage als auch in zwei separaten Abfragen), und der Auslöser arbeitet konsistent nur an einem der beiden Felder (qty, aber nicht an last_sale). HierMySQL Trigger funktioniert auf einem Feld, nicht auf dem zweiten Feld, in der gleichen Tabelle

ist die lästige Abfrage:

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

Alternativ diese Abfrage Kombinationen nicht funktionieren entweder:

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

Hier die Tabellenkonstrukte sind und löst:

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 ; 

Also wieder funktioniert der qty Trigger, aber die last_sale nicht.

+0

seltsam, es scheint keine Probleme mit Ihrem Code zu geben, werde es selbst ausprobieren –

Antwort

0

Tage später stellt sich heraus, eine einfache, aber tiefe Erklärung zu sein (ist es nicht immer?).

Die Trigger-Anweisung habe ich oben war:

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

Das Problem mit dieser Aussage ist, dass es keine Wertänderung zum Beispiel NULL-0, nicht zu erfassen. Es erfasst nur einen Wert für einen anderen Wert. Also brauchte ich für die NULL Szenarien eine zweite Anweisung ADD:

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; 

Und die ganze Welt ist richtig. :)

0

Ich kann nicht reproduzieren das Problem:

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) 
Verwandte Themen