Obiekt Zend_Db_Select
reprezentuje pojedyncze polecenie
SQL SELECT. Klasa posiada metody służące do
umieszczenia poszczególnych części zapytania. Za jej pomocą można zapisać elementy
zapytania poprzez metody i struktur danych PHP a klasa sama
tworzy poprawne polecenie SQL. Po zbudowaniu zapytania można go
użyć tak jakby było napisane w postaci zwykłego łańcucha znaków.
Wartość Zend_Db_Select
zawiera się w poniższych cechach:
-
Metody obiektowe służące tworzeniu zapytań SQL krok po kroku;
-
Poziom abstrakcji umożliwiający używanie określonych części zapytania SQL są w sposób niezależny od rodzaju bazy danych;
-
Automatyczne umieszczanie identyfikatorów metadanych w cudzysłowach ułatwia używanie identyfikatorów zawierających zarezerwowane słowa i specjalne znaki SQL;
-
Umieszczanie identyfikatorów i wartości w cudzysłowach pomaga ograniczyć ryzyko ataków wstrzykiwania kodu SQL (SQL injection);
Używanie Zend_Db_Select
nie jest obowiązkowe. Dla najprostszych
zapytań SELECT z reguły łatwiej jest zapisać
całe polecenie SQL w
postaci łańcucha znaków i wywołać je za pomocą metod Adaptera takich jak
query()
lub fetchAll()
. Użycie
Zend_Db_Select
jest przydatne jeśli zajdzie potrzeba połączenia
części złożonego zapytania w kodzie np. w zależności od wystąpienia dodatkowych warunków
logicznych.
Instancję klasy Zend_Db_Select
można utworzyć poprzez metodę
select()
obiektu
Zend_Db_Adapter_Abstract
.
Przykład 232. Przykład metody select() adaptera bazy danych
$db = Zend_Db::factory( ...options... ); $select = $db->select();
Innym sposobem utworzenia obiektu Zend_Db_Select
jest użycie
konstruktora, podając adapter bazy danych w argumencie.
Przykład 233. Przykład tworzenia nowego obiektu Select
$db = Zend_Db::factory( ...options... ); $select = new Zend_Db_Select($db);
Budując zapytanie można dodawać jego części jedna po drugiej. Obiekt
Zend_Db_Select
posiada odrębne metody dla każdej klauzuli
SQL.
Przykład 234. Przykład użycia metod służących dodawaniu części zapytania
// Utworzenie obiektu Zend_Db_Select $select = $db->select(); // Dodanie klauzuli FROM $select->from( ...podanie tabel i kolumn... ) // Dodanie klauzuli WHERE $select->where( ...podanie kryteriów ograniczenia... ) // Dodanie klauzuli ORDER BY $select->order( ...podanie kryteriów sortowania... );
Większości metod obiektu Zend_Db_Select
można używać za pomocą
przyjaznego płynnego interfejsu (fluent interface). Interfejs płynny oznacza, że
każda z metod zwraca referencję do obiektu wywołującego więc można od razu
użyć następnej metody.
Przykład 235. Przykład użycia płynnego interfejsu
$select = $db->select() ->from( ...podanie tabel i kolumn... ) ->where( ...podanie kryteriów ograniczenia... ) ->order( ...podanie kryteriów sortowania... );
Przykłady w tym rozdziale używają płynnego interfejsu ale zawsze można z niego zrezygnować. Często może się to okazać niezbędne w przypadku gdy należy wykonać operacje zgodne z logiką biznesową aplikacji przed umieszczeniem dodatkowej klauzuli w zapytaniu.
Można wybrać tabelę dla zapytania używając metody from()
.
Aby tego dokonać należy podać nazwę tabeli jako łańcuch znaków.
Zend_Db_Select
umieszcza cudzysłowy wokół podanej nazwy, więc
można używać znaków specjalnych.
Przykład 236. Przykład użycia metody from()
// Utworzenie zapytania: // SELECT * // FROM "products" $select = $db->select() ->from( 'products' );
Można podać również nazwę korelacyjną (nazywaną również aliasem tabeli) danej
tabeli.
Aby to zrobić w argumencie należy podać tablicę asocjacyjną, która będzie zawierała
mapowanie nazwy aliasu na nazwę tabeli. W pozostałych częściach zapytania
SQL będzie można używać tej nazwy zamiast tabeli. Jeśli
dane zapytanie łączy wiele tabel
Zend_Db_Select
utworzy unikalne aliasy na
podstawie prawdziwych nazw dla każdej tabeli dla której nie zrobi tego użytkownik.
Przykład 237. Przykład użycia aliasu
// Utworzenie zapytania: // SELECT p.* // FROM "products" AS p $select = $db->select() ->from( array('p' => 'products') );
Niektóre silniki bazy danych (RDBMS) wspierają podawanie
nazw schematu przed nazwą tabeli. W takim przypadku należy podać nazwę tabeli jako
"nazwaSchematu.nazwaTabeli" a
Zend_Db_Select
umieści w cudzysłowach każdą z części takiej nazwy indywidualnie. Można też podać
nazwę schematu oddzielnie. Nazwa schematu podana przy nazwie tabeli ma pierwszeństwo
wobec nazwy schematu podanej osobno (jeśli obie występują).
Przykład 238. Przykład podawania nazwy schematu
// Utworzenie zapytania: // SELECT * // FROM "myschema"."products" $select = $db->select() ->from( 'myschema.products' ); // lub $select = $db->select() ->from('products', '*', 'myschema');
Drugi argument metody from()
może zawierać kolumny, które
mają zostać pobrane z odpowiedniej tabeli. Jeśli nie poda się tego
argumentu domyślną wartością jest "*" czyli znak
specjalny SQL odpowiadający wszystkim kolumnom.
Kolumny można podawać w prostej tablicy łańcuchów tekstowych lub jako asocjacyjnej tablicy aliasów kolumn do nazw kolumn. Jeśli potrzebna jest tylko jedna kolumna to można ją podać w prostym stringu - nie trzeba używać tablicy.
Jeśli w tym argumencie zostanie podana pusta tablica to żadna kolumna z odpowiedniej
tabeli nie zostanie dołączona do wyniku zapytania. Zobacz
przykład kodu
znajdujący się pod rozdziałem dotyczącym metody join()
.
Nazwę kolumny można podać w formie "nazwaAliasu.nazwaKolumny".
Zend_Db_Select
umieści każdą z części nazwy oddzielnie
w cudzysłowach, używając aliasu wcześniej ustalonego w metodzie
from()
(jeśli nie został podany bezpośrednio).
Przykład 239. Przykład dodawania kolumn
// Tworzenie zapytania: // SELECT p."product_id", p."product_name" // FROM "products" AS p $select = $db->select() ->from(array('p' => 'products'), array('product_id', 'product_name')); // Tworzenie podobnego zapytania z użyciem aliasów tabeli: // SELECT p."product_id", p."product_name" // FROM "products" AS p $select = $db->select() ->from(array('p' => 'products'), array('p.product_id', 'p.product_name')); // Tworzenie podobnego zapytania z aliasem dla jednej kolumny: // SELECT p."product_id" AS prodno, p."product_name" // FROM "products" AS p $select = $db->select() ->from(array('p' => 'products'), array('prodno' => 'product_id', 'product_name'));
W zapytaniach SQL często zachodzi potrzeba użycia wyrażeń
zamiast zwykłych kolumn tabeli. Wyrażenia nie powinny być otoczone cudzysłowami
ani zawierać aliasów tabel. Jeśli podana kolumna zawiera nawiasy
Zend_Db_Select
rozpoznaje ją jako wyrażenie.
Można również samemu utworzyć obiekt klasy Zend_Db_Expr
aby łańcuch znaków nie został potraktowany jak zwykła nazwa kolumny.
Zend_Db_Expr
jest małą klasą zawierającą jeden string.
Zend_Db_Select
rozpoznaje instancje klasy
Zend_Db_Expr
i zamienia je na łańcuchy znaków ale nie
wprowadza zmian takich jak cudzysłowy czy aliasy tabel.
Uwaga
Używanie Zend_Db_Expr
dla wyrażeń nie jest obowiązkowe
jeśli zawiera ono nawiasy. Zend_Db_Select
rozpoznaje
nawiasy i traktuje dany łańcuch jak wyrażenie (nie umieszcza w cudzysłowach
ani nie dodanie nazw alias tabel).
Przykład 240. Przykłady podawania kolumn zawierających wyrażenia
// Tworzenie zapytania: // SELECT p."product_id", LOWER(product_name) // FROM "products" AS p // Wyrażenie z nawiasami staje się obiektem klasy Zend_Db_Expr. $select = $db->select() ->from(array('p' => 'products'), array('product_id', 'LOWER(product_name)')); // Tworzenie zapytania: // SELECT p."product_id", (p.cost * 1.08) AS cost_plus_tax // FROM "products" AS p $select = $db->select() ->from(array('p' => 'products'), array('product_id', 'cost_plus_tax' => '(p.cost * 1.08)') ); // Tworzenie zapytania używając Zend_Db_Expr: // SELECT p."product_id", p.cost * 1.08 AS cost_plus_tax // FROM "products" AS p $select = $db->select() ->from(array('p' => 'products'), array('product_id', 'cost_plus_tax' => new Zend_Db_Expr('p.cost * 1.08')) );
W powyższych przykładach Zend_Db_Select
nie zmienia stringa
i nie dodaje aliasów tabel ani nie używa cudzysłowów. Jeśli takie zmiany
są niezbędne (np. z powodu dwuznaczności nazw) należy je wprowadzić ręcznie.
Jeśli podane nazwy kolumn zawierają słowa kluczowe SQL lub
znaki specjalne należy użyć metody adaptera połączenia o nazwie
quoteIdentifier()
i rezultat umieścić w stringu. Metoda
quoteIdentifier()
używa cudzysłowów dzięki czemu można być
pewnym, że podany łańcuch znaków jest identyfikatorem tabeli lub kolumny
a nie częścią składni polecenia SQL.
Dzięki użyciu metody quoteIdentifier()
zamiast ręcznego
wpisywania cudzysłowów kod staje się niezależny od rodzaju bazy danych. Niektóre
systemy zarządzania bazą danych (RDBMS) używają niestandardowych
znaków do ograniczania identyfikatorów. Metoda
quoteIdentifier()
jest przystosowana do
używania odpowiednich symboli ograniczających w zależności od typu
używanego adaptera. Metoda quoteIdentifier()
dokonuje
również unikania znaków cudzysłowu, które pojawią się w argumencie wejściowym.
Przykład 241. Przykłady umieszczania wyrażeń w cudzysłowach
// Tworzenie zapytania, // umieszczając kolumnę o nazwie "from" w cudzysłowach: // SELECT p."from" + 10 AS origin // FROM "products" AS p $select = $db->select() ->from(array('p' => 'products'), array('origin' => '(p.' . $db->quoteIdentifier('from') . ' + 10)') );
Może powstać sytuacja w której niezbędne okazuje się dodanie kolumn do klauzuli
FROM lub JOIN,
która została utworzona wcześniej (za pomocą odpowiedniej metody).
Metoda columns()
pozwala na dodanie kolumn w dowolnym
momencie przed wykonaniem zapytania. Kolumny można podać jako łańcuchy znaków,
obiekty Zend_Db_Expr
lub jako tablice tych elementów. Drugi
argument tej metody może zostać pominięty co oznacza, że kolumny powinny zostać
dodane do tabeli z klauzuli FROM.
W przeciwnym razie należy podać alias lub nazwę tabeli.
Przykład 242. Przykłady dodawania kolumn metodą columns()
// Tworzenie zapytania: // SELECT p."product_id", p."product_name" // FROM "products" AS p $select = $db->select() ->from(array('p' => 'products'), 'product_id') ->columns('product_name'); // Tworzenie zapytania używając nazwy alias: // SELECT p."product_id", p."product_name" // FROM "products" AS p $select = $db->select() ->from(array('p' => 'products'), 'p.product_id') ->columns('product_name', 'p'); // Alternatywnie można użyć columns('p.product_name')
Wiele użytecznych zapytań zawiera klauzulę JOIN służącą do
łączenia wierszy z wielu tabel. Aby dodać tabele do obiektu
Zend_Db_Select
należy użyć metody
join()
. Używanie jej jest podobne do użycia metody
from()
z tym, że tu można również użyć warunek łączenia
tabel.
Przykład 243. Przykład użycia metody join()
// Tworzenie zapytania: // SELECT p."product_id", p."product_name", l.* // FROM "products" AS p JOIN "line_items" AS l // ON p.product_id = l.product_id $select = $db->select() ->from(array('p' => 'products'), array('product_id', 'product_name')) ->join(array('l' => 'line_items'), 'p.product_id = l.product_id');
Drugi argument metody join()
to string stanowiący warunek
połączenia. Jest to wyrażenie określające kryteria wg. których wiersze z
jednej tabeli łączą się z wierszami drugiej tabeli. W tym miejscu
można użyć aliasów tabel.
Uwaga
Do warunku połączenia nie są stosowane cudzysłowy; Jeśli występuje konieczność
umieszczenia nazwy kolumny w cudzysłowach, należy użyć metody adaptera
quoteIdentifier()
przy formowaniu wyrażenia warunku
połączenia.
Trzeci argument metody join()
to tablica nazw kolumn (tak
jak przy metodzie from()
). Domyślną wartością jest
"*". Można w nim podawać aliasy kolumn, wyrażenia lub obiekty
Zend_Db_Expr
w taki sam sposób jak w metodzie
from()
.
Aby nie wybierać żadnej kolumny należy podać pustą tablicę zamiast nazw kolumn.
Ten sposób działa również w metodzie from()
ale z
podstawowych tabel przeważnie kolumny są potrzebne, co nie zawsze jest prawdą
dla kolumn tabeli połączonej.
Przykład 244. Przykład nie podawania kolumn
// Tworzenie zapytania: // SELECT p."product_id", p."product_name" // FROM "products" AS p JOIN "line_items" AS l // ON p.product_id = l.product_id $select = $db->select() ->from(array('p' => 'products'), array('product_id', 'product_name')) ->join(array('l' => 'line_items'), 'p.product_id = l.product_id', array() ); // pusta lista kolumn
W miejscu listy kolumn tabeli połączonej występuje pusta tablica
(array()
).
SQL dysponuje wieloma rodzajami klauzul JOIN. Poniżej znajduje
się lista metod klasy Zend_Db_Select
obsługująca je.
-
INNER JOIN za pomocą
join(tabela, warunek, [kolumny])
lubjoinInner(tabela, warunek, [kolumny])
To jest najbardziej popularny rodzaj połączenia JOIN. Wiersze z każdej tabeli są porównywane za pomocą podanego warunku. Zbiór wyjściowy zawiera jedynie wiersze, które spełniają warunek połączenia. Jeśli żadna para wierszy nie spełnia warunku to zbiór pozostanie pusty.
Wszystkie systemy zarządzania bazą danych (RDBMS) posiadają implementację tego rodzaju polecenia JOIN.
-
LEFT JOIN za pomocą metody
joinLeft(tabela, warunek, [kolumny])
.Wszystkie wiersze z tabeli znajdującej się po lewej stronie "wchodzą" do wyniku. Te, które nie mają odpowiadającego wiersza w tabeli znajdującej się po stronie prawej - zostają wypełnione wartościami
NULL
(w kolumnach z prawej tabeli).Wszystkie systemy zarządzania bazą danych (RDBMS) posiadają implementację tego rodzaju polecenia JOIN.
-
RIGHT JOIN za pomocą metody
joinRight(tabela, warunek, [kolumny])
RIGHT JOIN to przeciwieństwo LEFT JOIN. Wszystkie wiersze z tabeli znajdującej się po prawej stronie są umieszczone w wyniku. Te, które nie posiadają odpowiednika w tabeli lewej otrzymują wartości
NULL
w kolumnach z lewej tabeli.Niektóre systemy zarządzania bazą danych (RDBMS) nie wspierają tego typu polecenia JOIN ale generalnie każdy RIGHT JOIN może zostać zaprezentowany jako LEFT JOIN poprzez odwrócenie kolejności dodawania tabel.
-
FULL JOIN za pomocą metody
joinFull(tabela, warunek, [kolumny])
To polecenie jest jak połączenie LEFT JOIN oraz RIGHT JOIN. Wszystkie wiersze z obu tabel są włączane do wyniku. Jeśli dany wiersz nie posiada odpowiednika spełniającego warunek połączenia w drugiej tabeli to w kolumnach z tej tabeli umieszczony jest
NULL
.Niektóre systemy zarządzania bazą danych (RDBMS) nie wspierają tego typu polecenia JOIN.
-
CROSS JOIN za pomocą metody
joinCross(tabela, [kolumny])
.Cross join to iloczyn kartezjański tabel. Każdy wiersz z pierwszej tabeli zostaje połączony z każdym wierszem z tabeli drugiej. Ilość wierszy w zbiorze wynikowym jest równa iloczynowi ilości wierszy w obu tabelach. Poprzez użycie warunku WHERE można ograniczyć wiersze wynikowe przez co cross join może być podobny do składni polecenia join ze standardu SQL-89.
Metoda
joinCross()
nie ma parametru odnoszącego się do warunku połączenia. Niektóre systemy zarządzania bazą danych (RDBMS) nie wspierają tego typu polecenia JOIN. -
NATURAL JOIN za pomocą metody
joinNatural(tabela, [kolumny])
.Polecenie natural join łączy wiersze pod względem wszystkich kolumn, które mają taką samą nazwę w obydwu tabelach. Warunkiem połączenia jest zgodność wartości wszystkich tak samo nazwanych kolumn tabel. Porównywanie wartości na zasadzie niezgodności (różnicy) nie stanowi polecenia natural join. Jedynie polecenia typu natural inner join są zaimplementowane w tym API pomimo tego że standard SQL definiuje też polecenia natural outer join.
Metoda
joinCross()
nie ma parametru odnoszącego się do warunku połączenia.
Oprócz powyższych metod można uprościć zapytania używając metod JoinUsing. Zamiast
podawania pełnego warunku można wybrać nazwę kolumny, na podstawie której
połączenie będzie przeprowadzone a obiekt Zend_Db_Select
dopisze niezbędną część polecenia warunku.
Przykład 245. Przykład użycia metody joinUsing()
// Tworzenie zapytania: // SELECT * // FROM "table1" // JOIN "table2" // ON "table1".column1 = "table2".column1 // WHERE column2 = 'foo' $select = $db->select() ->from('table1') ->joinUsing('table2', 'column1') ->where('column2 = ?', 'foo');
Każda z metod połączenia klasy Zend_Db_Select
ma
odpowiednią metodę 'using'.
-
joinUsing(tabela, [kolumny])
andjoinInnerUsing(tabela, [kolumny])
-
joinLeftUsing(tabela, [kolumny])
-
joinRightUsing(tabela, [kolumny])
-
joinFullUsing(tabela, [kolumny])
Za pomocą metody where()
można określić kryteria
ograniczające ilość wierszy zwracanych przez zapytanie. Pierwszy argument tej
metody to wyrażenie SQL które zostanie użyte w klauzuli
WHERE zapytania SQL.
Przykład 246. Przykład użycia metody where()
// Tworzenie zapytania: // SELECT product_id, product_name, price // FROM "products" // WHERE price > 100.00 $select = $db->select() ->from('products', array('product_id', 'product_name', 'price')) ->where('price > 100.00');
Uwaga
Wyrażenia w metodach where()
lub
orWhere()
nie zostają umieszczone w cudzysłowach.
Jeśli nazwa kolumny tego wymaga należy użyć metody
quoteIdentifier()
podczas tworzenia parametru warunku.
Drugi argument metody where()
jest opcjonalny. Stanowi on
wartość umieszczaną w warunku. Zend_Db_Select
ogranicza tą
wartość cudzysłowami i za jej pomocą podmienia symbol znaku zapytania
("?") w warunku.
Przykład 247. Przykład użycia parametru w metodzie where()
// Tworzenie zapytania: // SELECT product_id, product_name, price // FROM "products" // WHERE (price > 100.00) $minimumPrice = 100; $select = $db->select() ->from('products', array('product_id', 'product_name', 'price')) ->where('price > ?', $minimumPrice);
Drugi parametr metody where()
przyjmuje również
tablicę w przypadku gdy używa się operatora IN.
Przykład 248. Przykład użycia tablicy w metodzie where()
// Tworzenie zapytania: // SELECT product_id, product_name, price // FROM "products" // WHERE (product_id IN (1, 2, 3)) $productIds = array(1, 2, 3); $select = $db->select() ->from('products', array('product_id', 'product_name', 'price')) ->where('product_id IN (?)', $productIds);
Metoda where()
może być wywoływana wiele razy dla jednego
obiektu Zend_Db_Select
. Zapytanie wynikowe łączy wszystkie
warunki używając wyrażenia AND.
Przykład 249. Przykład wywołania metody where() wiele razy
// Tworzenie zapytania: // SELECT product_id, product_name, price // FROM "products" // WHERE (price > 100.00) // AND (price < 500.00) $minimumPrice = 100; $maximumPrice = 500; $select = $db->select() ->from('products', array('product_id', 'product_name', 'price')) ->where('price > ?', $minimumPrice) ->where('price < ?', $maximumPrice);
Jeśli istnieje potrzeba połączenia warunków za pomocą wyrażenia
OR należy użyć metody orWhere()
.
Można jej używać w taki sam sposób jak metody where()
.
W wynikowym poleceniu warunki zostaną połączone wyrażeniem OR
zamiast AND.
Przykład 250. Przykład użycia metody orWhere()
// Tworzenie zapytania: // SELECT product_id, product_name, price // FROM "products" // WHERE (price < 100.00) // OR (price > 500.00) $minimumPrice = 100; $maximumPrice = 500; $select = $db->select() ->from('products', array('product_id', 'product_name', 'price')) ->where('price < ?', $minimumPrice) ->orWhere('price > ?', $maximumPrice);
Zend_Db_Select
automatycznie umieszcza wyrażenia podane
do metod where()
lub orWhere()
w nawiasach. Dzięki temu kolejność wykonywania działań logicznych nie spowoduje
nieoczekiwanych rezultatów.
Przykład 251. Przykład umieszczania wyrażeń w nawiasach
// Tworzenie zapytania: // SELECT product_id, product_name, price // FROM "products" // WHERE (price < 100.00 OR price > 500.00) // AND (product_name = 'Apple') $minimumPrice = 100; $maximumPrice = 500; $prod = 'Apple'; $select = $db->select() ->from('products', array('product_id', 'product_name', 'price')) ->where("price < $minimumPrice OR price > $maximumPrice") ->where('product_name = ?', $prod);
W powyższym przykładzie zapytanie bez nawiasów przyniosłoby inny rezultat ponieważ
AND ma wyższy priorytet niż OR.
Dzięki nawiasom Zend_Db_Select
sprawia, że każde
wywołanie metody where()
łączy zawarte w niej warunki
z wyższym priorytetem niż AND który łączy poszczególne warunki.
W SQL, klauzula GROUP BY pozwala na ograniczenie wierszy wyników zapytania do jednego wiersza na każdą unikalną wartość znalezioną w kolumnie podanej przy klauzuli GROUP BY.
Aby określić kolumny używane do podzielenia wyników na grupy w
Zend_Db_Select
należy użyć metody
group()
.
Jako argument podaje się kolumnę lub tablicę kolumn, które mają trafić
do klauzuli GROUP BY.
Przykład 252. Przykład użycia metody group()
// Tworzenie zapytania: // SELECT p."product_id", COUNT(*) AS line_items_per_product // FROM "products" AS p JOIN "line_items" AS l // ON p.product_id = l.product_id // GROUP BY p.product_id $select = $db->select() ->from(array('p' => 'products'), array('product_id')) ->join(array('l' => 'line_items'), 'p.product_id = l.product_id', array('line_items_per_product' => 'COUNT(*)')) ->group('p.product_id');
Podobnie jak w przypadku metody from()
w argumencie można
używać aliasów tabel a nazwy są umieszczane w cudzysłowach jako identyfikatory
chyba że łańcuch znaków zawiera nawiasy lub jest
obiektem Zend_Db_Expr
.
W SQL, klauzula HAVING
wprowadza
ograniczenie w stosunku do grup wierszy. Jest to podobne do sposobu w jaki klauzula
WHERE
ogranicza wiersze ogólnie. Te klauzule są różne ponieważ
warunki WHERE
są oceniane prze definiowaniem grup, podczas gdy
warunki HAVING
nakładane są po uformowaniu grup.
W Zend_Db_Select
można określić warunki dotyczące
grup wierszy za pomocą metody having()
.
Użycie jej jest podobne do metody where()
. Pierwszy
argument to string zawierający wyrażenie SQL. Opcjonalny
drugi argument to wartość używana do zamienienia pozycyjnych parametrów w
wyrażeniu SQL. Wyrażenia umieszczone w wielu wywołaniach
metody having()
są łączone za pomocą operatora
AND lub OR - jeśli zostanie użyta metoda
orHaving()
.
Przykład 253. Przykład użycia metody having()
// Tworzenie zapytania: // SELECT p."product_id", COUNT(*) AS line_items_per_product // FROM "products" AS p JOIN "line_items" AS l // ON p.product_id = l.product_id // GROUP BY p.product_id // HAVING line_items_per_product > 10 $select = $db->select() ->from(array('p' => 'products'), array('product_id')) ->join(array('l' => 'line_items'), 'p.product_id = l.product_id', array('line_items_per_product' => 'COUNT(*)')) ->group('p.product_id') ->having('line_items_per_product > 10');
Uwaga
W metodach having()
oraz
orHaving()
nie jest stosowane umieszczanie
identyfikatorów w cudzysłowach. Jeśli nazwa kolumny tego wymaga należy użyć
metody quoteIdentifier()
podczas tworzenia parametru
warunku.
W SQL, klauzula ORDER BY
określa jedną bądź więcej
kolumn lub wyrażeń według których zbiór wynikowy jest posortowany. Jeśli poda się
wiele kolumn to sortowanie odbywa się w pierwszej kolejności na podstawie wcześniej
podanej kolumny. Jeśli istnieją wiersze o takiej samej wartości w danej kolumnie
to do sortowania używana jest kolejna klumna klauzuli ORDER BY
.
Domyślny kierunek sortowania to od najmniejszej wartości do największej.
Można sortować w przeciwnym kierunku przez użycie słowa kluczowego
DESC
po nazwie kolumny sortowania.
W Zend_Db_Select
można użyć metody
order()
i podać kolumnę lub tablicę kolumn
według których sortowanie ma przebiegać. Każdy z elementów tablicy
powinien być łańcuchem znaków określającym kolumnę. Opcjonalnie można dodać
słowa kluczowe ASC
lub DESC
oddzielone od kolumny spacją.
Podobnie jak przy metodach from()
oraz
group()
nazwy kolumn są otaczane cudzysłowami, chyba że
zawierają nawiasy lub są obiektami klasy Zend_Db_Expr
.
Przykład 254. Przykład użycia metody order()
// Tworzenie zapytania: // SELECT p."product_id", COUNT(*) AS line_items_per_product // FROM "products" AS p JOIN "line_items" AS l // ON p.product_id = l.product_id // GROUP BY p.product_id // ORDER BY "line_items_per_product" DESC, "product_id" $select = $db->select() ->from(array('p' => 'products'), array('product_id')) ->join(array('l' => 'line_items'), 'p.product_id = l.product_id', array('line_items_per_product' => 'COUNT(*)')) ->group('p.product_id') ->order(array('line_items_per_product DESC', 'product_id'));
Niektóre systemy zarządzania bazą danych (RDBMS) rozszerzają
SQL za pomocą klauzuli LIMIT
. Za jej
pomocą można ograniczyć ilość wierszy zwracanych w zapytaniu do podanej ilości.
Można również określić ilość wierszy, która ma zostać opuszczona przed
rozpoczęciem zwracania wyników zapytania. Dzięki temu można w łatwy sposób
uzyskać podzbiór ze zbioru wynikowego. Może to być przydatne
np. przy wyświetlaniu rezultatów zapytania z podziałem na strony.
W Zend_Db_Select
można użyć metody
limit()
aby określić ilość wierszy do zwrócenia oraz do
opuszczenia. Pierwszy argument metody to ilość wierszy
jaka maksymalnie ma zostać zwrócona. Drugi argument to ilość
wierszy do opuszczenia.
Przykład 255. Przykład użycia metody limit()
// Tworzenie zapytania: // SELECT p."product_id", p."product_name" // FROM "products" AS p // LIMIT 10, 20 // Equivalent to: // SELECT p."product_id", p."product_name" // FROM "products" AS p // LIMIT 20 OFFSET 10 $select = $db->select() ->from(array('p' => 'products'), array('product_id', 'product_name')) ->limit(20, 10);
Uwaga
Polecenie LIMIT
nie jest wspierane przez wszystkie rodzaje
baz danych. Niektóre z nich wymagają innej składni dla uzyskania
podobnego efektu. Każda z klas Zend_Db_Adapter_Abstract
zawiera metodę tworzącą polecenie SQL odpowiednie dla danego
RDBMS.
Można użyć metody limitPage()
jako alternatywy
do określania ilości wierszy do zwrotu i do pominięcia. Ta metoda pozwala
na podzielenie zbioru wynikowego na wiele podzbiorów o stałej wielkości
i zwrócenie jednego z nich.
Innymi słowy należy określić długość jednej "strony" z wynikami zapytania
oraz liczbę porządkową określającą stronę, która ma zostać zwrócona.
Numer strony stanowi pierwszy argument metody
limitPage()
a długość strony to drugi argument.
Obydwa argumenty są wymagane - nie mają wartości domyślnych.
Przykład 256. Przykład użycia metody limitPage()
// Tworzenie zapytania: // SELECT p."product_id", p."product_name" // FROM "products" AS p // LIMIT 10, 20 $select = $db->select() ->from(array('p' => 'products'), array('product_id', 'product_name')) ->limitPage(2, 10);
Metoda distinct()
pozwala na dodanie słowa
kluczowego DISTINCT
do zapytania SQL.
Przykład 257. Przykład użycia metody distinct()
// Tworzenie zapytania: // SELECT DISTINCT p."product_name" // FROM "products" AS p $select = $db->select() ->distinct() ->from(array('p' => 'products'), 'product_name');
Metoda forUpdate()
pozwala na dodanie słowa
kluczowego FOR UPDATE do zapytania SQL.
Przykład 258. Przykład użycia metody forUpdate()
// Tworzenie zapytania: // SELECT FOR UPDATE p.* // FROM "products" AS p $select = $db->select() ->forUpdate() ->from(array('p' => 'products'));
Z Zend_Db_Select
można łączyć zapytania poprzez
przekazanie tablicy obiektów Zend_Db_Select
lub łańcuchów zapytań SQL
do metody union()
.
Jako drugi parametr można podać stałe
Zend_Db_Select::SQL_UNION
lub Zend_Db_Select::SQL_UNION_ALL
aby określić rodzaj połączenia jaki chce się uzyskać.
Przykład 259. Przykład użycia metody union()
$sql1 = $db->select(); $sql2 = "SELECT ..."; $select = $db->select() ->union(array($sql1, $sql2)) ->order("id");
Poniższa część opisuje jak wywołać zapytanie zawarte w obiekcie
Zend_Db_Select
.
Zapytanie zawarte w obiekcie Zend_Db_Select
można wywołać
poprzez podanie obiektu jako pierwszego argumentu
metody query()
obiektu Zend_Db_Adapter_Abstract
.
Zalecane jest używanie obiektów Zend_Db_Select
zamiast łańcuchów znaków z zapytaniem.
Metoda query()
w zależności od typu adaptera bazy danych
zwraca obiekt klasy Zend_Db_Statement
lub PDOStatement.
Przykład 260. Przykład użycia metody query() adaptera bazy danych
$select = $db->select() ->from('products'); $stmt = $db->query($select); $result = $stmt->fetchAll();
Jako alternatywny sposób w stosunku do użycia
metody query()
adaptera bazy danych,
można użyć metody o takiej samej nazwie obiektu
Zend_Db_Select
. Obydwie metody zwracają obiekt klasy
Zend_Db_Statement
lub PDOStatement w zależności od typu
użytego adaptera.
Przykład 261. Przykład użycia metody obiektu Zend_Db_Select
$select = $db->select() ->from('products'); $stmt = $select->query(); $result = $stmt->fetchAll();
Jeśli niezbędny jest dostęp do polecenia SQL w postaci łańcucha
znaków zawartego w obiekcie Zend_Db_Select
, należy użyć
metody __toString()
.
Przykład 262. Przykład użycia metody __toString()
$select = $db->select() ->from('products'); $sql = $select->__toString(); echo "$sql\n"; // Wyjściowy string: // SELECT * FROM "products"
Ta część opisuje inne metody klasy Zend_Db_Select
, które nie
zostały wymienione wcześniej: getPart()
oraz
reset()
.
Metoda getPart()
zwraca postać łańcucha
znaków odpowiadającą jednej części polecenia SQL.
Można użyć tej metody aby uzyskać tablicę warunków klauzuli
WHERE
, tablicę kolumn (lub wyrażeń)
zawartych w liście SELECT
albo wartości ilości wierszy
klauzuli LIMIT
.
Wartością zwracaną nie jest string zawierający składnię SQL. Zamiast tego zwracana jest wewnętrzna postać danych, co przeważnie oznacza tablicę zawierającą wartości i wyrażenia. Każda część zapytania ma inną strukturę.
Jedynym argumentem metody getPart()
jest łańcuch znaków
identyfikujący żądaną część zapytania. String 'from'
odpowiada części
obiektu Zend_Db_Select
, która przechowuje informacje
o tabelach (włączając w to tabele połączone) w klauzuli FROM
.
Klasa Zend_Db_Select
definiuje stałe, których można użyć
jako oznaczeń zapytania SQL. Dozwolone jest stosowanie tych
stałych bądź nazw dosłownych.
Tabela 62. Stałe używane przez metody getPart() oraz reset()
Stała | Wartość dosłowna |
---|---|
Zend_Db_Select::DISTINCT |
'distinct' |
Zend_Db_Select::FOR_UPDATE |
'forupdate' |
Zend_Db_Select::COLUMNS |
'columns' |
Zend_Db_Select::FROM |
'from' |
Zend_Db_Select::WHERE |
'where' |
Zend_Db_Select::GROUP |
'group' |
Zend_Db_Select::HAVING |
'having' |
Zend_Db_Select::ORDER |
'order' |
Zend_Db_Select::LIMIT_COUNT |
'limitcount' |
Zend_Db_Select::LIMIT_OFFSET |
'limitoffset' |
Przykład 263. Przykład użycia metody getPart()
$select = $db->select() ->from('products') ->order('product_id'); // Można użyć dosłownej nazwy żądanej części $orderData = $select->getPart( 'order' ); // Alternatywnie można posłużyć się stałą $orderData = $select->getPart( Zend_Db_Select::ORDER ); // Wartość zwrotna może nie być stringiem a tablicą. // Każda część zapytania może mieć inną strukturę. print_r( $orderData );
Metoda reset()
umożliwia wyczyszczenie podanej części
lub całości (jeśli nie poda się argumentu) zapytania SQL.
Jedyny argument jest opcjonalny. Można podać w nim część zapytania przeznaczoną
do wyczyszczenia używając tych samych łańcuchów co w przypadku metody
getPart()
. Podana część zapytania jest ustawiana w stan
domyślny.
Jeśli nie poda się parametru, metoda reset()
ustawia
wszystkie części zapytania w ich stan domyślny. Przez to używany obiekt
Zend_Db_Select
odpowiada nowemu obiektowi, tak jakby
został on dopiero utworzony.
Przykład 264. Przykład użycia metody reset()
// Tworzenie zapytania: // SELECT p.* // FROM "products" AS p // ORDER BY "product_name" $select = $db->select() ->from(array('p' => 'products') ->order('product_name'); // Zmienione wymagania, sortowanie wg. innej kolumny: // SELECT p.* // FROM "products" AS p // ORDER BY "product_id" // Wyczyszczenie jednej części aby można było ją ponownie zdefiniować $select->reset( Zend_Db_Select::ORDER ); // Podanie nowej kolumny sortowania $select->order('product_id'); // Wyczyszczenie wszystkich części zapytania $select->reset();