web-dev-qa-db-ja.com

MySQLトリガーでIF条件を構成する方法は?

MySQLトリガーを記述しようとしています。次のような2つのテーブルがあります。

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

顧客が購入すると、新しいレコードが各テーブルに追加されます。テーブルBに「sku_copy」列を追加したので、新しいレコードが作成されても、列にデータが入力されません。

新しいレコードが作成されたら、トリガーでテーブルAの「sku」フィールドをテーブルBの「sku_copy」フィールドにコピーします。ただし、トリガーで次の条件を構造化する方法に問題があります。

IF:テーブルAの「order_id」は、テーブルBの「order_id」と一致します。その後、「sku」をそのテーブルAレコードから、一致する「order_id」を持つテーブルBのレコードにコピーします。データをテーブルB「sku_copy」に追加する必要があります。

次のSQLトリガーを使用していますが、実行するとこのエラーが発生します。

"#1363-INSERTトリガーに古い行がありません"

これがトリガーです:

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 ;

誰かがこのコードのエラーを修正する方法を示したり、より良いものを提案したりできますか?

あなたが与えることができるあらゆる助けをありがとう。

ここに更新があります:

私はこのトリガーを試しましたが(これは上記の例のように単純化されたのではなく、ライブデータです)、エラーコードが表示されます。

"#1064-SQL構文にエラーがあります。MySQLサーバーのバージョンに対応するマニュアルで、7行目の 'WHERE virtuemart_order_id = new.virtuemart_order_id; END IF; END'の近くで使用する正しい構文を確認してください。

ここにそのトリガーがあります:

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 ;

このトリガーを機能させる方法について何か提案はありますか?

5
tk748

TableBにはorder_noが含まれているため、最初に評価することを想定しています。その場合は、トリガー内で挿入ステートメントの代わりに更新ステートメントを使用する必要があります。

SQLフィドル

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');

(この例のGOは、バッチ区切り記号として使用され、MySQLに送信されません。)

クエリ1

SELECT * FROM TableB;

結果

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

アップデートにも対応したい場合は、AFTER UPDATEこのようなトリガー:

SQLフィドル

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

クエリ1

SELECT * FROM TableB;

結果

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

どちらの場合でも、NEWおよびOLD仮想テーブルは、トリガーが定義されているテーブルを参照します。 NEWには、挿入または変更された行の新しいバージョンが含まれています。 OLDには、変更前のバージョンの行が含まれています。 OLDは、挿入に古いバージョンがないため、更新トリガーでのみ定義されます。

3
Sebastian Meine