MySQL zaujímavosť

Smokie

MySQL zaujímavosť
« kdy: 23. 11. 2011, 12:17:36 »
Ahojte,

narazil som na zaujimavú vlastnosť MySQL, o ktorej som doteraz, po rokoch, nevedel.

Hral som sa s Cart triedou v CodeIgniterovi, ktorá vytvára nákupný košík. Ako ID tovaru som musel zadať reťazec, ktorý kombinoval ID tovaru a ID jeho variantu. Takže výsledný tvar bol napríklad "14_78".

V takomto tvare som to poslal do modelu do metódy, ktorá mala nájsť tovar podľa jeho ID a samozrejme som očakával chybu. Namiesto toho sa mi vrátil správny výsledok.

Požiadavky
SELECT * FROM table WHERE ID = 14
SELECT * FROM table WHERE ID = "14_78"
vrátia rovnaké výsledky. Pritom ID je integer.
Potom som sa s tým trochu hral a skúšal rôzne kolízne možnosti typu dať hľadať "6_78" a očakávať, či mi nenájde riadky s ID 6 a 60...69, napríklad. Ale nestalo sa.

Je bezpečné používať tento spôsob? Máte niekto s tým skúsenosti? Je to vlastnosť alebo chyba, ktorá môže jedného dňa vystreliť?



Petr_Svetr

Re: MySQL zaujímavosť
« Odpověď #1 kdy: 23. 11. 2011, 13:01:56 »
Ako ID tovaru som musel zadať reťazec, ktorý kombinoval ID tovaru a ID jeho variantu. Takže výsledný tvar bol napríklad "14_78".
To nechapu, kombinace dvou ID ze dvou tabulek je zaklad navrhu DB - proc pouzivate tuhle prasarnu? Kdo vam tohle poradil, nebo jste tak invencni sam? Co si nastudovat treba zaklady navrhu DB - nemate cas?
Zalezi, co s tim konkretne chcete delat, ale IMHO by to asi chtelo vazebni tabulku s dvema FK. Potom i vazebni ID (PK) bude ciselne a nemusite resit chujoviny typu spojovani dvou ID do stringu.
Omlouvam se ostrejsi ton, ale tohle znaci elementarni neznalost a podobnym stylem prace se pripravte na velky prusvih...

Rda

Re: MySQL zaujímavosť
« Odpověď #2 kdy: 23. 11. 2011, 13:34:29 »
To neni zajimavost, to je standardni chovani:

http://dev.mysql.com/doc/refman/5.0/en/type-conversion.html

Ale z vasi strany je prasarna provozovat dany SQL dotaz, tipuji ze tam mate i sql injection diru o ktere nevite - neosetreny retezec :)

Udelejte si z daneho vstupu cislo jiz predem, nez ho zacnete posilat do mysql.. a pak ho nemusite uvozovkovat - napr. to prozente funkci intval($vstup) - to je zrejme beztak to co by udelalo i mysql:

http://php.net/manual/en/function.intval.php
http://www.php.net/manual/en/language.types.string.php#language.types.string.conversion

a tam naleznete ze jadrem veci je strtod():

http://linux.die.net/man/3/strtod

ZAVER: Funguje to, to ano, ale neni to ciste reseni. Taky bych vam vynadal, ale uz to udelal kolega prede mnou :)

Re: MySQL zaujímavosť
« Odpověď #3 kdy: 23. 11. 2011, 13:35:12 »
Je bezpečné používať tento spôsob? Máte niekto s tým skúsenosti? Je to vlastnosť alebo chyba, ktorá môže jedného dňa vystreliť?
Vyzkoušejte si následující SQL dotaz a třeba vás něco trkne:

SELECT CAST('14_78' as UNSIGNED INTEGER)

Re: MySQL zaujímavosť
« Odpověď #4 kdy: 23. 11. 2011, 13:35:36 »
Požiadavky
SELECT * FROM table WHERE ID = 14
SELECT * FROM table WHERE ID = "14_78"
vrátia rovnaké výsledky. Pritom ID je integer.

Je bezpečné používať tento spôsob? Máte niekto s tým skúsenosti? Je to vlastnosť alebo chyba, ktorá môže jedného dňa vystreliť?

A nebude to tím, že MySQL převede řetězec "14_78" na 14. Stejně dopadne "14whatever", ne?


Smokie

Re: MySQL zaujímavosť
« Odpověď #5 kdy: 23. 11. 2011, 14:31:15 »
Nemusite sa bat. O ziadnu chybu v navrhu databaze nejde.
Ale to by vas napadlo ak by ste si poriadne precitali na co reagujete. To na margo toho ostreho tonu, teraz uz pokracujme normalne a kludne. :)

