webrebel html css javascript laravel oop php mysql wordpress kurz

Ignorantské INSERTy

napísal , 29 Feb 2012 [ SQL ]

INSERT? Fuck that!
3 malé tipy, s ktorými si ušetríte pár riadkov kódu a budete takí ťažkí frajeri, že sa už nezbavíte ženských (chlapov, v prípade, že to číta nejaká programátorka (do they even exist?:)).

Predstavte si, že vaša životná púť dospeje do situácie, kedy chcete niečo zapísať do MySQL tabuľky, ale nechcete sa zapodievať kontrolami, či daný záznam už existuje. Čo s tým..

1) Chcem vložiť riadok do tabuľky. Ak už existuje, nič sa nebude zapisovať.

INSERT IGNORE INTO vajcia (id, nazov, kaliber)
VALUES(NULL, 'Vajčisko', 'masívny')

Úplne normálny INSERT s tým rozdielom, že keď ak by sa bili primárne kľúče alebo unikátne kľúče (čiže záznam už existuje), query sa odignoruje. Vloženie sa odignoruje alebo riadok sa uloží neočakávaným spôsobom aj ak bude obsahovať iné chyby, na čo si treba dávať pozor.

2) Chcem vložiť riadok do tabuľky. Ak už existuje, chcem update-núť jeho údaje

INSERT INTO checkins (id, id_user, id_venue, count, last_checkin)
VALUES (NULL, 230, 6434, 1, NOW())
ON DUPLICATE KEY UPDATE count = count + 1, last_checkin = NOW()

Príklad ukazuje niečo ako "check in" na 4square. Pri prvom raze sa vloží záznam, že som na nejakom mieste vôbec bol, pri ostatných razoch sa zvýši počítadlo návštev a čas posledného check-in-u sa aktualizuje. Je to v podstate INSERT a UPDATE spojený do jednej query.

3) To isté čo druhý prípad, s malým rozdielom
Ak by som vkladal nejaký dlhý text, musel by som ho v predchádzajúcom spôsobe zopakovať 2x (raz v INSERTE a raz v UPDATE časti). Pri extrémne dlhých textoch by nám to teoreticky mohlo vadiť. Situáciu zachráni REPLACE.

REPLACE INTO poznamka (id, id_projekt, datum, text)
VALUES (NULL, 42, '2012-12-12', 'Všetko som vybavil, môžme spustiť tú apokalypsu... [1MB dalsich kecov]')

Je tu však jedna zradafeature. Ak záznam existuje, vymaže sa a vloží sa nový, čiže sa zmení aj primárny kľúč (ak je AUTO_INCREMENTovací).

Bonus
Prvý prípad s INSERT IGNORE sa dá riešiť trocha lepším, ale divnejším spôsobom, použitím ON DUPLICATE KEY UPDATE, takto:

INSERT INTO vajcia (id, nazov, kaliber)
VALUES(NULL, 'Vajčisko', 'masívny')
ON DUPLICATE KEY UPDATE id = id

Výhoda je, že sa neignorujú žiadne chyby, iba duplicitné kľúče. Nevýhodou je trocha mätúca syntax.

Teraz si už len treba dávať pozor na tie ženské.

napísal , 29 Feb 2012

10 komentárov

