sql >> Databáze >  >> RDS >> Mysql

Práce se spouštěči v databázi MySQL – návod

spouštěč je předdefinovaný příkaz SQL, který se automaticky provede, když v databázi nastanou určité akce. Může být spuštěn buď před nebo po INSERT , UPDATE nebo DELETE událost.

Spouštěče se používají hlavně k udržování softwarové logiky na serveru MySQL a mají několik výhod:

  • Spouštěče pomáhají udržet globální operace centralizované na jednom místě.

  • Redukují kód na straně klienta a pomáhají minimalizovat zpáteční cesty k databázovému serveru.

  • Pomáhají dělat aplikace škálovatelnější na různých platformách.

Některé běžné případy použití spouštěčů zahrnují protokolování auditu, předvýpočet databázových hodnot (např. kumulativní součty) a vynucení komplexních pravidel integrity dat a ověřování.

V této příručce se dozvíte:

  • Jak je strukturována syntaxe spouštěče.

  • Jak vytvořit spouštěče, které se spouštějí předtím, než nastanou jiné databázové události.

  • Jak vytvořit spouštěče, které se spouštějí po výskytu jiných databázových událostí.

  • Jak odstranit spouštěče.

Než začnete

  1. Pokud jste tak ještě neučinili, vytvořte si účet Linode a Compute Instance. Podívejte se na naše příručky Začínáme s Linode a Vytvoření výpočetní instance.

  2. Při aktualizaci systému postupujte podle našeho průvodce nastavením a zabezpečením výpočetní instance. Můžete také chtít nastavit časové pásmo, nakonfigurovat název hostitele, vytvořit omezený uživatelský účet a posílit přístup SSH.

  3. Server a klient MySQL nainstalovaný na serveru Linode. Instalační příručky pro MySQL jsou k dispozici pro různé distribuce v naší sekci MySQL.

Příprava databáze

Abychom lépe porozuměli tomu, jak triggery fungují, vytvoříme vzorovou databázi a přidáme do ní vzorová data. Později v databázi vytvoříme různé spouštěče jako důkaz koncepčního cvičení.

  1. Nejprve se přihlaste k serveru MySQL:

    mysql -u root -p
    

    Poté zadejte heslo uživatele root vašeho serveru MySQL a stiskněte Enter pokračovat.

  2. Dále uvidíte výzvu MySQL podobnou té, která je zobrazena níže:

    mysql >
  3. Vytvořte test_database spuštěním příkazu níže:

    CREATE DATABASE test_database;
    

    Výstup:

    Query OK, 1 row affected (0.02 sec)
  4. Přepnout do databáze:

    USE test_database;
    

    Výstup:

    Database changed
  5. Jakmile je databáze vybrána, vytvoříme nějaké tabulky, které použijeme pro demonstraci spouštěčů. Začneme vytvořením stores stůl. Tato tabulka bude obsahovat informace o dvou vzorových prodejnách/kancelářích, z nichž naše hypotetická obchodní činnost působí:

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

    Výstup:

    Query OK, 0 rows affected (0.07 sec)
  6. Dále přidejte dva záznamy do stores tabulky spuštěním následujících příkazů:

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

    Po každém příkazu získáte následující výstup:

    Query OK, 1 row affected (0.08 sec)
    ...
  7. Potvrďte záznamy spuštěním příkazu níže:

    SELECT * FROM stores;
    

    Výstup:

    +----------+--------------+
    | store_id | store_name   |
    +----------+--------------+
    |        1 | Philadelphia |
    |        2 | Galloway     |
    +----------+--------------+
    2 rows in set (0.01 sec)
  8. Dále vytvořte products stůl. Na stole budou různé produkty nabízené v obchodě:

    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;
    

    Výstup:

    Query OK, 0 rows affected (0.13 sec)
    • Každý produkt bude jednoznačně identifikován pomocí product_id .

    • product_name pole bude specifikovat názvy položek.

    • cost_price a retail_price pole určí kupní a prodejní cenu.

    • availability bude definovat dostupnost produktu v různých obchodech. Pokud je produkt dostupný pouze v našem místním obchodě (Philadelphia), označíme jej LOCAL hodnota. Jinak použijeme hodnotu ALL označovat produkt, který je dostupný v obou obchodech (Philadelphia a Galloway).

  9. Přidejte ukázková data do products tabulka:

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

    Po každém příkazu vložení získáte výstup zobrazený níže:

    Query OK, 1 row affected (0.02 sec)
    ...
  10. Potvrďte, zda byly produkty vloženy spuštěním příkazu níže:

    SELECT * FROM products;
    

    Výstup:

    +------------+----------------+------------+--------------+--------------+
    | 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. Dále bude dostupnost produktů mapována do další tabulky s názvem products_to_stores . Tato tabulka bude pouze odkazovat na product_id z products tabulkou a store_id z stores tabulka, kde je položka dostupná.

    Vytvořte products_to_stores tabulky spuštěním kódu níže:

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

    Výstup:

    Query OK, 0 rows affected (0.14 sec)
  12. Dále vytvoříme archived_products stůl. Tabulka bude obsahovat informace o odstraněných produktech pro budoucí použití:

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

    Výstup:

    Query OK, 0 rows affected (0.14 sec)
  13. Nakonec vytvoříme products_price_history tabulka pro sledování různých cen jednotlivých produktů v průběhu času:

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

    Výstup:

    Query OK, 0 rows affected (0.14 sec)