Trieda Cart si vytvara pole v session, do ktoreho uklada polozky v nakupnom kosiku. To pole ma dopredu nastavene kluce a mne sa ho nechcelo vtedy rozsirovat (ano, je tam aj kluc "options", ale...). Jeden z tych klucov je aj ID, ktore ma reprezentovat ID tovaru/polozky v databaze. Ja som k tomu ale potreboval pridat este dalsie ID, ktore reprezentuje doplnkovy udaj (dajme tomu farbu tovaru). V danej chvili som nevedel kde ho vlozit, tak mi napadlo, ze ho prilepim do kluca ID, spojim ho s id tovaru a potom az bude treba, tak ich zase rozlepim.

Potom som kod spustil, bez rozlepenia, ocakaval som v tej casti, ktorej sa to tyka chybu, resp. nulovy vysledok a on tam zrazu vysledok bol.

To je cele.

Ziadna prasarna, ziadna bezpecnostna chyba. :) intval poznam a vsetko je osetrene ako ma byt.

Ale ma to zaujalo a chcel som vediet kto ma s tym ake skusenosti a o co sa vlastne jedna.

Smokie

Re: MySQL zaujímavosť
« Odpověď #6 kdy: 23. 11. 2011, 14:32:38 »
Požiadavky
SELECT * FROM table WHERE ID = 14
SELECT * FROM table WHERE ID = "14_78"
vrátia rovnaké výsledky. Pritom ID je integer.

Je bezpečné používať tento spôsob? Máte niekto s tým skúsenosti? Je to vlastnosť alebo chyba, ktorá môže jedného dňa vystreliť?

A nebude to tím, že MySQL převede řetězec "14_78" na 14. Stejně dopadne "14whatever", ne?
Ano, to tiez funguje.

Logik

  • *****
  • 1 022
    • Zobrazit profil
    • E-mail
Re: MySQL zaujímavosť
« Odpověď #7 kdy: 23. 11. 2011, 16:33:18 »
To, že je to standardní chování mysql  nic nemění na tom, že je to špatné chování. Implicitní konverze z řetězce na číslo "tiše" zahazující chyby je prasečina. Např. z toho důvodu, že až tam jednou přijde řetězec, kterej opravdu číslo bejt nemá, tak to mysql nepozná a pojede v pohodě a tiše dál... Takže se nedivím, že se tomu tazatel diví.

K

Re: MySQL zaujímavosť
« Odpověď #8 kdy: 23. 11. 2011, 17:36:29 »
Mam pocit, ze pokud by se zapnul strict mod v mysql tak by to chybu vyhodilo, ale mozna kecam.

petr.svetr

Re: MySQL zaujímavosť
« Odpověď #9 kdy: 23. 11. 2011, 19:37:54 »
Nemusite sa bat. O ziadnu chybu v navrhu databaze nejde.
Ale to by vas napadlo ak by ste si poriadne precitali na co reagujete. To na margo toho ostreho tonu, teraz uz pokracujme normalne a kludne. :)
kdyz myslite - ja jsem presvedceny, ze ano, protoze to co popisujete je duvod, proc pred 40 lety vznikly RDMS.
Nezivim se jako programator, ale celkem jim vidim pod ruce a za tohle se sekaji ruce, ukopavaji k*lky a tak dale.Samozrejme ve vasem konkretnim pripade to nejde resit pres relace, jiste.
Hodne stesti, bydete ho potrebovat.

Kit

Re: MySQL zaujímavosť
« Odpověď #10 kdy: 23. 11. 2011, 20:53:32 »
kdyz myslite - ja jsem presvedceny, ze ano, protoze to co popisujete je duvod, proc pred 40 lety vznikly RDMS.
Nezivim se jako programator, ale celkem jim vidim pod ruce a za tohle se sekaji ruce, ukopavaji k*lky a tak dale.Samozrejme ve vasem konkretnim pripade to nejde resit pres relace, jiste.
Hodne stesti, bydete ho potrebovat.
Smokie asi chtěl naznačit, že ten špatný databázový model nevymyslel on, ale někdo jiný a teď se ho jen snaží udělat ještě horším.

Smokie: Popsaný způsob je v rozporu s 1NF. Pokud chceš přidat další atribut, tak si ho klidně přidej, ale ne takovým způsobem. Proč jednoduše nepřidáš další sloupec do tabulky?

Smokie

Re: MySQL zaujímavosť
« Odpověď #11 kdy: 23. 11. 2011, 21:03:22 »
kdyz myslite - ja jsem presvedceny, ze ano, protoze to co popisujete je duvod, proc pred 40 lety vznikly RDMS.
Nezivim se jako programator, ale celkem jim vidim pod ruce a za tohle se sekaji ruce, ukopavaji k*lky a tak dale.Samozrejme ve vasem konkretnim pripade to nejde resit pres relace, jiste.
Hodne stesti, bydete ho potrebovat.
Smokie asi chtěl naznačit, že ten špatný databázový model nevymyslel on, ale někdo jiný a teď se ho jen snaží udělat ještě horším.

