Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Arbeiten mit Triggern in einer MySQL-Datenbank – Ein Tutorial

Ein Auslöser ist ein vordefinierter SQL-Befehl, der automatisch ausgeführt wird, wenn bestimmte Aktionen in der Datenbank auftreten. Es kann entweder vor oder nach einem INSERT ausgelöst werden , UPDATE , oder DELETE Veranstaltung.

Trigger werden hauptsächlich verwendet, um die Softwarelogik im MySQL-Server aufrechtzuerhalten, und sie haben mehrere Vorteile:

  • Trigger helfen dabei, globale Vorgänge an einem Ort zu zentralisieren.

  • Sie reduzieren den clientseitigen Code und tragen dazu bei, die Roundtrips zum Datenbankserver zu minimieren.

  • Sie tragen dazu bei, Anwendungen über verschiedene Plattformen besser skalierbar zu machen.

Einige gängige Anwendungsfälle von Triggern umfassen die Audit-Protokollierung, die Vorberechnung von Datenbankwerten (z. B. kumulative Summen) und die Durchsetzung komplexer Datenintegritäts- und Validierungsregeln.

In diesem Handbuch erfahren Sie:

  • Wie die Syntax für einen Trigger aufgebaut ist.

  • So erstellen Sie Trigger, die ausgeführt werden, bevor andere Datenbankereignisse eintreten.

  • So erstellen Sie Trigger, die ausgeführt werden, nachdem andere Datenbankereignisse eingetreten sind.

  • So löschen Sie Trigger.

Bevor Sie beginnen

  1. Wenn Sie dies noch nicht getan haben, erstellen Sie ein Linode-Konto und eine Compute-Instanz. Sehen Sie sich unsere Leitfäden Erste Schritte mit Linode und Erstellen einer Compute-Instanz an.

  2. Folgen Sie unserem Leitfaden zum Einrichten und Sichern einer Compute-Instanz, um Ihr System zu aktualisieren. Möglicherweise möchten Sie auch die Zeitzone festlegen, Ihren Hostnamen konfigurieren, ein eingeschränktes Benutzerkonto erstellen und den SSH-Zugriff sichern.

  3. Ein MySQL-Server und -Client, der auf dem Linode-Server installiert ist. Installationsanleitungen für MySQL sind für verschiedene Distributionen in unserem MySQL-Bereich verfügbar.

Datenbank vorbereiten

