spájame
slovenskú
IT komunitu
pridaj sa
Registrácia · Login
Ucitel

Ucitel


Overený používateľ, členom od 28.12.2012

(zatiaľ žiadne)
Prepared statements, wtf?

Prepared statements, wtf?

Ucitel, 28.12.2012
Stale pouzivate v skriptoch mysql_ funkcie? Neviete co su to prepared statements? V tomto clanku sa naucime pristupovat k SQL databazam spravne a bezpecne. Viac »

Ucitel napísal 20 komentárov

1 0 Ucitel 2013-09-06 12:31:29
Aha, http://namebox.io, tiez to spravil za dva dni a stihol aj nakodit celu vlastnu appku a spravit pekny dizajn, potom o tom napisal blog http://drew.roon.io/building-namebox.

Tym ze nieco odflaknes by som sa nechvalil, pred tym ako to budes ukazovat dalsim ludom a nahanat pagerank tak by som na tom este zamakal.
2 0 Ucitel 2013-09-04 21:47:20
Aj to tak vyzera ako spravene za dva dni.
0 0 Ucitel 2013-05-16 15:28:40
Zaujimaju niekoho tieto promo clanky? Zbytocny spam v RSS. Keby sem obcas Frantisek nepisal tak to davno zmazem.
0 0 Ucitel 2013-04-09 17:32:22
No dost tragedia toto.

Najviac sa mi lubi Monikine jablko, ale nic ma vyslovene nezabilo, hladal by som este dalej.
0 0 Ucitel 2013-02-06 12:38:27
@viťo Ak pouzivas sleep rezim namiesto uplneho vypnutia tak to trva par sekund tak ci tak. Ja mam problem s tym, ze ked vypnes metro a pridas start tak z toho mas obycajny Windows 7 s hroznym ribbon explorer UI, za co potom platis tych 60 eur? Mne osobne ale staci ten dobry pocit z niecoho noveho. :)
2 0 Ucitel 2013-02-05 13:59:18
Jediny rozdiel medzi OEM a "full" verziou je afaik ten, ze s OEM nemas peknu krabicu, 32+64bit instalaciu a free support.

Kazdopadne platit aj "iba" 60 eur za upgrade, ktory ti neprinesie nic uzitocne a este ti znizuje produktivitu featurami ako metro a odstranenie startu mi pride totalne hlupe, obzvlast v porovnani s OSX kde som za upgrade (ktory sluzi aj ako plnohodnotna instalacia OS) zaplatil 16 eur.
1 0 Ucitel 2013-01-31 16:52:50
@Gabriel Potkány Hej, to je dost bezne WTF, ze neexistuje jednoduchy sposob ako copy-pastnut "hotove" query niekam inam na debugovanie.

Z toho co ponuka PDO vies zistit povodne query pouzite pre vytvorenie PDOStatement-u pomocou $stmt->queryString, rovnake query spolu so vsetkymi bindnutymi parametrami vies ziskat pomocou $stmt->debugDumpParams(), ktore ti ho vypise priamo na vystup (dost hlupa implementacia).

Ty vsak ale asi chces nejake "finalne query", ktore sa da priamo spustit, s "doplnenymi" parametrami. Pri pouziti skutocnych nativnych prepared statements vsak take query nikdy neexistuje, pretoze ako je vysvetlene v clanku, query a data sa posielaju aj samotnemu serveru osobitne.

Ani pri pouziti emulovanych prepared statements vsak PDO neposkytuje priamo ziadnu moznost ziskat finalne query. Mozes si ho poskladat sam pomocou str_replace/preg_replace a $pdo->quote() na escapovanie doplnovanych parametrov. Finalne query mozes ziskat aj z logu SQL servera, ak mas zapnute logovanie queries (neodporucam v produkcii).

Kedze som ti asi velmi nepomohol, tak na zaver ti ponuknem iny, lepsi, sposob ako debugovat queries v PDO a to pomocou metod $pdo->errorInfo() resp. $stmt->errorInfo(), ktore su PDO ekvivalentom funkcie mysql_error() a teda vratia kompletnu chybovu hlasku priamo od SQL serveru. Ak nastavis $pdo->setAttribute(PDO::ATTR_ERRORMODE, PDO::ERRMODE_WARNING), tak ti bude PDO hlasit chyby automaticky ako spravu na urovni E_WARNING, ak chces byt moderny, mozes pouzit hodnotu PDO::ERRMODE_EXCEPTION a bude ti namiesto chyb hadzat vynimky.

