PHP/Zarządzanie rekordami: Różnice pomiędzy wersjami

Usunięta treść Dodana treść
Zyx (dyskusja | edycje)
utworzenie
 
Zyx (dyskusja | edycje)
Linia 88:
 
=== Zamiana rekordów ===
Bardzo przydatną operacją jest automatyczne podmienianie rekordów. Polega ono na tym, że jeżeli wstawiamy rekord A do tabeli, w której znajduje się już rekord B o podobnym kluczu, jest on automatycznie nadpisywany przez system. MySQL posiada dwa zapytania, które są pomocne przy podmienianiu rekordów, jednak zanim się do nich dobierzemy, musimy utworzyć sobie nową tabelę.
 
Aby MySQL mógł zdecydować, czy rekord należy nadpisać, musi wiedzieć, które pola tabeli przechowują wartości unikalne, czyli takie, że nie można znaleźć dwóch rekordów o identycznej wartości w tym polu. Wiemy już, że taką właściwość powinno mieć pole ''id'', i rzeczywiście - informujemy o tym bazę, tworząc dla niego tzw. klucz główny (''PRIMARY KEY''). Dba on o to, aby wartości się nie powtarzały. Jednak klucz ten można nałożyć tylko na jedno pole naraz, a operacja REPLACE przy rekordach mających z definicji nie tylko unikalne, ale też nadawane automatycznie ID, zbyt dużego sensu nie ma. Dlatego istnieje indeks ''UNIQUE'', który może być nałożony na dowolnie dużo pól i także sprawi, że zyskają one tę właściwość. Aby pokazać to w praktyce, utwórzmy tabelę dla elektronicznego słownika (w wersji uproszczonej, oczywiście):
{{TODO|Opisać zapytania ''REPLACE''}}
 
<nowiki>CREATE TABLE `slownik` (
`id` MEDIUMINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`haslo` VARCHAR(40) NOT NULL,
`znaczenie` VARCHAR(255) NOT NULL,
UNIQUE(
`haslo`
)
) ENGINE = MYISAM;</nowiki>
 
Mamy tu trzy pola: ''id'', ''haslo'' oraz ''znaczenie''. ID służy jedynie celom administracyjnym (wyszukiwanie względem liczby jest zawsze szybsze, niż względem tekstu). Dla użytkownika naszego słownika najważniejsze będzie jednak pole ''haslo'', które także powinno mieć wartości unikalne. Indeks UNIQUE tworzymy tak, jak na przykładzie: po liście pól wstawiamy słowo kluczowe ''UNIQUE'', w którym w nawiasie wymieniamy pola posiadające taką właściwość.
 
Jeżeli jesteśmy administratorami słownika, mogącymi dodawać do niego nowe hasła, unikalność obsługiwana przez MySQL ma dla nas duże znaczenie. Kiedy będzie w nim bowiem już dużo słów, ze zwykłej pomyłki możemy spróbować dodać po raz drugi to samo. Tradycyjne polecenie ''INSERT'' zareagowałoby błędem powiadamiającym, że próbujemy utworzyć rekord, w którym powtarza się unikalna wartość. Dlatego możemy zastosować inne zapytanie: ''REPLACE''. Wstawiamy nim pierwsze trzy hasła:
 
<nowiki>REPLACE slownik (haslo, znaczenie) VALUES('tree', 'drzewo');
REPLACE slownik (haslo, znaczenie) VALUES('house', 'dom (budynek)');
REPLACE slownik (haslo, znaczenie) VALUES('sign', 'znak');</nowiki>
 
W tym momencie działają one identycznie, jak znane nam zapytanie ''INSERT'' (mają nawet podobną składnię, chociaż dozwolone jest stosowanie także składni polecenia ''UPDATE''). Możemy zapytać się, jaka jest zawartość tabeli i pokażą nam się wszystkie trzy wymienione rekordy. Spróbujmy teraz po raz drugi dodać istniejące hasło (np. ''tree''):
 
<nowiki>REPLACE slownik (haslo, znaczenie) VALUES('tree', 'drzewo, drzewko');
Query OK, 2 rows affected (0.00 sec)</nowiki>
 
Zwróć uwagę, jaki komunikat kontrolny pokazał MySQL: zmodyfikowane zostały ''dwa'' rekordy. Wyświetlmy zawartość tabeli: okazuje się, że pierwotny rekord ''tree'' (z ID równym 1) został skasowany, a na jego miejscu pojawił się nowy, któremu serwer nadał ID 4. Mamy zatem sformułowaną zasadę działania polecenia ''REPLACE'':
# Spróbuj dodać nowy rekord.
# Jeśli nie powiedzie się z powodu duplikacji unikalnej wartości, usuń stary rekord powodujący kolizję.
# I ponownie dodaj nowy rekord.
 
{{Uwaga|Polecenie ''REPLACE'' nie jest częścią standardu ANSI SQL, dlatego najprawdopodobniej nie będzie zaimplementowane na bazach innych, niż MySQL!}}
 
''REPLACE'' nie jest jedynym poleceniem realizującym zamianę rekordów. Od wersji 4.1.0 MySQL obsługuje także rozszerzenie zapytania ''INSERT'' o element ''ON DUPLICATE KEY UPDATE'', zgodne ze standardem ANSI SQL. Dzięki niemu nie trzeba kasować kolidującego rekordu, lecz jedynie nadpisać jego wartości nowymi. Dodajmy ponownie jakieś istniejące hasło:
 
<nowiki>INSERT INTO slownik (haslo, znaczenie) VALUES('house', 'dom (budynek), rodzaj obiektu mieszkalnego.')
ON DUPLICATE KEY UPDATE znaczenie=VALUES(znaczenie);
Query OK, 2 rows affected (0.02 sec)</nowiki>
 
Pierwsza część tego zapytania to znany nam już dobrze ''INSERT''. Próbuje on wstawić nowy rekord. Kiedy jednak zajdzie kolizja, do akcji wkracza nowa część: ''ON DUPLICATE KEY UPDATE'', w której możemy zdefiniować sposób nadpisania starego rekordu według składni ''nazwa_pola = nowa_wartosc, nazwa_pola = nowa_wartosc, ...''. Możemy tutaj ustawiać statyczne wartości, np. ''pole = 1'', lub też odwołać się do wartości pola, która miała być wstawiona poleceniem ''INSERT''. Służy do tego funkcja ''VALUES(nazwa_pola)''. Wykorzystaliśmy ją w powyższym przykładzie, aby wprowadzić nową definicję hasła na miejsce starej.
 
Dzięki możliwości nadpisywania istniejących rekordów, nasza baza stanie się bardziej elastyczna, a my nie będziemy musieli samodzielnie realizować sprawdzania, czy przypadkiem nie spowodujemy jakiejś kolizji. Jeżeli jednak zamierzamy napisać aplikację, która będzie mogła pracować z różnymi systemami DB, musimy sprawdzić, czy wszystkie one obsługują podaną operację, lub napisać dla każdej z nich części kodu osobno.
 
=== Błędy w zapytaniach ===