Um besser zu verstehen, wie Trigger funktionieren, erstellen wir eine Beispieldatenbank und fügen ihr Beispieldaten hinzu. Später werden wir verschiedene Trigger in der Datenbank als Proof-of-Concept-Übung erstellen.

  1. Melden Sie sich zuerst bei Ihrem MySQL-Server an:

    mysql -u root -p
    

    Geben Sie dann das Root-Passwort Ihres MySQL-Servers ein und drücken Sie Enter um fortzufahren.

  2. Als nächstes sehen Sie eine MySQL-Eingabeaufforderung ähnlich der unten gezeigten:

    mysql >
  3. Erstellen Sie eine test_database indem Sie den folgenden Befehl ausführen:

    CREATE DATABASE test_database;
    

    Ausgabe:

    Query OK, 1 row affected (0.02 sec)
  4. Zur Datenbank wechseln:

    USE test_database;
    

    Ausgabe:

    Database changed
  5. Sobald die Datenbank ausgewählt ist, erstellen wir einige Tabellen, die wir zum Demonstrieren von Triggern verwenden werden. Wir beginnen mit der Erstellung der stores Tisch. Diese Tabelle enthält Informationen zu zwei beispielhaften Geschäften/Büros, von denen aus unser hypothetisches Unternehmen tätig ist:

    CREATE TABLE stores
    (
    store_id BIGINT PRIMARY KEY AUTO_INCREMENT,
    store_name VARCHAR(50)
    ) ENGINE=InnoDB;
    

    Ausgabe:

    Query OK, 0 rows affected (0.07 sec)
  6. Fügen Sie als Nächstes zwei Datensätze zu den stores hinzu Tabelle, indem Sie die folgenden Befehle ausführen:

    INSERT INTO stores (store_name) VALUES ('Philadelphia');
    INSERT INTO stores (store_name) VALUES ('Galloway');
    

    Nach jedem Befehl erhalten Sie die folgende Ausgabe:

    Query OK, 1 row affected (0.08 sec)
    ...
  7. Bestätigen Sie die Datensätze, indem Sie den folgenden Befehl ausführen:

    SELECT * FROM stores;
    

    Ausgabe:

    +----------+--------------+
    | store_id | store_name   |
    +----------+--------------+
    |        1 | Philadelphia |
    |        2 | Galloway     |
    +----------+--------------+
    2 rows in set (0.01 sec)
  8. Erstellen Sie als Nächstes die products Tisch. Der Tisch enthält verschiedene Produkte, die im Geschäft angeboten werden:

    CREATE TABLE products
    (
    product_id BIGINT PRIMARY KEY AUTO_INCREMENT,
    product_name VARCHAR(40),
    cost_price DOUBLE,
    retail_price DOUBLE,
    availability VARCHAR(5)
    ) ENGINE=InnoDB;
    

    Ausgabe:

    Query OK, 0 rows affected (0.13 sec)
    • Jedes Produkt wird eindeutig durch eine product_id identifiziert .

    • Ein product_name Feld gibt die Namen der Elemente an.

    • Der cost_price und retail_price Felder bestimmen den Kauf- bzw. Verkaufspreis.

    • Eine availability Spalte definiert die Produktverfügbarkeit in den verschiedenen Filialen. Wenn das Produkt nur in unserem örtlichen Geschäft (Philadelphia) erhältlich ist, kennzeichnen wir es mit einem LOCAL Wert. Andernfalls verwenden wir den Wert von ALL um ein Produkt zu kennzeichnen, das in beiden Läden (Philadelphia und Galloway) erhältlich ist.

  9. Beispieldaten zu den products hinzufügen Tabelle:

    INSERT INTO products (product_name, cost_price, retail_price, availability) VALUES ('WIRELESS MOUSE', '18.23', '30.25','ALL');
    
    INSERT INTO products (product_name, cost_price, retail_price, availability) VALUES ('8 MP CAMERA', '60.40', '85.40','ALL');
    
    INSERT INTO products (product_name, cost_price, retail_price, availability) VALUES ('SMART WATCH', '189.60', '225.30','LOCAL');
    

    Nach jedem Einfügebefehl erhalten Sie die unten gezeigte Ausgabe:

    Query OK, 1 row affected (0.02 sec)
    ...
  10. Bestätigen Sie, ob die Produkte eingefügt wurden, indem Sie den folgenden Befehl ausführen:

    SELECT * FROM products;
    

    Ausgabe:

    +------------+----------------+------------+--------------+--------------+
    | product_id | product_name   | cost_price | retail_price | availability |
    +------------+----------------+------------+--------------+--------------+
    |          1 | WIRELESS MOUSE |      18.23 |        30.25 | ALL          |
    |          2 | 8 MP CAMERA    |       60.4 |         85.4 | ALL          |
    |          3 | SMART WATCH    |      189.6 |        225.3 | LOCAL        |
    +------------+----------------+------------+--------------+--------------+
    3 rows in set (0.00 sec)
  11. Als nächstes wird die Verfügbarkeit der Produkte einer anderen Tabelle mit dem Namen products_to_stores zugeordnet . Diese Tabelle verweist nur auf die product_id aus den products Tabelle und die store_id aus den stores Tabelle, wo der Artikel verfügbar ist.

    Erstellen Sie die products_to_stores Tabelle, indem Sie den folgenden Code ausführen:

    CREATE TABLE products_to_stores
    (
    ref_id BIGINT PRIMARY KEY AUTO_INCREMENT,
    product_id BIGINT,
    store_id BIGINT
    ) ENGINE=InnoDB;
    

    Ausgabe:

    Query OK, 0 rows affected (0.14 sec)
  12. Als Nächstes erstellen wir ein archived_products Tisch. Die Tabelle enthält Informationen zu gelöschten Produkten zur späteren Bezugnahme:

    CREATE TABLE archived_products
    (
    product_id BIGINT PRIMARY KEY ,
    product_name VARCHAR(40),
    cost_price DOUBLE,
    retail_price DOUBLE,
    availability VARCHAR(5)
    ) ENGINE=InnoDB;
    

    Ausgabe:

    Query OK, 0 rows affected (0.14 sec)
  13. Zuletzt erstellen wir eine products_price_history Tabelle zum Verfolgen der unterschiedlichen Preise der einzelnen Produkte im Laufe der Zeit:

    CREATE TABLE products_price_history
    (
    product_id BIGINT PRIMARY KEY AUTO_INCREMENT,
    price_date DATETIME,
    retail_price DOUBLE
    ) ENGINE=InnoDB;
    

    Ausgabe:

    Query OK, 0 rows affected (0.14 sec)