Jakmile je struktura naší databáze na místě, můžeme nyní pokračovat a naučit se základní syntaxi spouštěče databáze MySQL, abychom vytvořili naši první ukázku.

Syntaxe spouštěče

Jak bylo uvedeno výše, spouštěče jsou spouštěny automaticky buď před nebo po spuštění příkazu SQL v databázi. Základní syntaxe pro vytváření spouštěčů je následující:

CREATE TRIGGER TRIGGER_NAME

TRIGGER_TIME TRIGGER_EVENT

ON TABLE_NAME FOR EACH ROW

[TRIGGER BODY];
  • TRIGGER_NAME :Každý spouštěč musí mít jedinečný název a měli byste jej definovat zde.

  • TRIGGER_TIME :Buď BEFORE nebo AFTER .

  • TRIGGER_EVENT :Musíte zadat databázovou událost, která vyvolá spouštěč:INSERT , UPDATE nebo DELETE .

  • TRIGGER BODY :Toto specifikuje skutečný SQL příkaz (nebo příkazy), které chcete spouštět vaším spouštěčem.

Pokud má tělo spouštěče více než jeden příkaz SQL, musíte jej uzavřít do BEGIN...END blok. Také budete muset dočasně změnit DELIMITER která signalizuje konec těla spouště na novou hodnotu. To zajišťuje, že příkazy v těle nebudou předčasně interpretovány vaším MySQL klientem. Příklad vypadá takto:

DELIMITER &&

CREATE TRIGGER TRIGGER_NAME

TRIGGER_TIME TRIGGER_EVENT

ON TABLE_NAME FOR EACH ROW

BEGIN

[TRIGGER BODY]

END &&

DELIMITER ;
Poznámka Poslední řádek tohoto příkladu změní DELIMITER zpět na výchozí ; hodnotu.

Vytvoření před spouštěči událostí

V této části se podíváme na různé typy spouštěčů, které se spouštějí před operací databáze. Patří mezi ně BEFORE INSERT , BEFORE UPDATE a BEFORE DELETE spouští.

Vytvoření spouštěče před vložením

Vytvoříme náš první BEFORE INSERT spoušť. Spouštěč zajistí, aby maloobchodní cena produktu byla vyšší než nákladová cena, kdykoli jsou položky vloženy do products stůl. Jinak se uživateli databáze zobrazí chyba.

  1. Ještě na mysql > zadejte následující příkaz:

    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 ;
    
    • Výše uvedený kód definuje název spouštěče (price_validator ), čas (BEFORE ), událost (INSERT ) a tabulku (products ), která má být ovlivněna.

    • Náš spouštěč používá NEW klíčové slovo pro kontrolu cost_price a retail_price před vložením záznamu do products pomocí tabulky IF...THEN...END IF prohlášení.

    • Pokud cost_price je větší nebo rovna retail price , naše spouštěče sdělují MySQL, aby vyvolalo vlastní výjimku, která uživateli dá pokyn, aby chybu napravil.

  2. Chcete-li výše uvedený spouštěč otestovat, zkuste vložit produkt, který porušuje ověřovací pravidlo:

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

    Výstup:

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

    Výše uvedené příkazy vložení by měly selhat, protože retail_price (144,00) není větší než cost_price (145,00).

Vytvoření spouštěče před aktualizací

Dále vytvoříme BEFORE UPDATE spoušť. Tento spouštěč zabrání uživatelům databáze upravovat název produktu, jakmile je produkt vložen do databáze. Pokud v databázi pracuje více uživatelů, BEFORE UPDATE spouštěč může být použit k tomu, aby byly hodnoty pouze pro čtení, což může zabránit zlomyslným nebo neopatrným uživatelům zbytečně upravovat záznamy.

  1. Vytvořte nový product_name_validator spusťte příkazem níže:

    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 ;
    

    Toto pravidlo porovnává hodnoty nového product_name (NEW.product_name ) a starý název, který je již v databázi (OLD.product_name ). Pokud dojde k neshodě, je vyvolána výjimka.

  2. Chcete-li vyvolat product_name_validator spouštěče, můžeme se pokusit aktualizovat název produktu pomocí ID 1 :

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

    Výstup:

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

Definování spouštěče před odstraněním

V této části uvidíte, jak můžete definovat BEFORE DELETE spouštěč, který uživatelům zabrání ve smazání konkrétních záznamů z tabulky.

  1. Chcete-li vytvořit prevent_delete spusťte níže uvedený příkaz:

    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 ;
    

    Toto pravidlo zabrání produktům označeným hodnotou ALL ve sloupci dostupnosti, aby nebyly odstraněny.

  2. Dále se pokuste odstranit první produkt z tabulky produktů a zjistěte, zda bude spouštěč vyvolán:

    DELETE FROM products WHERE product_id='1';
    

    Výstup:

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