Smokie: Popsaný způsob je v rozporu s 1NF. Pokud chceš přidat další atribut, tak si ho klidně přidej, ale ne takovým způsobem. Proč jednoduše nepřidáš další sloupec do tabulky?
Ale aky dalsi stlpec? :D Je jedna tabulka s tovarom, druha tabulka s jeho variantami. Varianty maju okrem svojho ID a FK tovaru. Ziadna dalsia tabulka ohladom toho nie je nutna, ani ziadana, pretoze to spojenie ID je len v session a nikde inde.

Aj ked vlastne... preco mi nenapadlo skor posielat iba ID variantu namiesto ID tovaru, ked ten vztah je v databaze. Aj ked neviem ci vam prave o toto islo. :)

Kit

Re: MySQL zaujímavosť
« Odpověď #12 kdy: 23. 11. 2011, 21:26:41 »
Ale aky dalsi stlpec? :D Je jedna tabulka s tovarom, druha tabulka s jeho variantami. Varianty maju okrem svojho ID a FK tovaru. Ziadna dalsia tabulka ohladom toho nie je nutna, ani ziadana, pretoze to spojenie ID je len v session a nikde inde.

Aj ked vlastne... preco mi nenapadlo skor posielat iba ID variantu namiesto ID tovaru, ked ten vztah je v databaze. Aj ked neviem ci vam prave o toto islo. :)

Jestliže tabulka Varianty má ID a FK, jsou to zřejmě 2 sloupce. 1NF říká, že hodnoty ve sloupcích mají být atomické. Tabulka Varianty to možná splňuje. Otázkou je, jestli primárním klíčem v tabulce Varianty je pouze sloupec ID nebo dvojice ID+FK a zda tabulka Varianty splňuje 2NF. Podle toho se bude vytvářet i cizí klíč v tabulce Tovar z jednoho nebo dvou hodnot (VariantyID nebo VariantyID+VariantyFK). V obou případech je však potřeba, aby FK v tabulce Tovar byl samostatný sloupec.

Smokie

Re: MySQL zaujímavosť
« Odpověď #13 kdy: 23. 11. 2011, 21:43:20 »
Ale aky dalsi stlpec? :D Je jedna tabulka s tovarom, druha tabulka s jeho variantami. Varianty maju okrem svojho ID a FK tovaru. Ziadna dalsia tabulka ohladom toho nie je nutna, ani ziadana, pretoze to spojenie ID je len v session a nikde inde.

Aj ked vlastne... preco mi nenapadlo skor posielat iba ID variantu namiesto ID tovaru, ked ten vztah je v databaze. Aj ked neviem ci vam prave o toto islo. :)

Jestliže tabulka Varianty má ID a FK, jsou to zřejmě 2 sloupce. 1NF říká, že hodnoty ve sloupcích mají být atomické. Tabulka Varianty to možná splňuje. Otázkou je, jestli primárním klíčem v tabulce Varianty je pouze sloupec ID nebo dvojice ID+FK a zda tabulka Varianty splňuje 2NF. Podle toho se bude vytvářet i cizí klíč v tabulce Tovar z jednoho nebo dvou hodnot (VariantyID nebo VariantyID+VariantyFK). V obou případech je však potřeba, aby FK v tabulce Tovar byl samostatný sloupec.
Evidentne si vobec nerozumieme.

ID v tabulkach su atomicke. ID v tabulke je iba ID, konkretne int(11), nie je to kombinacia ID a FK. ID stlpce su nastavene ako primarny kluc a maju nastaveny autoincrement. :) Kombinaciou ID a FK to zacalo byt IBA a LEN v session, cize mimo databazovej vrstvy. A potom som poslal SELECT v ktorom som vo WHERE namiesto atomickeho ID zadal kombinaciu "ID_FK" (SELECT FROM table WHERE ID = "14_154", napriklad) a namiesto toho aby take query nenaslo nic alebo vyvolalo chybu (co bolo ocakavane spravanie, pretoze neexistuje riadok s ID = 14_154, iba 14), tak vratilo rovnaky vysledok ako keby som do WHERE zadal iba ID (co bolo prekvapive spravanie).

bydga

Re: MySQL zaujímavosť
« Odpověď #14 kdy: 23. 11. 2011, 21:54:08 »
Atomicita fajn, proto např. Facebook používá pro zaměření postu kombinaci pageid_postid - viz
http://graph.facebook.com/110636388961605_231438083589209
což je post
https://www.facebook.com/permalink.php?story_fbid=231438083589209&id=110636388961605

Nechci shazovat 3NF, ale mimo VŠ prostě existují situace, kdy se to nevyplatí:)