Favicon Svetmobilne.cz  Svět mobilně Favicon Svetaudia.cz  Svět audia Favicon TVFreak.cz  TV Freak   Fórum Favicon Digimanie.cz  Digimanie   Fórum   Galerie
Zobrazené výsledky: 1 až 11 z 11

Téma: [MySQL] Zase trigger.. :(

  1. #1
    Občasný diskutér
    Registrace
    May 2006
    Příspěvků
    141

    takze, sice pri pisani tohto topicu som dany problem uz vyriesil, ale uplne inou cestou. kazdopadne by ma zaujimalo, ci je mozne tento problem riesit aj povodne myslenym sposobom.

    Tu je moj trigger
    Kód:
    delimier |
    CREATE TRIGGER `it_zberdat`.`RevEntry` BEFORE UPDATE ON `it_zberdat`.`prehlad`
     FOR EACH ROW BEGIN
    IF (new.aktivna="n") THEN
      INSERT INTO poznamka values(0,old.iid,old.uid,old.polozka,"Polozka bola odobrana",now(),"revoke");
    ELSE
      INSERT INTO poznamka values(0,old.iid,old.uid,old.polozka,"Polozka bola reaktivovana",NOW(),"assign");
    END IF;
    END
    |
    delimiter ;
    Takze, trigger robi to, ze po zmene udajov v tabulke prehlad zapise do tabulky poznamky vykonanu zmenu.. konkretne zmenu hodnoty stlpca aktivna.

    Problem bol v sposobe vkladania zaznamov, ktory pri viacnasobnom odobrani a prideleni polozky viacerym osobam vytvaral duplicitne riadky v tabulke prehlad a teda pri zmene udajov bol vysledny pocet ovplyvnenych riadkov napriklad 3 a teda 3x spusteny trigger a 3 nove riadky v tabulke poznamky. A to som prave potreboval eliminovat na jedna zmena = jeden riadok..

    Tu je syntax tvorby triggera z Mysql doc.
    CREATE
    [DEFINER = { user | CURRENT_USER }]
    TRIGGER trigger_name trigger_time trigger_event
    ON tbl_name FOR EACH ROW trigger_stmt
    Hlavna otazka teda znie : Da sa nejakym sposobom nahradit FOR EACH ROW inou syntaxou, tak aby pri viacnasobnom spusteni bol trigger vykonany prave 1x a nie 3x ? Nikde som ziadne ine moznosti nenasiel.. uplne laicky..ak by sa to dalo nahradit FOR LAST ROW

    No a problem som nakoniec vyriesil tak, ze som odstranil duplicitne riadky a zmenil syntax INSERTu na syntax INSERT INTO .. ON DUPLICATE KEY UPDATE... http://dev.mysql.com/doc/refman/5.0/...duplicate.html
    Odpovídat lze po přihlášení

  2. #2
    Obyvatel SHW
    Registrace
    Jul 2006
    Příspěvků
    377

    Citace Původně odesláno od kikloop Zobrazit příspěvek
    Da sa nejakym sposobom nahradit FOR EACH ROW inou syntaxou, tak aby pri viacnasobnom spusteni bol trigger vykonany prave 1x a nie 3x ? Nikde som ziadne ine moznosti nenasiel.. uplne laicky..ak by sa to dalo nahradit FOR LAST ROW
    Pokud je v manuálu syntaxe s FOR EACH ROW napsána jako nevariantní, tak zjevně není variantní. Klíčové slovo LAST ROW nedává příliš nesmysl, protože nemůžete zaručit, v jakém pořadí budou řádky aktualizovány – vhodnější by tedy bylo něco jako ANY ROW. Jestliže správně chápu význam sloupce uid, tak se to tabulky poznamka zapisují různé řádky lišící se alespoň v uid. Jaké uid by se tedy podle vás mělo to tabulky zapsat při současném ovlivnění více řádků?

    BTW Zapisovat do tabulky poznámka textový řetězec je dosti neefektivní, když tu samou informaci lze vyčíst i z posledního sloupce, který je pravděpodobně typu ENUM.

    Citace Původně odesláno od kikloop Zobrazit příspěvek
    No a problem som nakoniec vyriesil tak, ze som odstranil duplicitne riadky a zmenil syntax INSERTu na syntax INSERT INTO .. ON DUPLICATE KEY UPDATE...
    Jelikož neznám detailní strukturu databáze, tak nemohu hodnotit, jak dobře jste problém vyřešil, ale něco mně říká, že to nebylo ve stylu best-practice.
    Odpovídat lze po přihlášení



  3. #3
    Občasný diskutér
    Registrace
    May 2006
    Příspěvků
    141

    Kód:
    Tabulka POZNAMKA
      `id` int(11) NOT NULL auto_increment,
      `iid` mediumint(9) default NULL 
      `uid` smallint(6) default NULL 
      `polozka` enum('4gcard','simcard','notebook','telefon','licence','desktop') NULL,
      `poznamka` text NOT NULL,
      `pridane` datetime NOT NULL,
      `typ` enum('add','assign','revoke','notice','warn','eol') default NULL,
      PRIMARY KEY  (`id`),
      KEY `ix_iiditem` (`iid`,`polozka`),
      KEY `ix_uid` (`uid`)
      KEY 'ix_typ' ('typ')
    
    tabulka prehlad
      `id` int(10) unsigned NOT NULL auto_increment,
      `uid` smallint(6) unsigned NOT NULL,
      `iid` mediumint(9) unsigned NOT NULL,
      `polozka` enum('4gcard','simcard','notebook','telefon','licence','desktop') NOT NULL,
      `pridane` datetime default NULL,
      `pridal` tinyint(4) unsigned NOT NULL,
      `aktivna` enum('a','n') NOT NULL,
      PRIMARY KEY  (`id`),
      UNIQUE KEY `ux_iiditem` (`iid`,`uid`,`polozka`),
      KEY `ix_uid` (`uid`),
      KEY `ix_iid` (`iid`)
    - Problem s duplicitnymi hodnotami bol v tabulke prehlady, kedy pri znovu prideleni prostriedku sa zaznam neaktualizoval ale zapisal novy a teda existovalo viac zaznamov ktore vyhovovali podmienke triggeru new.aktivna=n. Problem som odstranil pridani unikatneho indexu na stlpce IID, UID, POLOZKa teda jeden uzivatel moze vlastnit len raz IID z danej polozky, ale moze vlastnit viac IID z danej polozky a viac rovnakych poloziek s inym IID. snad je to jasne Takze dalsi insert s rovnakymi hodnotami skonci chybou a preto ta syntax INSERT ON DUPLICATE KEY UPDATE..



    - Poznamky je mozne pridavat uzivatelom, teda UID je vyplnene, POLOZKA a IID je v tom pripade NULL.
    - Poznamky je mozne pridavat prostriedkom, teda IID a polozka su vyplenene, UID neni vyplnene..
    - Poznamky je mozne pridavat kombinacii uzivatela a prostriedku - vsetky udaje su vyplnene.

    Jestliže správně chápu význam sloupce uid, tak se to tabulky poznamka zapisují různé řádky lišící se alespoň v uid. Jaké uid by se tedy podle vás mělo to tabulky zapsat při současném ovlivnění více řádků?
    nejde o to, ale UID by sa malo zapisat, ale kolko riadkov sa pri spusteni triggeru zapise do tabulky poznamka. Doteraz to fungovalo tak, ze stary zaznam sa nastavil na aktivna =N a pre noveho vlastnika sa vytvoril novy zaznam aktivna=A, ak som pridelil danu polozku znovu prvemu uzivatelovi tak sa nezmenila stara ale vytvorila nova aktivna=A - pri odobrani aktivna=N - a tu bol problem, pretoze uz existovali 2 zaznamy, ktore vyhovovali podmienke kde UID je dany uzivatel, IID a polozka - dana polozka a aktivna=N - teda 2x trigger a 2 zaznamy v poznamke

    BTW Zapisovat do tabulky poznámka textový řetězec je dosti neefektivní, když tu samou informaci lze vyčíst i z posledního sloupce, který je pravděpodobně typu ENUM.
    Uznavam, je to neefektivne, stlpec "typ" je indexovany i ked k efektivnosti prispieva len malo.. Stlpec poznamka je text - pretoze do tohto pola su okrem automatickych sprav zaznamenane aj poznamky konkretnych spravcov.
    Naposledy upraveno uživatelem kikloop: 09-06-2008 v 13:33
    Odpovídat lze po přihlášení

  4. #4
    Starousedlík SHW
    Registrace
    May 2006
    Příspěvků
    4,042

    Nechtěl bys ještě jaksi doplnit, k čemu ty tabulky sloužej? Jaký data se tam ukládaj?

    Maj ty data mezi sebou nějakej vztah? Jestli jo, tak kde je referenční integrita?

    Ty tabulky maj vetšinu sloupců stejnejch. To mě vede k myšlence, že ta struktura nebude asi optimální...
    Odpovídat lze po přihlášení

  5. #5
    Občasný diskutér
    Registrace
    May 2006
    Příspěvků
    141

    OK tak to este nejak opisem + nejake tie vzorove data..
    Sluzi to k evidencii prostriedkov vo firme pouzivanych zamestnancami. Teda pridelene sluzobne telefony, simkarty, notebooky. Je dolezite poznat historiu daneho prostriedku a uzivatela. Teda kto v minulosti vlastnil dany prostriedok a co v minulosti vlastnil dany uzivatel. - na to sluzi prave tabulka poznamky, kde sa vacsinou teda za pouzitia triggerov zapisuju automaticke spravy (Zaciatok evidencie polozky, polozka pridelena, odobrana, znovu pridelena, + poznamky administratorov - odoslane na reklamaciu, vratene, ukradnute, koniec zivnostnosti/ vyradenie z evidencie)

    Existuju tabulky '4gcard','simcard','notebook','telefon','licence', 'desktop' - kde su ulozene udaje o jednotlivych prostriedkoch, datum nakupu, cislo faktury, zaruka do.. . Je snad jasne, ze struktura neni totozna takze neni mozne pouzit jednu tabulku.

    vysvetlim teda tu tabulku PREHLAD:
    ID - primarny kluc - auto increment - vsetko jasne
    UID - ID uzivatela - tabulka_uzivatelov.id = prehlad.uid
    IID - ID polozky - vybrana_polozka.id = prehlad.iid
    polozka - rozhoduje z ktorej tabulky sa bude vyberat IID, teda ak tu bude simcard, tak simcard.ID = prehlad.IID AND prehlad.polozka='simcard'
    .
    .
    pridal - ID administratora
    aktivna - Priznak, ci je dany zaznam aktivny.

    Vzorove data...
    tabulka SIMCARD
    Kód:
    ID SIMID TELCISLO    PIN  PIN2 PUK PUK2 BPIN TARIF 
    0  12346 775888888  124 ...
    1  23456 775999999  589 ...
    tabulka PREHLAD
    Kód:
    ID UID IID   POLOZKA    PRIDANE   PRIDAL AKTIVNA
    1    2   1   simcard   2008-08-08   1      A
    2    2   5   simcard   2008-08-09   1      A
    3    2   10  desktop   2008-08-09   1      A
    4    2   11  telefon   2008-08-10   1      A
    5    3   1   simcard   2008-08-01   1      N
    - Uzivatel 2 ma teda AKTIVNE pridelenu 1 SIM kartu s 5, a ma prideleny este jeden desktop s ID 10 a telefon s ID 11 + uzivatel UID=2 prevzal DRUHU SIM kartu od uzivatela UID=3 si IID=1.

    V ktorej tabulke mam hladat zistim podla POLOZKA a co mam hladat je IID.

    takze tabulka poznamky: - Tu pri triedeni podla casu/ datumu je mozne zistit historiu pohybov
    Kód:
    ID  IID  UID   POLOZKA   PRIDANE     TYP       POZNAMKA
    0    1   NULL  simcard   2008-08-01  add      Zaciatok evidencie
    1    3    1    simcard   2008-08-02  assign   Polozka pridelena
    2    3    1    simcard   2008-08-03  revoke   Polozka odobrana
    3    2    2    simcard   2008-08-04  assign   Polozka pridelena
    - Tu je priklad historie jednej polozky -
    1. Trigger po vytvoreni zaznamu v tabulke SIMCARD automaticky prida zaznam do tabulky poznamka s informaciou o zaciatku evidencie. Este by som chcel vysvetlit UID = NULL - hovori o tom, ze sa zaznam tyka iba SIM karty. taktiez existuju zaznamy s null hodnotami pre IID a polozka ale UID je platna hodnota- to znamena ze sa jedna o poznamku k uzivatelovi.
    2. Trigger po vytvoreni zaznamu v tabulke PREHLAD automaticky prida poznamku o prideleni prostriedku uzivatelovi
    3. Trigger pri UPDATE tabulky PREHLAD na AKTIVNA=N automaticky prida poznamku o odobrani prostriedku
    4. a znova pridelena polozka inemu uzivatelovi..

    Chcel by som este pripomenut ze sa snazim riesit to, ako pri vyskyte viacerych znaznamov v podmienke TRIGGERU, spustit telo iba 1x
    Naposledy upraveno uživatelem kikloop: 09-06-2008 v 14:53
    Odpovídat lze po přihlášení

  6. #6
    Starousedlík SHW
    Registrace
    May 2006
    Příspěvků
    4,042

    Problém je v tom, že ty tabulky dublujou údaje. Takový tabulky se vždycky bbě aktualizujou a hrozí rozsynchrnonizování. Doporučil bych Ti todle:
    1) Zruš tabulku PREHLED. Nenese žádnou informaci. To, že měl "uživatel 3" kdysi přidělenou simku a teď ji má "uživatel 2" jde odvodit z tabulky POZNAMKA. Pokud potřebuješ, tak si pro tabulku PREHLED napiš VIEW nebo STORED PROC. Odpadnou ti veškerý problémy s trigerama.
    (aktivní jsou ty přidělení, pro který neexistuje následující odebrání - jednoduchej JOIN přes sebe sama).

    Další nápady, jak to zlepšit:
    2) Přejměnuj tabulku POZNAMKA - to jméno je hodně nedeskriptivni. Co třeba ZMENYSTAVU?
    3) TYP udělej jako INTEGER FOREIGN KEY do nové tabulky CISELNIK, nebo třeba POZNAMKA, kde budou uvedený textový významy toho typu.
    4) Udělej tabulku EVIDENCE, kde budou všechny evidované prostředky nezávisle na typu. ID těchto prostředků bude odkazovat do tabulky ZMENYSTAVU a zaroven do jednotlivejch tabulek obsahujicich specialni atributy pro danej typ veci. Tim získáš relativně funkční referenční integritu (např. pro smazání položky pak při dobře definovanejch FK stačí vymazat položku z tabulky EVIDENCE.


    Možná se Ti to zdá hnidopišství, ale jestli to neni vyloženě jednorázová věc a počítáš s tim, že se to bude rozrůstat, upravovat, tak se Ti tydle úpravy mnohokrát vyplatěj.
    Odpovídat lze po přihlášení

  7. #7
    Starousedlík SHW
    Registrace
    May 2006
    Příspěvků
    4,042

    Ještě další myšlenky:
    místo událostí přiděleno, odebráno bych do tabulky EVIDENCE dal sloupeček OD a DO (zarazeni a vyrazeni z evidence) a do tabulky ZMENASTAVU dej misto PRIDANE taky sloupecky OD a DO (odkdy a dokdy byl pridelen prostredek danemu cloveku). Pak vlastne i sloupecek typ bude zbytecny. DO IS NULL bude znacit dodnes.

    jednoduse zjistis vsechny pridelene prostredky v dany cas:
    SELECT * FROM ZMENASTAVU WHERE OD < DATUM AND (DO > DATUM OR DO IS NULL)
    vsechny pridelene prostredky:
    SELECT * FROM ZMENASTAVU WHERE DO IS NULL
    vsechny nepridelene prostredky:
    SELECT * from EVIDENCE WHERE ID NOT IN (SELECT * FROM ZMENASTAVU WHERE DO IS NULL)
    atd...
    Odpovídat lze po přihlášení



  8. #8
    Občasný diskutér
    Registrace
    May 2006
    Příspěvků
    141

    Diky za kazdopadne dobre pripomienky

    1. Zrusenie tab. PREHLAD - to by som momentalne mohol nejakym sposobom aplikovat. Uznavam, ze tieto informacie su vlastne duplicitne, ale to by som musel pravdepodobne aplikovat sucasne s pridanim stlpcov OD - DO.

    2. tabulka POZNAMKA nesie naozaj len informacie o poznamkach, historii pohybov.. Nemyslim si ze ten nazov neni vystizny v danom kontexte

    3. Ak si to myslel tak, ze by som zrusil stlpec POZNAMKA v tab. POZNAMKA a zo stlpca TYP spravil INT a FK na inu tabulku s indexom poznamok, tak o tom som vazne uvazoval. Je mi jasne ze 100x zapisovat text "pridana polozka" neni efektivne.. Je to vec zmeny SQL dotazu a nenarocnej upravy struktury. problem je v tom, ze sa tam zapisuju aj poznamky, ktore sa neopakuju :-/

    4. ano, to by taktiez slo, ale myslim si, ze by to bolo az prilis sofistikovane riesenie, ktore by mi uz neprinieslo nejake relativne zvysenie vykonnosti kodu.

    k stlpcom OD DO - ich vyuzitie vidim jedine pri zruseni tabulky prehlad. Pretoze momentalne tabulka prehlad nesie jednoznacnu informaciu o prideleni prostriedku. Je to vlastne tabulka aktualnych stavov. Tabulka poznamky je vlastne len historia.
    Odpovídat lze po přihlášení

  9. #9
    Starousedlík SHW
    Registrace
    May 2006
    Příspěvků
    4,042

    4) neni zkvuli vykonu, ale kvuli vytvoreni referencni integrity - spousta prace s databazi se pak zjednodussi, protoze neni treba propagovat zmeny do dalsich tabulek.
    2) Pokud Ti nazev vyhovuje, OK :-D
    1) Nemusel, akorat struktura od-do zjednodušuje dotazy. I tak je tabulka prehled duplicitna: např.

    SELECT * FROM poznamky p1 LEFT JOIN poznamky p2 ON (p1.iid = p2.iid AND p1.pridane < p2.pridane)
    WHERE p2.id IS NULL
    (tzn. zaznamy z poznamek,kde neexistuje "novejsi" zaznam se stejnym iid)
    Ti vrati aktualni stav vsech prostredku. Podminkou na typ pak ziskas prirazene, neprirazene, nikdy neprirazene (pouze zarazene do evidence).
    Odpovídat lze po přihlášení

  10. #10
    Občasný diskutér
    Registrace
    May 2006
    Příspěvků
    141

    Tak nakoniec som par z tvojich rad uspesne aplikoval. Ci to bol spravny krok uvidim az casom, ked sa naplni databaza
    Kadopadne davam + za diskusiu na urovni
    Odpovídat lze po přihlášení

  11. #11
    Starousedlík SHW
    Registrace
    May 2006
    Příspěvků
    4,042

    Tak ať Ti slouží :-)
    Odpovídat lze po přihlášení

Podobná témata

  1. Gamepady: thrustmaster dual trigger rumbleforce
    Od bojka.r v sekci Periferie
    Reakcí: 4
    Poslední příspěvek: 22-12-2012, 18:36
  2. mysql set @variable
    Od petr.svec v sekci Programování
    Reakcí: 5
    Poslední příspěvek: 04-12-2009, 11:07
  3. Zase RAM ???
    Od daniel.mel v sekci Problémy s PC (HW/SW) a řešení
    Reakcí: 3
    Poslední příspěvek: 13-11-2009, 12:45
  4. MySQL a JOIN
    Od petr.svec v sekci Programování
    Reakcí: 3
    Poslední příspěvek: 10-02-2009, 15:52
  5. PC zase na dlouho
    Od tai v sekci PC - archiv
    Reakcí: 26
    Poslední příspěvek: 03-10-2008, 19:11