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
-
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.
-
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.
-
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.
-
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.
-
Als nächstes sehen Sie eine MySQL-Eingabeaufforderung ähnlich der unten gezeigten:
mysql >
-
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)
-
Zur Datenbank wechseln:
USE test_database;
Ausgabe:
Database changed
-
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)
-
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) ...
-
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)
-
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
undretail_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 einemLOCAL
Wert. Andernfalls verwenden wir den Wert vonALL
um ein Produkt zu kennzeichnen, das in beiden Läden (Philadelphia und Galloway) erhältlich ist.
-
-
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) ...
-
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)
-
Als nächstes wird die Verfügbarkeit der Produkte einer anderen Tabelle mit dem Namen
products_to_stores
zugeordnet . Diese Tabelle verweist nur auf dieproduct_id
aus denproducts
Tabelle und diestore_id
aus denstores
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)
-
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)
-
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
:EntwederBEFORE
oderAFTER
. -
TRIGGER_EVENT
:Sie müssen das Datenbankereignis angeben, das den Trigger aufruft:INSERT
,UPDATE
, oderDELETE
. -
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 dasDELIMITER
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.
-
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 dencost_price
zu prüfen undretail_price
bevor ein Datensatz zu denproducts
eingefügt wird Tabelle, mit demIF...THEN...END IF
Aussage. -
Wenn der
cost_price
größer oder gleich demretail price
ist , weisen unsere Trigger MySQL an, eine benutzerdefinierte Ausnahme auszulösen, die den Benutzer anweist, den Fehler zu beheben.
-
-
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 alscost_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.
-
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. -
Zum Aufrufen des
product_name_validator
auslösen, können wir versuchen, den Namen des Produkts mit der ID1
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.
-
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. -
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.
-
Führen Sie den folgenden Code aus, um
product_availability
zu erstellen Abzug. Da wir mehrere Codezeilen im Triggerkörper haben, verwenden wir einBEGIN...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 dieavailability
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.
-
-
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');
-
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.
-
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 derproducts_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 . -
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';
-
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.
-
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 inarchived_products
protokollieren Tabelle zum späteren Nachschlagen. -
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';
-
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