Sobald unsere Datenbankstruktur eingerichtet ist, können wir nun fortfahren und die grundlegende Syntax eines MySQL-Datenbank-Triggers lernen, um unser erstes Beispiel zu erstellen.

Trigger-Syntax

Wie bereits erwähnt, werden Trigger automatisch ausgelöst, entweder bevor oder nachdem ein SQL-Befehl in der Datenbank ausgeführt wird. Die grundlegende Syntax zum Erstellen von Triggern lautet wie folgt:

CREATE TRIGGER TRIGGER_NAME

TRIGGER_TIME TRIGGER_EVENT

ON TABLE_NAME FOR EACH ROW

[TRIGGER BODY];
  • TRIGGER_NAME :Jeder Trigger muss einen eindeutigen Namen haben und Sie sollten ihn hier definieren.

  • TRIGGER_TIME :Entweder BEFORE oder AFTER .

  • TRIGGER_EVENT :Sie müssen das Datenbankereignis angeben, das den Trigger aufruft:INSERT , UPDATE , oder DELETE .

  • TRIGGER BODY :Dies gibt den tatsächlichen SQL-Befehl (oder die Befehle) an, die von Ihrem Trigger ausgeführt werden sollen.

Wenn ein Trigger-Hauptteil mehr als eine SQL-Anweisung hat, müssen Sie ihn in ein BEGIN...END einschließen Block. Außerdem müssen Sie vorübergehend das DELIMITER ändern das signalisiert das Ende des Triggerkörpers auf einen neuen Wert. Dadurch wird sichergestellt, dass die Anweisungen im Body nicht vorzeitig von Ihrem MySQL-Client interpretiert werden. Ein Beispiel dafür sieht wie folgt aus:

DELIMITER &&

CREATE TRIGGER TRIGGER_NAME

TRIGGER_TIME TRIGGER_EVENT

ON TABLE_NAME FOR EACH ROW

BEGIN

[TRIGGER BODY]

END &&

DELIMITER ;
Hinweis Die letzte Zeile dieses Beispiels ändert das DELIMITER zurück zum Standard ; wert.

Vor-Ereignis-Trigger erstellen

In diesem Abschnitt sehen wir uns die verschiedenen Arten von Triggern an, die vor einer Datenbankoperation ausgelöst werden. Dazu gehört der BEFORE INSERT , BEFORE UPDATE , und BEFORE DELETE Auslöser.

Erstellen eines Triggers vor dem Einfügen