http://www.php.net/manual/en/pdostatement.debugdumpparams.php
http://www.php.net/manual/en/pdo.quote.php
http://www.php.net/manual/en/pdostatement.errorinfo.php
http://www.php.net/manual/en/pdo.error-handling.php
0 0 Ucitel 2013-01-31 16:11:07
@Lukáš Staňa Tnx za tip, nevedel som ze priamo v PHP je funkcia na prevod adresy do tohto formatu.

@František Čaník Clovek by nemal riesit veci, kde nema stopercentnu strukturu, potom velmi rychlo vznika bordel. Ja osobne robim navrh databazy ako jeden z prvych krokov pri vyvoji aplikacie, potom mas model ktory zachytava vacsinu objektov v aplikacii a vztahy medzi nimi, ktory mozes vyuzit pri vyvoji samotnej aplikacnej logiky.

Vyklikat rychlo nieco v Admineri, nakodit aplikaciu a nakoniec pomenit datove typy, nahadzat nejake cudzie kluce a volat to optimalizacia urcite nie je dobry pristup.
0 0 Ucitel 2013-01-29 17:39:00
@František Čaník Nie, DATETIME sa pouziva na casove udaje vseobecne, ak mas data vo forme unix timestampu mozes pouzit napr. FROM_UNIXTIME() funkciu v MySQL resp. ekvivalent pre ine DB alebo to naformatovat spravne na strane PHP - date('c').
Co sa tyka IP, ano 39 je najvacsia dlzka beznej IPv6 adresy.
Viem ze su to detaily, len nechcem aby si niekto z clanku odniesol, ze data v databaze ukladame do VARCHARov s nahodnou dlzkou.
0 0 Ucitel 2013-01-29 17:22:46
Z mojho pohladu je Windows 8 totalny fail. Ako spravny ucitel som si ho samozrejme nainstaloval hned po oficialnom uvedeni. Odvtedy som ho ukazal niekolkym "beznym pouzivatelom" (ktory maju s windowsami X rocne skusenosti) a kazdy to do 10 minut zmateny a frustrovany vzdal. Myslim, ze MS spravil nieco ale, ked ich hlavna cielova skupina nevie tento system ani pouzivat.
2 0 Ucitel 2013-01-29 17:06:28
V SQL sa na ukladanie casovych zaznamov pouziva typ DATETIME resp. DATE, pouzivanie VARCHARov s nahodnou dlzkou nie je ziaden extra dobry napad. Na IP adresu ti tiez staci VARCHAR(39).
1 1 Ucitel 2013-01-22 19:28:44
Zbytocne vyhajpovana vec, okrem toho ze sa uz objavili pochybnosti o tej suberbezpecnosti ktorou sa prezentuju ( http://arstechnica.com/business/2013/01/megabad-a-quick-look-at-the-state-of-megas-encryption/ ), tak na sluzbu za ktorou stoji clovek co prevadzkoval hosting postaveny na nelegalnom obsahu by som si aj tak nikdy ziadne citlive data nenahral.
1 0 Ucitel 2013-01-09 22:07:10
@Nanobot Dakujem za komentar, pri pisani som sa ani nepozastavil pri tom ci pouzit alebo nepouzit diakritiku, kedze vacsinou programujem alebo pisem po anglicky tak pouzivam anglicke rozlozenie klavesnice a som zvyknuty pisat/citat texty bez diakritiky. Kazdopadne beriem na vedomie a dalsi clanok bude pekne s diakritikou.
Co sa tyka anglickych vyrazov tak mne osobne tiez pripadaju prirodzenejsie, ale urcite by sa zase nasiel niekto kto by kritizoval pouzivanie anglickych vyrazov na slovenskom portale. Preto sa snazim pouzit aspon tie pouzivanejsie slovenske vyrazy.
0 0 Ucitel 2013-01-03 17:34:41
@Michal Macejko Porozmyslam nad tym ako by sa z toho dal vytvorit clanok z ktoreho by sa dalo aj nieco naucit, nie len copy'n'pastovat kod. Ale v principe by to vyzeralo podobne ako pise @Miroslav Petro, akurat vytvaranie nejakej pomocnej tabulky znie ako overkill.
0 0 Ucitel 2012-12-31 13:17:57
Rozhodol som sa, ze skusim napisat este jeden clanok, mate nejaku temu, ktora tu chyba a radi by ste videli o nej napisany clanok (webdev, PHP/JS/C, unixy, hocico)?
0 0 Ucitel 2012-12-29 15:58:52
@ritopich Zapnuta emulacia = escapovanie, teda realne to ani prepared statements nie su, nikdy sa nevola PREPARE a EXECUTE.
Vyhodne je to v tom, ze mozes programovat akoby si robil prepared statements a bude to fungovat aj s databazou, ktora ich nepodporuje, neskor ked budes chciet pouzit databazu s prepared statements staci ti pridat jeden riadok kodu. A ano, vo vacsine pripadov to bude rychlejsie.
Vyhodou prepared statements je ako som spominal v clanku nulova moznost SQL injekcie a vyssia rychlost v pripade, ze sa jedno query bude volat viac-krat s roznymi vstupmi.
Podstatne je, ze ak uz pouzivas prepared statements ci uz skutocne alebo emulovane, alebo mysqli_real_escape_string, tak si vyhral a tvoj kod je z hladiska SQL injekcie bezpecny.

@Miloš Nie je na to (AFAIK) ziadne elegantne riesenie, musis vygenerovat tu cast statementu a potom v cykle dosadit hodnoty, teda napr.:

$data = array(1, 2, 3, 4, 5, 6);
$stmt_in_section = substr(str_repeat(',?', count($a)), -1); // vrati "?,?,?,?,?,?"
$stmt = $pdo->prepare("SELECT * FROM users WHERE id IN ($stmt_in_section)");
foreach($data as $key => $val) $stmt->bindValue($key +1, $val);

Z tych dvoch riadkov si potom mozes vytvorit pomocnu funkciu alebo metodu. V realnych projektoch ale prevdepodobne nebudes pracovat priamo s PDO, ale s nejakou vyssou vrstvou postavenou nad PDO, ktora bude taketo veci ulahcovat.
0 0 Ucitel 2012-12-28 22:24:58
@tester Tazko povedat, ja volim vacsinou MySQL kvoli tomu ze sa v nej najlepsie vyznam a je najdostupnejsia na hostingoch, s ostatnymi databazami nemam tak vela skusenosti. V blizkej buducnosti by som sa chcel urcite pozriet lepsie na PostgreSQL, ktora vie kopec cool veci oproti MySQL a vyzera ako zlata stredna cesta medzi MySQL a Oracle/MSSQL
0 0 Ucitel 2012-12-28 20:39:57
@tester Procedury su v niecom podobne, ale vedia toho podstatne viac. Procedury mozu obsahovat logiku a niekolko samotnych dotazov, vacsinou su ulozene v databaze perzistentne, naopak prepared statements su obycajne dotazy, ktore su docasne ulozene a daju sa volat s roznymi argumentami.
0 0 Ucitel 2012-12-28 20:02:16
Edit: Doplnene do sample kodu vypnutie emulacie prepared statements, ktora je defaultne zapnuta, to znamena ze PDO defaultne iba escapuje vstupy a spusta normalne dotazy a nepouziva skutocne prepared statements.

@ritopich Tnx za komentar, v clanku bola mensia chyba.
Pri pouziti nativnych prepared statements sa skutocne posielaju dva dotazy, pri volani prepare sa hned posle PREPARE dotaz, bindValue/bindParam iba zbiera data do instancie objektu a execute ich potom odosle v EXECUTE dotaze.
Defaultne je ale v PDO zapnuta emulacia prepared statements a data sa iba escapuju, dosadia a odoslu ako normalny dotaz v execute.
Co sa tyka frameworku, tak aj ked na velke aplikacie by som dnes uz pouzil ORM (ktore bude aj tak postavene na PDO alebo mysqli), na mensie aplikacie je to vacsinou overkill a myslim si ze je dobre vediet ako to skutocne funguje pred tym ako sa naucim nejaky vyssi framework.

@Miro Miťko Rosival To je fajn, myslel ze je to az prilis suche a neutralne.
2 1 Ucitel 2012-12-28 03:21:51
Ten server-side kod je dost tragedia, mysql_ funkcie su dlhodobo nevyvijane (v dalsej verzii php budu deprected), spravne je pouzit mysqli_ alebo PDO.
Co je horsie je ta exemplarna sqli diera, vstupne data musis escapovat pomocou mysqli_real_escape_string (ziadne strip_tags a htmlescapechars) alebo este lepsie pouzit prepared statements.
Okrem toho ak pouzivas LIKE musis escapovat aj znaky % a _, inak si pouzivatel zadanim takeho znaku bude vediet vypisat celu databazu.

Okrem toho mas v celom clanku kopec nepresnosti a chyb (chybajuce uvodzovky, v javaskripte neexistuje funkcia die, etc..), nabuduce si to po sebe aspon raz precitaj.
Zajtra.sk > Ľudia > Ucitel