Rad sa bazom podataka u Drupal 7 - lekcija 11 - Merge upiti (spajanje)
Merge upiti su specijalni hibridni tip upita. Iako je sintaksa za ove upite definisana u SQL 2003, zapravo ne postoji baza podataka koja podržava ovu sintaksu direktno. Međutim, većina baza nudi alternativne implementacije sa specifičnim sintaksama. Konstruktor merge upita u Drupalu apstrahuje koncept merge upita u obliku objekta, tako da se objekat može različito kompajlirati za svaku bazu, uzimajući u obzir njene specifičnosti.
U opštem smislu, merge upit je kombinacija INSERT i UPDATE upita. Ako postoji red sa određenim ključem koji zadovoljava uslove, izvršiće se UPDATE, a ako ne postoji, izvršiće se INSERT. U većini slučajeva to je ekvivalentno sledećem:
<?php if (db_result(db_query("SELECT COUNT(*) FROM {example} WHERE id=:id", array(':id' => $id))->fetchField())) { // Izvrši UPDATE sa WHERE id = $id } else { // Izvrši INSERT sa id = $id } ?>
Prava implementacija zavisi od baze podataka. Iako je koncept merge upita atomska operacija, implementacija može biti ili ne biti atomska u zavisnosti od baze. MySQL implementacija je atomska, dok primer gore nije.
Osnovni primer
<?php db_merge('example') ->key(array('name' => $name)) ->fields(array( 'field1' => $value1, 'field2' => $value2, )) ->execute(); ?>
U ovom primeru radimo sa tabelom "example". Definišemo jedan ključ 'name' sa vrednošću $name, i niz polja sa vrednostima za upis.
Ako red sa poljem 'name' jednakim $name postoji, biće ažurirana polja field1 i field2 sa vrednostima $value1 i $value2. Ako red ne postoji, biće kreiran novi red sa tim vrednostima.
Različite vrednosti za insert i update
Možemo postaviti različite vrednosti za INSERT i UPDATE deo:
<?php db_merge('example') ->key(array('name' => $name)) ->fields(array( 'field1' => $value1, 'field2' => $value2, )) ->updateFields(array( 'field1' => $alternate1, )) ->execute(); ?>
U ovom primeru, ako red postoji, polje field1 će biti ažurirano na vrednost $alternate1. Ako ne postoji, biće kreiran novi red sa vrednostima $value1 i $value2 za field1 i field2.
Metod updateFields()
prima jedan asocijativni niz polja i vrednosti, ili dva numerička niza (polja i vrednosti) u istom redosledu.
Upotreba SQL izraza
<?php db_merge('example') ->key(array('name' => $name)) ->fields(array( 'field1' => $value1, 'field2' => $value2, )) ->expression('field1', 'field1 + :inc', array(':inc' => 1)) ->execute(); ?>
U ovom primeru, ako red postoji, vrednost polja field1 će biti povećana za 1. Ovo je korisno za upite brojača, kada treba povećavati vrednost prilikom svakog događaja. Ako red ne postoji, polja field1 i field2 će biti postavljena na $value1 i $value2.
Metod expression()
može se pozvati više puta za različita polja, gde prvi parametar označava polje, drugi SQL izraz koji treba postaviti, a treći niz vrednosti za zamenu unutar izraza.
Nije potrebno da polje u expression()
bude prisutno i u fields()
.
Ograničeno ažuriranje
<?php db_merge('example') ->key(array('name' => $name)) ->fields(array( 'field1' => $value1, 'field2' => $value2, )) ->updateExcept('field1') ->execute(); ?>
Metod updateExcept()
prima niz polja ili niz parametara sa imenima polja. Polja navedena u ovom metodu neće biti ažurirana ako red postoji. U ovom primeru, ako red postoji, polje field2 će biti ažurirano na $value2, dok će field1 ostati nepromenjeno. Ako red ne postoji, biće kreiran sa vrednostima $value1 i $value2.
Prioritet
API omogućava postavljanje upita koji mogu biti besmisleni, pa se primenjuju sledeća pravila da se minimiziraju greške:
- Ako je polje definisano u
expression()
, ima veći prioritet odupdateFields()
iupdateExcept()
. - Ako je vrednost definisana u
updateFields()
, ignorisaće seupdateExcept()
. - Ako su polja definisana u
updateFields()
, samo ta polja će biti ažurirana ako red postoji. Polja koja nisu navedena neće biti menjana.
Međutim, moguće je definisati upite koji nemaju smisla.