komentuj
  1. Tibor Soviš [ Streda 29.2.2012, 13:36 ]

    Sranda, to prvé som nepoznal...
    Technická: načo vo všetkých príkladoch vymenúvaš stĺpec id, keď do neho "vkladáš" NULL? Bez zneho je to kratšie a krajšie.

  2. 81403 (blade) [ Streda 29.2.2012, 14:17 ]

    Normálne vynechávam všetko, čo sa dá vynechať :) Sem som dal dlhší zápis preto, aby bolo vidieť štruktúru, že máme aj stĺpec s IDčkom.

  3. Tibor Soviš [ Streda 29.2.2012, 14:19 ]

    To dáva zmysel...

  4. m-> 29 [ Streda 29.2.2012, 18:06 ]

    Prvé zmienené INSERT IGNORE by som moc nepoužíval, pretože neignoruje len chyby duplicitného kľúča ale všetky chyby.

    Potom by sa niekto mohol čudovať čo to má v DB za nezmysly, pretože nesprávne dáta sa MySQL bude snažiť konvertovať na správne dáta, ktoré však nemusia byť úplne správne ;-)

  5. hogy [ Streda 29.2.2012, 20:24 ]

    Ja len chcem povedat, ze existuju aj programatorky - mam kolegynu programatorku :)

  6. 81403 (blade) [ Štvrtok 1.3.2012, 10:25 ]

    m29: dík, to je dobrá poznámka. Neignoruje síce úplne všetky chyby (napr. ak má query zlú syntax, dostaneš error), ale zlé data sa snaží skonvertovať a môže z toho vzniknúť bordel. Update-ol som to aj v článku.

    hogy: ale prosím ťa, zase si vymýšľaš ;)

  7. Rous [ Piatok 30.3.2012, 15:47 ]

    Predne diky za palce nahoru, Pane 5 hcubyrh chyb. . Verte, ze nemam zapotrebi prilevat zadny olej do ohne, ale soucasna mizerie piskani (ktera ceskemu florbalu extremne skodi i na mezinarodni scene) me proste stve a byl jsem pripraveny, ze kdyby neprisel podobny clanek, tak ho napisu sam. takze: 1.) opravdu si myslim, ze do poloviny zapasu (tedy do stavu 0:5) zadne velke chyby nebyly. Ostava hrala bez chyb v rozehravce, Tatran se trapil a kdyz uz se mu neco povedlo, tak byl na konci perfektne chytajici golman. (coz Tatran take postradal), takze stav 0:5 byl odpovidajici bez jakehokoliv vlivu rozhodcich, kteri ani moc nemuseli zasahovat. 2.) zde mate ty hrube chyby, co podle me ovlivnily zapas, ve kterem se Tatranu darilo vicemene jen v precisleni: a) za stavu 1:5 Garcar neustal pristrceni u mantinelu-uder do obliceje 5 minut (rozhodci to videl, ale rekl jen pozor na to, nebo budu vylucovat ) pokud by v tu chvili skoncila presilovka, nejspise by nedoslo k zavaru, po kterem prisel najezd sice prisny, ale opravneny najezd b) za stavu 2:7 zavar pred branou FBC po tycce. Garcar opet uderil protihrace do obliceje opet bez trestu. c) behem obratu ve 3. tretine po akci FBC a nasledne ztrate balonu sel Tatran do protiutoku, jeden z hracu FBC takticky pribrzdil protiutok beznym faulem u mantinelu, ale nepomohlo to. Presto zaznela pistalka. Nasledoval dvouvterinovy zaber na rozhodciho, ktery si az po odpiskani evidentne uvedomil, ze pripravil Tatran o vyhodu, protoze faul akci nezastavil po chvilce premysleni, jak z toho ven, se zvedla prava ruka a z bezneho faulu byl znicehonic faul na 2 minuty. d) v zaverecnych minutach prisel obloucek do brankoviste Tatranu, kam se narychlo vracel golman, Klimes (v domeni, ze je prazdna brana) celou akci zlikvidoval klasickym kroscekem jasny najezd, ze ktereho nakonec nebyl ani trestny uder. e) zaverecny gol padl po faulu na 2 minuty pro Garacara drzeni hole (vybavuji si, ze za tento faul chodil pravidelne ven naprosto bezne Petr Novotny v Boleslavi) krome techto 5 hcubyrh chyb by se naslo i par dalsich podivnosti, ale u tech to televize nedokazala natolik prokazat (napr. nebylo videt, jestli za stavu 0:5 provedl neco Machala Garcarovi, ze pak sli za Garcaruv faul sedet oba ) abych si za tim mohl 100% stat jako si stojim za temito 5 pochybenimi. Uff. Zdar Petis

  8. 81403 (blade) [ Piatok 30.3.2012, 15:56 ]

    Áno, článok bol v skutočnosti o florbale (či o čom to) a tie inserty boli len taký krycí manéver na zmätenie nepriateľa. Teší ma, že si to niekto všimol.

  9. yablko [ Piatok 30.3.2012, 19:19 ]

    Oh, nebojte sa priliať oleja koľko len chcete a keď skončíte, zastavte sa za rohom - dostanete od nás medailu za najlepší komentár v internete

  10. psycho [ Streda 5.12.2012, 22:56 ]

    Ach, kvoli tebe som teraz dlho googlil riesenie, lebo si ma ojeklamal.

    REPLACE INTO nema ziadnu zradu. Ak záznam existuje, NAHRADI SA, čiže sa NEZMENI primárny kľúč - pokial ho tam uvedies. Zmenia sa iba udaje s danym primarnym klucom. To je imho primarna funkcia toho REPLACE.

    Ty si tam dal null, preto sa ti vytvoril novy.