Podívali jsme se na různé spouštěče, které se vyvolávají před operací databáze. Dále se podíváme na další typy spouštěčů, které se spouštějí po událostech databáze.

Vytvoření spouštěčů po událostech

V produkčním prostředí můžete chtít, aby se některé spouštěče automaticky spouštěly po výskytu databázové události (například vkládání záznamů do různých tabulek). Níže uvedené příklady ukazují, jak lze tyto druhy spouštěčů použít v naší vzorové databázi.

Vytvoření spouštěče po vložení

Tento příklad vytvoří pravidlo s názvem product_availability který vloží mapovací záznamy do products_to_stores stůl. Tento spouštěč se používá k vynucení obchodní logiky; zejména pomáhá definovat dostupnost produktů pro různé obchody.

  1. Spuštěním níže uvedeného kódu vytvořte product_availability spoušť. Protože v těle spouštěče máme více řádků kódu, použijeme BEGIN...END blokovat:

    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 ;
    
    • Když je položka vkládána do products tabulka, spouštěč zkontroluje availability pole.

    • Pokud je označena LOCAL hodnotu, bude produkt dostupný pouze v jednom obchodě.

    • Jakákoli jiná hodnota dá spouštěči pokyn, aby zpřístupnil produkt dvěma obchodům, které jsme vytvořili dříve.

  2. Chcete-li zobrazit product_availability trigger v akci, vložte dva záznamy do tabulky produktů:

    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. Poté zadejte dotaz na products_to_stores tabulka:

    SELECT * FROM products_to_stores;
    

    Měli byste vidět výstup podobný tomu zobrazenému níže:

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

Definování spouštěče po aktualizaci

Spouštěč lze spustit také po UPDATE událost. Uvidíme, jak můžeme tento typ spouštěče využít ke sledování změn cen v našem obchodě v průběhu času.

  1. Vytvořte product_history_updater spustit spuštěním příkazu níže:

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

    Tento spouštěč zaznamenává změny retail_price produktu v products_price_history tabulka.

    Poznámka Na rozdíl od předchozích příkladů má toto pravidlo pouze jeden příkaz v těle spouštěče, takže nemusíme měnit DELIMITER .
  2. Poté zkuste aktualizovat cenu prvního produktu spuštěním příkazu níže:

    UPDATE products SET retail_price='36.75' WHERE product_id='1';
    
  3. Dále se zeptejte products_price_history tabulka, abyste zjistili, zda byla zaznamenána změna ceny:

    SELECT * FROM products_price_history;
    

    Pokud spoušť fungovala podle očekávání, měli byste získat následující výstup:

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

Vytvoření spouštěče po odstranění

V některých případech můžete chtít zaznamenat operace odstranění poté, co v databázi došlo k určité akci. Toho lze dosáhnout pomocí AFTER DELETE spoušť.

  1. Vytvořte nový product_archiver spusťte příkazem níže:

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

    Tento spouštěč archivuje smazané produkty do samostatné tabulky s názvem archived_products . Když je položka odstraněna z hlavních products náš spouštěč jej automaticky zaznamená do archived_products tabulka pro budoucí použití.

  2. Dále odstraňte produkt z products tabulky a zjistěte, zda bude spouštěč vyvolán:

    DELETE FROM products WHERE product_id='3';
    
  3. Nyní, když zaškrtnete archived_products tabulky, měli byste vidět jeden záznam:

    SELECT * FROM archived_products;
    

    Výstup:

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

Odstranění spouštěče

Viděli jste různé typy spouštěčů a jak je lze použít v produkčním prostředí. Někdy můžete chtít odstranit spouštěč z databáze.

Pokud spouštěč již nechcete používat, můžete jej smazat pomocí níže uvedené syntaxe:

DROP TRIGGER IF EXISTS TRIGGER_NAME;
Poznámka IF EXISTS klíčové slovo je volitelný parametr, který smaže spouštěč, pouze pokud existuje.

Chcete-li například odstranit product_archiving trigger, který jsme definovali výše, použijte níže uvedený příkaz:

DROP TRIGGER IF EXISTS product_archiver;

Výstup:

Query OK, 0 rows affected (0.00 sec)
Pozor Při odstraňování tabulek spojených se spouštěči buďte opatrní. Jakmile je tabulka odstraněna z databáze MySQL, související spouštěče jsou také automaticky odstraněny.

Další informace

Další informace o tomto tématu můžete získat v následujících zdrojích. Přestože jsou poskytovány v naději, že budou užitečné, vezměte prosím na vědomí, že nemůžeme ručit za přesnost nebo aktuálnost externě hostovaných materiálů.

  • Syntaxe a příklady spouštěče MySQL

  1. Časové razítko s přesností na milisekundy:Jak je uložit v MySQL

  2. Jak vytvořit bezpečný příkaz připravený mysql v php?

  3. Jak odebrat záhlaví sloupců při odesílání výsledků dotazu e-mailem na SQL Server (T-SQL)

  4. Optimalizace dotazů v PostgreSQL. Základy VYSVĚTLENÍ – 3. část