8. Lecke: MySQL-adatbázisok kezelése PHP-ben
8.6 DML INSERT
Új rekord beszúrása egy táblába legalább olyan egyszerű, mint a rekord módosítása. A végrehajtásban sincs nagy különbség, csupán az SQL-mondat lesz más. Mégis azt kell mondanunk, hogy a jól megtervezett adatbázisban az új rekordok fölvétele okozza a legtöbb gondot. Lássuk csak miért!
A redundancia kiküszöbölése érdekében az adatbázis tervezésekor olyan adatszerkezetet alakítunk ki, amely részleges és a tranzitív függésektől mentes.
Mivel a káros függések megszűntetésekor dekompozíciót alkalmazunk, még a kis adatbázisok is több táblákra bomlanak. A táblák közötti kapcsolatokat ide-gen kulcsok írják le.
A felhasználó ebből persze semmit sem lát. Amikor megadja egy könyv adatait, nem érdekli őt, hogy a kiadók, és a szerzők külön táblában tárolódnak és arra is fittyet hány, hogy a konyv és szerzo tábla N:M kapcsolat miatt kapcsolótáblára is szükség volt. Egy könyv összes adatát egyetlen űrlapon akarja begépelni. A programozónak természetesen olyan kezelőfelületet kell
előállíta-nia, amelyen a felhasználó kényelmesen dolgozhat, de a bejövő adatokat (meg-felelő ellenőrzés után) a különböző táblákban kell tárolnia, és az idegen kulcsok helyességéről is gondoskodnia kell.
Következő példánkban egy könyv adatait rögzítjük. Az egyszerűség kedvé-ért induljunk ki abból, hogy a bevitel megtörtént, az adatok eljutottak a szerver-re, és a validáláson is túlvagyunk. A rögzítendő adatokat a jobb áttekinthetőség kedvéért egy asszociatív tömbbe rendeztük:
$insert=array(
"kiado"=>array("kiNev"=>"Szak Kiadó Kft."), "szerzo"=>array("szNev"=>"Young, Michael J."), "konyv"=>array( re-kordjainak mezőnevei és értékeik. Az azonosítók mindenhonnan hiányoznak, ugyanis a táblában automatikus sorszámozású (AUTO_INCREMENT) mezők lesznek az azonosítók.
A fenti tömb csak az adatok átláthatóságát szolgálja, a példaprogra-mokban nem szerepel.
A feladatot a kiado táblával kell kezdenünk. Az új kiadó rekordjának be-szúrása nem fog nehézséget okozni, azonban nem szabad megfeledkezni arról, hogy szükségünk lesz az újonnan beszúrt rekord azonosítójára, hiszen ez idegen kulcsként fog szerepelni a konyv táblában.
A kiadó után fölvehetjük az új könyvet, majd a szerzőt, de ismét meg kell jegyeznünk azonosítókat, hiszen a kony_szerzo táblában idegen kulcsokkal kell jelezni az új könyv és az új szerző kapcsolatát.
Összesen tehát négy táblába kell rekordot elhelyeznünk. A nehézségeket tovább fokozza ez egyes műveletek esetén fennálló hibalehetőség.
Ha fel tudjuk venni az új könyvet és a szerzőt, de a konyv_szerzo tábla rekordjának beszúrásakor hiba keletkezik, akkor minden lépést vissza kellene vonnunk…
Töröljük az érintett táblából az utolsó rekordokat? Jó megoldás! ...Akkor, ha csak mi használjuk az adatbázist. A web alkalmazásnak azonban éppen az az
168 MySQL-adatbázisok kezelése PHP-ben
óriási előnye, hogy egyszerre többen is dolgozhatnak vele. Mi történik, ha a mi munkánk közben más is rögzített könyveket? Bizony ilyenkor az ő rekordjaikat törölnénk egy estleges visszalépéskor.
Szerencsére a MySQL InnoDB táblái tranzakcióbiztosak (a mi adatbázisunk táblái ilyenek), így nyugodtan használhatjuk a tranzakció kezelést!
Ehhez semmi egyebet nem kell tennünk, mint a mysql_query() függ-vénnyel, a megfelelő helyeken el kell küldenünk a "BEGIN", "COMMIT", illetve a "ROLLBACK" parancsokat.
Az első INSERT előtt a mysql_query("BEGIN"); függvényhívással elindítjuk a tranzakciót. Elvégezzük a rekordok beszúrását, de minden egyes INSERT-eknél külön változóban tároljuk az erőforrás azonosítót. A rekordfölvéltelek után megvizsgáljuk őket. Ha bármelyik erőforrás azonosító false, akkor visszagörgetjük a tranzakciót. Azaz minden INSERT-et
semmis-sé teszünk. Ha minden rendben ment, akkor egy
mysql_query("COMMIT")-tal zárjuk a műveleteket.
Valójában egyetlen problémánk maradt. Hogyan tudjuk meg az elsődleges táblákba beszúrt rekordok azonosítóit? A beszúrás utáni utolsó rekord azonosí-tójának lekérdezése az ismert okok miatt nem járható út. A MySQL API-ban azonban rendelkezésre áll a mysql_insert_id() függvény, amely a meg-adott kapcsolat legutolsó AUTO_INCREMENT értékét adja vissza.
egész mysql_insert_id ([erőforrás_id] )
Ezzel a függvénnyel már megtudhatjuk az egyes INSERT parancsokkal be-szúrt utolsó rekordok azonosítóit, hiszen a tábláink mindegyike AUTO_INCREMENT azonosítókat tartalmaz.
Forrás: mysql_query_insert.php
70. ábra Rekordok tranzakció biztos beszúrása
8.7 ÖSSZEFOGLALÁS, KÉRDÉSEK
8.7.1 Összefoglalás
Mai leckénkben a PHP MySQL API-jának legfontosabb függvényeit ismertük meg. Megtanultuk, hogy a MySQL-szerverek elérése a kapcsolat fölépítésével kezdődik, amit a mysql_connect() függvény hívásával végezhetünk el.
Ezután következik a mysql_select_db() indítása, azaz az adatbázis kivá-lasztása. A létrehozott SQL-mondatot, a myslq_query() függvénnyel küld-hetjük el az adatbázis-kezelő rendszernek, az eredményt pedig általában válto-zóba tesszük. A DQL-lekérdezések erőforrás azonosítóval, vagy false értékkel a DML-mondatok true, vagy false eredménnyel térnek vissza. A relációkat visszaadó lekérdezések rekordjait a mysql_fetch_row(), illetve a mysql_fetch_assoc() függvények ciklikus hívásával nyerhetjük ki.
A DML-mondatok végrehatása után csak arra kell figyelni, hogy a művelet sikeres volt-e. Ha adatbázisunk táblái tranzakció biztosak, a BEGIN, COMMIT, és ROLLBACK parancsok elküldésével valósíthatjuk meg tranzakció kezelést.
8.7.2 Önellenőrző kérdések
1. Hány MySQL kapcsolatot nyithatunk meg ugyanahhoz a szerverhez egy PHP-szkriptben?
170 MySQL-adatbázisok kezelése PHP-ben
Általában egyet nyitunk, de több kapcsolatot is fölépít-hetünk. Tudni kell azonban, hogy a mysql_connect() többszöri meghívása esetén alapértelmezésben ugya-nazt a kapcsolat azonosítót adja vissza. Ha azonban a függvény negyedik paraméterként true értéket adunk meg, akkor minden hívás új kapcsolatot alakít ki.
2. Megmaradhat-e a kapcsolat, ha a mysql_connect() függvénytől ka-pott azonosítót munkamenet változóként tároljuk?
Nem. A kapcsolat mindenképpen megszakad, amikor a PHP-szkript befejeződik.
3. Mire használható a mysql_set_charset() függvény?
A MySQL-szervertől érkező válaszok karakterkódolá-sának szabályozására.
4. Hogyan törölhet rekordot egy táblából?
A DELETE parancsot tartalmazó SQL-mondatot el kell küldeni a MySQL-szervernek, és megvizsgálni, hogy a mysql_query() függvény visszatérési értéke true, vagy false.
5. Hogyan tudja elérni, hogy az egymás után végrehajtott
DML-lekérdezésnek csak akkor legyen hatása, ha mindegyik végrehajtása sikeres volt?
A lekérdezések elküldését tranzakción belül kell elvé-gezni. Ha bármelyik mysql_query() false eredményt ad vissza, ki kell adni a mysql_query(”ROLLBACK”); paran-csot. Ha minden DML-mondat sikeresen lefutott, akkor a mysql_query(”COMMIT”) hívással lehet jóváhagyni a tranzakciót.