web-dev-qa-db-fra.com

Comment structurer la condition IF dans le déclencheur MySQL?

J'essaie d'écrire un déclencheur MySQL. J'ai deux tableaux comme celui-ci:

Table A------------------------------Table B

order_id--------sku---------------order_id----order_#----sku_copy

    568---------AAA---------------568---------2345
    567---------BBB---------------567---------6789-------empty column
    566---------CCC---------------566---------1234

Lorsqu'un client effectue un achat, un nouvel enregistrement est ajouté à chaque table. J'ai ajouté la colonne "sku_copy" au tableau B, afin qu'elle ne soit pas remplie lorsqu'un nouvel enregistrement est créé.

Lorsqu'un nouvel enregistrement est créé, je veux que mon déclencheur copie le champ "sku" du tableau A dans le champ "sku_copy" du tableau B. Cependant, le problème que j'ai est de savoir comment structurer la condition suivante dans le déclencheur.

SI: "order_id" dans le tableau A correspond à "order_id" dans le tableau B. ALORS: copiez "sku" de cet enregistrement du tableau A vers l'enregistrement du tableau B avec le "order_id" correspondant. Les données doivent être ajoutées au tableau B "sku_copy".

J'utilise le déclencheur SQL suivant mais il donne cette erreur lors de son exécution:

"# 1363 - Il n'y a pas de VIEILLE ligne sur le déclencheur INSERT"

Voici le déclencheur:

DELIMITER $$
CREATE TRIGGER trigger_name
    AFTER INSERT ON tableA
    FOR EACH ROW BEGIN

    INSERT INTO tableB
    SET sku_copy = OLD.sku,
         order_id = OLD.order_id,
        order = OLD.order;
END $$
DELIMITER ;

Quelqu'un peut-il me montrer comment corriger l'erreur dans ce code ou suggérer une meilleure?

Merci pour toute aide que vous pouvez apporter.

Voici une mise à jour:

J'ai essayé ce déclencheur (ce sont les données en direct au lieu d'être simplifiées comme dans les exemples ci-dessus) mais j'obtiens un code d'erreur:

"# 1064 - Vous avez une erreur dans votre syntaxe SQL; consultez le manuel qui correspond à la version de votre serveur MySQL pour la bonne syntaxe à utiliser près de" WHERE virtuemart_order_id = new.virtuemart_order_id; END IF; END "à la ligne 7"

Voici ce déclencheur:

DELIMITER $$
CREATE TRIGGER `sku_after_update` AFTER UPDATE ON `uau3h_virtuemart_order_items` 
  FOR EACH ROW
  BEGIN
    IF (old.order_item_sku_copy != new.order_item_sku)
    THEN
    UPDATE uau3h_virtuemart_orders
        SET order_item_sku_copy=new.order_item_sku,                      
    WHERE virtuemart_order_id=new.virtuemart_order_id;
    END IF;
  END$$
DELIMITER ;

Quelqu'un a-t-il des suggestions sur la façon de faire fonctionner ce déclencheur?

5
tk748

Je suppose que vous apprécierez d'abord TableB car il contient le order_no. Dans ce cas, vous devez utiliser une instruction de mise à jour dans votre déclencheur au lieu d'une instruction d'insertion:

SQL Fiddle

Configuration du schéma MySQL 5.6.6 m9 :

CREATE TABLE TableA(order_id INT, sku VARCHAR(10));

CREATE TABLE TableB(order_id INT, order_no VARCHAR(10),sku_copy VARCHAR(10));

GO
CREATE TRIGGER trigger_name
    AFTER INSERT ON TableA
    FOR EACH ROW BEGIN

    UPDATE TableB
    SET sku_copy = NEW.sku
    WHERE order_id = NEW.order_id;
END;
GO
INSERT INTO TableB(order_id, order_no)VALUES(1,'111');
INSERT INTO TableB(order_id, order_no)VALUES(2,'222');
INSERT INTO TableB(order_id, order_no)VALUES(3,'333');
GO
INSERT INTO TableA(order_id, sku)VALUES(1,'AAA'),(2,'BBB');

(Le GO dans cet exemple est utilisé comme séparateur de lots et n'est pas envoyé à MySQL.)

Requête 1 :

SELECT * FROM TableB;

Résultats:

| ORDER_ID | ORDER_NO | SKU_COPY |
----------------------------------
|        1 |      111 |      AAA |
|        2 |      222 |      BBB |
|        3 |      333 |   (null) |

Si vous souhaitez également réagir aux mises à jour, créez simplement un AFTER UPDATE déclencher comme ceci:

SQL Fiddle

Configuration du schéma MySQL 5.6.6 m9 :

CREATE TABLE TableA(order_id INT, sku VARCHAR(10));

CREATE TABLE TableB(order_id INT, order_no VARCHAR(10),sku_copy VARCHAR(10));

GO
CREATE TRIGGER TableA_AfterInsert
    AFTER INSERT ON TableA
    FOR EACH ROW BEGIN

    UPDATE TableB
    SET sku_copy = NEW.sku
    WHERE order_id = NEW.order_id;
END;
GO
INSERT INTO TableB(order_id, order_no)VALUES(1,'111');
INSERT INTO TableB(order_id, order_no)VALUES(2,'222');
INSERT INTO TableB(order_id, order_no)VALUES(3,'333');
GO
INSERT INTO TableA(order_id, sku)VALUES(1,'AAA'),(2,'BBB');
GO
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
GO
CREATE TRIGGER TableA_AfterUpdate
    AFTER UPDATE ON TableA
    FOR EACH ROW BEGIN

    IF (OLD.sku != NEW.sku)
    THEN
      UPDATE TableB
      SET sku_copy = NEW.sku
      WHERE order_id = NEW.order_id;
    END IF;
END;
GO
UPDATE TableA
  SET sku = 'NEW'
WHERE order_id = 2;
GO

Requête 1 :

SELECT * FROM TableB;

Résultats:

| ORDER_ID | ORDER_NO | SKU_COPY |
----------------------------------
|        1 |      111 |      AAA |
|        2 |      222 |      NEW |
|        3 |      333 |   (null) |

Dans les deux cas, les tables virtuelles NEW et OLD font référence à la table sur laquelle le déclencheur est défini. NEW contient la nouvelle version de la ligne qui a été insérée ou modifiée. OLD contient la version pré-modification de la ligne. OLD n'est défini que dans un déclencheur de mise à jour car il n'y a pas d'ancienne version sur un insert.

3
Sebastian Meine