Autor Zpráva
Milan1236000
Profil
Zdravím,

mám tabulku, ve které potřebuju udržovat u 2 záznamů v jednom sloupci stejné hodnoty.
Uživatel (administrátor) bude moct upravovat jen jeden záznam a ten druhý právě potřebuju triggerem aktualizovat podle prvního.


CREATE DEFINER=`root`@`localhost` TRIGGER `optional_responsible_groups` AFTER UPDATE ON `mantis_custom_field_table` FOR EACH ROW BEGIN

# custom field 10 is always up to date according to custom field 11
UPDATE mantis_custom_field_table
SET possible_values = (SELECT possible_values FROM mantis_custom_field_table WHERE id = 10)
WHERE id = 11;

END

Vyznačená část dotazu funguje běžně samostatně, ale trigger je takto asi špatně napsaný, protože mi při každé změně v této tabulce hází chybu. S triggerem jsem ještě nedělal, takže nevím, co konkrétně je špatně. Podezřívám jen část FOR EACH ROW, jestli by tam spíš být neměla.

Poradíte, prosím? :)

Díky.
Kajman
Profil
Možná se volání triggeru cyklí, nebo tam je kolize čtení a zápisu. Ono je dobré si tu chybu přečíst a poslat i s dotazem.

Zkusil bych v triggeru udělat podmínku, že se update má dělat, jen pokud aktuálně měněný řádek má id 10.

IF NEW.id = 10
THEN
  UPDATE mantis_custom_field_table
  SET possible_values = NEW.possible_values
  WHERE id = 11
        AND NOT possible_values <=> NEW.possible_values;
END IF;
Kcko
Profil
Kajman:
 AND NOT possible_values <=> NEW.possible_values;

Spaceship funguje i v MySQL? Co má vůbec tahle podmínkovat prezentovat?
Kajman
Profil
Tento operátor z mysql porovnává i null hodnoty.

A podmínka by měla dělat update, jen když je potřeba.
Kcko
Profil
Něco jako Vránův exclusivní or? Využití triggerů pro aktualizaci souhrnné informace
Neznal jsem, díky.
Kajman
Profil
Ne, on tím řeší případnou úpravu dvou řádků jedním dotazem, ale zase nemusí řešit null hodnoty, protože u těch sloupců nedává smysl null hodnota (sloupec je nejspíše nastaven na NOT NULL).
Kcko
Profil
Jasně, díky za vysvětlení.
Milan1236000
Profil
Moc díky za odpověď. Bohužel ani tento kód nefunguje. Zobrazuje se stejná hláška jako předtím:
SQL Error (1442): Can't update table 'mantis_custom_field_table' in stored function/trigger because it is already used by statement which invoked this stored function/trigger
Jen se nyní tato chyba zobrazuje při úpravě záznamu s id = 10.
Kcko
Profil
Kajman:
Doplňující otázka, není ta podmínka zbytečná? Update se stejně musí provést (fyzicky řádek neovlivní díky podmínce), ale režie zůstavá (vykonává se a nic se nestane).
Kajman
Profil
Milan1236000:
Podle hlášky to vypadá, že mysql nedovolí upravovat tabulku, nad kterou byl ten trigger puštěný.

Možná by pomohl event. Buď jednorázový, pokud jde vytvořit v triggeru, nebo nějaký cyklický, který bude opakovaně hlídat shodu. V obou případech tam bude nějaká prodleva, než se u 11 nastaví sloupec dle 10.

Kcko:
Některé databáze pustí update triggery i když jsou nové hodnoty stejné, jaké předešlé. Některé databáze ne. Pro jistotu bych to tam dal právě z důvodu, že se upravuje ta samá tabulka, nad kterou je trigger puštěný. Ale ani to nepomohlo.
Milan1236000
Profil
Kajman:
Už je mi to jasné, tímto se to zacyklí. Dal jsem dohromady jiný způsob, který funguje. Bohužel ale funguje jen napůl - pokud se upraví id 11, tak se správně zkopírují hodnoty z id 10, jindy to nefunguje. Už mi nějak došly nápady (aspoň pro dnešní noc). :)

CREATE DEFINER=`root`@`localhost` TRIGGER `mantis_custom_field_table_after_update` BEFORE UPDATE ON `mantis_custom_field_table` FOR EACH ROW BEGIN

    IF NEW.id = 11 THEN
        SET NEW.possible_values = (SELECT possible_values FROM mantis_custom_field_table WHERE id = 10);
    END IF;

END

Eventem se mi to zdá nešikovné, protože potřebuju 100% konzistentní data okamžitě při jakékoli změně. :)
Milan1236000
Profil
Zkusil jsem ještě v triggeru id 11 mazat a znovu vytvářet s hodnotami podle id 10, ale i to házelo tu samou chybu. Fakt nechápu z jakého důvodu...

Rozhodl jsem se, že to nebudu hrotit a dám tam ten event. Nastavil jsem si to tedy na zkoušku, ale zatím jsem žádnou změnu u id 11 nezpozoroval. Žádnou chybu to nehází, ale nic se neaktualizuje. Píšu to opět špatně?

CREATE DEFINER=`root`@`localhost` EVENT `keepId11UpToDate`
    ON SCHEDULE
        EVERY 10 SECOND STARTS '2019-10-27 18:35:00'
    ON COMPLETION PRESERVE
    ENABLE
    COMMENT 'test'
    DO BEGIN

    UPDATE mantis_custom_field_table
    SET possible_values = (SELECT possible_values FROM mantis_custom_field_table WHERE id = 10)
    WHERE id = 11;

END

Díky.

edit:
Nakonec jsem tu úpravu dal do kódu aplikace, když s tím jsou takové problémy. :)
Kajman
Profil
Milan1236000:
Fakt nechápu z jakého důvodu...
Viz manuál
A stored function or trigger cannot modify a table that is already being used (for reading or writing) by the statement that invoked the function or trigger.

Píšu to opět špatně?
A v mysql ten update také není možné takto zapsat. Zkuste si ho poustit samostatně, mělo by to vypsat chybu. Updaty nad čtenou tabulkou je možno v mysql psát díky joinu. Něco jako
UPDATE mantis_custom_field_table cil
       JOIN mantis_custom_field_table vzor
         ON vzor.id = 10
SET    cil.possible_values = vzor.possible_values
WHERE  cil.id = 11
  

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0