Wir erstellen unseren ersten BEFORE INSERT Abzug. Der Trigger stellt sicher, dass der Verkaufspreis eines Produkts höher ist als der Selbstkostenpreis, wenn Artikel in die products eingefügt werden Tisch. Andernfalls erhält der Datenbankbenutzer eine Fehlermeldung.

  1. Immer noch auf mysql > geben Sie den folgenden Befehl ein:

    DELIMITER $$
    
    CREATE TRIGGER price_validator
    
    BEFORE INSERT
    
    ON products FOR EACH ROW
    
    IF NEW.cost_price>=NEW.retail_price
    
    THEN
    
    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Retail price must be greater than cost price.';
    
    END IF $$
    
    DELIMITER ;
    
    • Der obige Code definiert den Auslösernamen (price_validator ), Zeit (BEFORE ), Ereignis (INSERT ) und die Tabelle (products ) betroffen sein.

    • Unser Trigger verwendet den NEW Schlüsselwort, um den cost_price zu prüfen und retail_price bevor ein Datensatz zu den products eingefügt wird Tabelle, mit dem IF...THEN...END IF Aussage.

    • Wenn der cost_price größer oder gleich dem retail price ist , weisen unsere Trigger MySQL an, eine benutzerdefinierte Ausnahme auszulösen, die den Benutzer anweist, den Fehler zu beheben.

  2. Um den obigen Auslöser zu testen, versuchen Sie, ein Produkt einzufügen, das gegen die Validierungsregel verstößt:

    INSERT INTO products (product_name, cost_price, retail_price, availability) VALUES ('GAMING MOUSE PAD', '145.00', '144.00','LOCAL');
    

    Ausgabe:

    ERROR 1644 (45000): Retail price must be greater than cost price.

    Die obigen Einfügebefehle sollten fehlschlagen, da der retail_price (144,00) ist nicht größer als cost_price (145,00).

Erstellen eines Vor-Update-Triggers

Als nächstes erstellen wir einen BEFORE UPDATE Abzug. Dieser Auslöser verhindert, dass Datenbankbenutzer einen Produktnamen bearbeiten, sobald ein Produkt in die Datenbank eingefügt wurde. Wenn Sie mehrere Benutzer haben, die in der Datenbank arbeiten, ein BEFORE UPDATE Trigger kann verwendet werden, um Werte schreibgeschützt zu machen, und dies kann böswillige oder unvorsichtige Benutzer daran hindern, Datensätze unnötig zu ändern.

  1. Erstellen Sie einen neuen product_name_validator Trigger mit dem folgenden Befehl:

    DELIMITER $$
    
    CREATE TRIGGER product_name_validator
    
    BEFORE UPDATE
    
    ON products FOR EACH ROW
    
    IF NEW.product_name<>OLD.product_name
    
    THEN
    
    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Product name is read-only and it can not be changed.';
    
    END IF $$
    
    DELIMITER ;
    

    Dieser Trigger vergleicht die Werte des neuen product_name (NEW.product_name ) und der alte Name bereits in der Datenbank (OLD.product_name ). Bei Nichtübereinstimmung wird eine Ausnahme ausgelöst.

  2. Zum Aufrufen des product_name_validator auslösen, können wir versuchen, den Namen des Produkts mit der ID 1 zu aktualisieren :

    UPDATE products SET product_name='WIRELESS BLUETOOTH MOUSE' WHERE product_id='1';
    

    Ausgabe:

    ERROR 1644 (45000): Product name is read-only and it can not be changed.

Definieren eines Triggers vor dem Löschen

In diesem Abschnitt erfahren Sie, wie Sie einen BEFORE DELETE definieren können Auslöser, um Benutzer daran zu hindern, bestimmte Datensätze aus einer Tabelle zu löschen.

  1. Um den prevent_delete zu erstellen auslösen, führen Sie den folgenden Befehl aus:

    DELIMITER $$
    
    CREATE TRIGGER prevent_delete
    
    BEFORE DELETE
    
    ON products FOR EACH ROW
    
    IF OLD.availability='ALL'
    
    THEN
    
    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'The product can not be deleted because it is available in ALL stores.';
    
    END IF $$
    
    DELIMITER ;
    

    Dieser Auslöser verhindert Produkte, die mit dem Wert ALL gekennzeichnet sind in der Verfügbarkeitsspalte gelöscht werden.

  2. Versuchen Sie als Nächstes, das erste Produkt aus der Produkttabelle zu löschen, und prüfen Sie, ob der Trigger aufgerufen wird:

    DELETE FROM products WHERE product_id='1';
    

    Ausgabe:

    ERROR 1644 (45000): The product can not be deleted because it is available in ALL stores.

