Autor | Zpráva | ||
---|---|---|---|
Milan1236000 Profil |
#1 · Zasláno: 25. 10. 2019, 22:00:09
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 |
#2 · Zasláno: 26. 10. 2019, 08:59:43
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 |
#3 · Zasláno: 26. 10. 2019, 09:46:57
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 |
#5 · Zasláno: 26. 10. 2019, 10:24:28
Něco jako Vránův exclusivní or? Využití triggerů pro aktualizaci souhrnné informace
Neznal jsem, díky. |
||
Kajman Profil |
#6 · Zasláno: 26. 10. 2019, 10:42:45
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 |
#7 · Zasláno: 26. 10. 2019, 10:55:50
Jasně, díky za vysvětlení.
|
||
Milan1236000 Profil |
#8 · Zasláno: 26. 10. 2019, 16:00:11
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 |
||
Kcko Profil |
#9 · Zasláno: 26. 10. 2019, 17:09:25
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 |
#10 · Zasláno: 26. 10. 2019, 17:43:37
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 |
#13 · Zasláno: 29. 10. 2019, 09:31:05
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 |
||
Časová prodleva: 3 roky
|
0