Autor | Zpráva | ||
---|---|---|---|
Michael241 Profil * |
#1 · Zasláno: 20. 6. 2023, 12:09:06
Dobrý den,
měl bych jednu prosbu o radu. Mám 3 tabulky, a v tabulce `produkt` potřebuji měnit aktuální stav při změně skladu. To již mám hotové, problém nastavá v situaci, kdy je produkt v SETU - to by problém nebyl, problém je, pokud je zařazen u více produktů (tedy může být v setu s 5 druhy produkty, např jedná se o produkt "Obal na knihu" a ten je v setu s 10 různýma knihama, a 3 dalšíma věcma za jinou cenu.) Stav skladu setu funguje tak, že je skladem nejmenší množství minimálně jednoho produktu. Tedy je skladem 5 knih, 12 obalů, 20 pravítek, tak sklad setu bude 5. - Pokud se prodá zvlášť 1 obal, sklad bude stále 5 - Pokud se ale prodá zvlášť 1 kniha, sklad musí být 4 Stručně mám tabulky: produkt (id, aktualni_stav) produkt_sklad (id, produkt_id, sklad_id, mnozstvi) produkt_set (id, proukt_id, produkt_set_id) Abych to doplnil - funguje vše fajn, jen nefunguje to, že id_set_karty může být pole (když doplním LIMIT 1 tak funguje, což nemohu protože potřebuji aktualizovat všechny karty) (může být kombinovaný u více produktů, jak jsem psal) a já potřebuji měnit stav dle produktů v daných setech. a SQL DROP TRIGGER aktualizace_skladu; DELIMITER $$ CREATE TRIGGER aktualizace_skladu AFTER UPDATE ON produkt_sklad FOR EACH ROW BEGIN DECLARE id_set_karty INT DEFAULT 0; SELECT produkt_id INTO id_set_karty FROM produkt_sklad WHERE produkt_set_id = NEW.produkt_id; UPDATE produkt p SET p.aktualni_stav = COALESCE( ( SELECT SUM(mnozstvi) FROM produkt_sklad WHERE produkt_id = NEW.produkt_id ), 0 ) WHERE p.id = NEW.produkt_id; END IF; /* aktualizace SET */ IF is_in_set>0 THEN UPDATE produkt p SET p.aktualni_stav = COALESCE( ( SELECT MIN(aktualni_stav) FROM produkt WHERE id IN( SELECT produkt_set_id FROM produkt_set WHERE produkt_id = id_set_karty ) ), 0) WHERE p.id = id_set_karty; END IF; END; |
||
ttttttttttt Profil * |
#2 · Zasláno: 21. 6. 2023, 01:37:07
Je to kompletní?
is_in_set není definované.
Celý ten trigger mi přijde zbytečně složitý. Když se produktu sníží množství, tak stačí všem produktům ze setu nastavit aktuální stav na least(aktualni_stav, NEW.mnozstvi) , ne? Dá se to celé nahrazit za něco jako
UPDATE produkt p SET p.aktualni_stav = least(aktualni_stav, NEW.mnozstvi) WHERE p.id IN (SELECT proukt_id FROM produkt_set WHERE produkt_set_id = NEW.produkt_id) Pokud ne, proč? |
||
Michael241 Profil * |
#3 · Zasláno: 21. 6. 2023, 10:55:04
pardon, is_in_set je (má být) id_set_karty, špatně jsem to napsal.
No nevypadá to vlastně špatně, jen co vidím za problém je, že toto by sice fungovalo a aktualizovalo produkt na případně menší sklad než má, ale nemohu tam použít least(aktualni_stav, NEW.mnozstvi) protože NEW.mnozstvi neni celkový stav, je to pouze množství na jednom skladu, které se zrovna upravilo. ještě je možnost sklad 2, 3...proto tam mám COALESCE ( SELECT SUM(amount)... protože může být na více skladech.. Takže mě vlastně napadá v least - NEW.mnozstvi nahradit za ( SELECT aktualni_stav FROM produkt WHERE id = NEW.produkt.id ) což by mělo vrátit celkový, aktuálně upravený sklad ? |
||
Michael241 Profil * |
PS 2 - To tvoje vlastně nereflektuje to, když množství naskladním.
Tj. aktualni_stav setu 6 ks => sklad produktů je v setu je nyní ale naskladněn na - 8 ks (první díl setu) a - 11 ks druhý díl setu ale neprovádí to aktualizaci, nechává to stále 6 ks, protože to bere (6, 11) ale SET má mít teď sklad 8ks (nejmenší sklad jednoho dílu) Tak vyřešil jsem to zatím takto, ale ještě úplně nevím jestli to bude OK. UPDATE produkt p SET p. aktualni_stav = ( SELECT MIN(aktualni_stav) FROM produkt WHERE id IN( SELECT produkt_set_id FROM produkt_set WHERE produkt_id = p.id ) ) WHERE p.id IN ( SELECT produkt_id FROM produkt_set WHERE produkt_set_id = NEW.product_id ); |
||
ttttttttttt Profil * |
#5 · Zasláno: 23. 6. 2023, 01:07:05
Dobrá připomínka, nedošlo mi, že tam je víc skladů. Při zvyšování počtu položek to nefunguje, to je taky pravda.
Nemám moc rád, když je v triggerech netriviální logika, tou je pro mě SELECT, který čte jiné řádky, tak bych se tomu řešení osobně spíš vyhnul. Budeš potřebovat ještě AFTER INSERT, AFTER DELETE triggery. Pokud máš kaskádové mazání přes cizí klíče, tak je dobré si rozmyslet, co se stane při smazání produktu. Nejspíš se jen ta aktualizace zavolá vícekrát na smazaném záznamu, takže kromě pár dotazů navíc nic. Pokud těch produktů není moc (tisíce jsou imho pořád ok), taky bych to řešil přes VIEW a aktuální množství dopočítával. Myslím, že to se správými indexy pořád bude dostatečně rychlé (milisekundy) a robustnější. Případně pak materializovaný pohled, pokud ho databáze podporuje. |
||
Časová prodleva: 1 rok
|
0