Wir haben uns die verschiedenen Trigger angesehen, die vor einer Datenbankoperation aufgerufen werden. Als nächstes werden wir uns die anderen Arten von Triggern ansehen, die nach Datenbankereignissen ausgelöst werden.

Nachereignisauslöser erstellen

In einer Produktionsumgebung möchten Sie möglicherweise, dass einige Trigger automatisch ausgeführt werden, nachdem ein Datenbankereignis eintritt (z. B. das Einfügen von Datensätzen in verschiedene Tabellen). Die folgenden Beispiele zeigen, wie diese Art von Triggern in unserer Beispieldatenbank verwendet werden können.

Erstellen eines After-Insert-Triggers

Dieses Beispiel erstellt einen Trigger namens product_availability das Zuordnungsdatensätze in products_to_stores einfügt Tisch. Dieser Trigger wird verwendet, um die Geschäftslogik durchzusetzen; Insbesondere hilft es, die Produktverfügbarkeit für die verschiedenen Geschäfte zu definieren.

  1. Führen Sie den folgenden Code aus, um product_availability zu erstellen Abzug. Da wir mehrere Codezeilen im Triggerkörper haben, verwenden wir ein BEGIN...END blockieren:

    DELIMITER $$
    
    CREATE TRIGGER product_availability
    
    AFTER INSERT
    
    ON products FOR EACH ROW
    
    BEGIN
    
    IF NEW.availability='LOCAL' then
    
    INSERT INTO products_to_stores (product_id, store_id) VALUES (NEW.product_id, '1');
    
    ELSE
    
    INSERT INTO products_to_stores (product_id, store_id) VALUES (NEW.product_id, '1');
    
    INSERT INTO products_to_stores (product_id, store_id) VALUES (NEW.product_id, '2');
    
    END IF;
    
    END $$
    
    DELIMITER ;
    
    • Wenn ein Artikel in die products eingefügt wird Tabelle, der Trigger prüft die availability Feld.

    • Wenn es mit dem LOCAL gekennzeichnet ist Wert, wird das Produkt nur in einem Geschäft zur Verfügung gestellt.

    • Jeder andere Wert weist den Trigger an, das Produkt für die beiden Shops verfügbar zu machen, die wir zuvor erstellt haben.

  2. Um die product_availability zu sehen Trigger in Aktion, fügen Sie die beiden Datensätze in die Produkttabelle ein:

    INSERT INTO products (product_name, cost_price, retail_price, availability) VALUES ('BLUETOOTH KEYBOARD', '17.60', '23.30','LOCAL');
    INSERT INTO products (product_name, cost_price, retail_price, availability) VALUES ('DVB-T2 RECEIVE', '49.80', '53.40','ALL');
    
  3. Fragen Sie dann products_to_stores ab Tabelle:

    SELECT * FROM products_to_stores;
    

    Sie sollten eine Ausgabe ähnlich der unten gezeigten sehen:

    +--------+------------+----------+
    | ref_id | product_id | store_id |
    +--------+------------+----------+
    |      1 |          4 |        1 |
    |      2 |          5 |        1 |
    |      3 |          5 |        2 |
    +--------+------------+----------+
    3 rows in set (0.00 sec)

Definieren eines Triggers nach der Aktualisierung

Ein Trigger kann auch nach einem UPDATE ausgelöst werden Veranstaltung. Wir werden sehen, wie wir diese Art von Auslöser nutzen können, um Preisänderungen in unserem Geschäft im Laufe der Zeit zu verfolgen.

  1. Erstellen Sie einen product_history_updater auslösen, indem Sie den folgenden Befehl ausführen:

    CREATE TRIGGER product_history_updater
    
    AFTER UPDATE
    
    ON products FOR EACH ROW
    
    INSERT INTO products_price_history (product_id, price_date, retail_price) VALUES (OLD.product_id, NOW(), NEW.retail_price);
    

    Dieser Trigger zeichnet Änderungen am retail_price eines Produkts auf in der products_price_history Tabelle.

    Hinweis Im Gegensatz zu vorherigen Beispielen hat dieser Trigger nur eine Anweisung im Hauptteil des Triggers, sodass wir das DELIMITER nicht ändern müssen .
  2. Versuchen Sie dann, den Preis des ersten Produkts zu aktualisieren, indem Sie den folgenden Befehl ausführen:

    UPDATE products SET retail_price='36.75' WHERE product_id='1';
    
  3. Als nächstes fragen Sie products_price_history ab Tabelle, um zu sehen, ob die Preisänderung protokolliert wurde:

    SELECT * FROM products_price_history;
    

    Wenn der Trigger wie erwartet funktioniert hat, sollten Sie die folgende Ausgabe erhalten:

    +------------+---------------------+--------------+
    | product_id | price_date          | retail_price |
    +------------+---------------------+--------------+
    |          1 | 2020-01-28 11:46:21 |        36.75 |
    +------------+---------------------+--------------+
    1 row in set (0.00 sec)

Erstellen eines Triggers nach dem Löschen

In einigen Fällen möchten Sie möglicherweise Löschvorgänge protokollieren, nachdem eine bestimmte Aktion in der Datenbank ausgeführt wurde. Sie können dies erreichen, indem Sie den AFTER DELETE verwenden auslösen.

  1. Erstellen Sie einen neuen product_archiver Trigger mit dem folgenden Befehl:

    CREATE TRIGGER product_archiver
    
    AFTER DELETE
    
    ON products FOR EACH ROW
    
    INSERT INTO archived_products (product_id, product_name, cost_price, retail_price, availability) VALUES (OLD.product_id, OLD.product_name, OLD.cost_price, OLD.retail_price, OLD.availability);
    

    Dieser Trigger archiviert gelöschte Produkte in einer separaten Tabelle namens archived_products . Wenn ein Artikel aus den Haupt-products gelöscht wird Tabelle, unser Trigger wird sie automatisch in archived_products protokollieren Tabelle zum späteren Nachschlagen.

  2. Löschen Sie als Nächstes ein Produkt aus den products Tabelle und prüfen Sie, ob der Trigger aufgerufen wird:

    DELETE FROM products WHERE product_id='3';
    
  3. Wenn Sie nun die archived_products überprüfen Tabelle, sollten Sie einen Datensatz sehen:

    SELECT * FROM archived_products;
    

    Ausgabe:

    +------------+--------------+------------+--------------+--------------+
    | product_id | product_name | cost_price | retail_price | availability |
    +------------+--------------+------------+--------------+--------------+
    |          3 | SMART WATCH  |      189.6 |        225.3 | LOCAL        |
    +------------+--------------+------------+--------------+--------------+
    1 row in set (0.00 sec)

Löschen eines Triggers

Sie haben die verschiedenen Arten von Triggern gesehen und wie sie in einer Produktionsumgebung verwendet werden können. Manchmal möchten Sie vielleicht einen Trigger aus der Datenbank entfernen.

Sie können einen Trigger löschen, wenn Sie ihn nicht mehr verwenden möchten, indem Sie die folgende Syntax verwenden:

DROP TRIGGER IF EXISTS TRIGGER_NAME;
Hinweis Der IF EXISTS Schlüsselwort ist ein optionaler Parameter, der einen Trigger nur löscht, wenn er existiert.

Zum Beispiel, um product_archiving zu löschen Trigger, den wir oben definiert haben, verwenden Sie den folgenden Befehl:

DROP TRIGGER IF EXISTS product_archiver;

Ausgabe:

Query OK, 0 rows affected (0.00 sec)
Achtung Seien Sie vorsichtig, wenn Sie Tabellen löschen, die Triggern zugeordnet sind. Sobald eine Tabelle aus der MySQL-Datenbank gelöscht wird, werden die zugehörigen Trigger ebenfalls automatisch gelöscht.

Weitere Informationen

Weitere Informationen zu diesem Thema finden Sie in den folgenden Ressourcen. Obwohl diese in der Hoffnung bereitgestellt werden, dass sie nützlich sind, beachten Sie bitte, dass wir nicht für die Genauigkeit oder Aktualität extern gehosteter Materialien garantieren können.

  • MySQL-Triggersyntax und Beispiele