Odejmowanie w MySQL’u wydaje się być proste. No bo jaka może być filozofia w odejmowaniu jednej liczby od drugiej, zwłaszcza że obie są typu INT? Jeden przypadek sprawił, że jednak wcale nie jest tak do końca oczywiste.
Załóżmy, że mamy w bazie dwie tabelki X i Y:
Chcielibyśmy w jednym zapytaniu zmniejszać kolumnę “stock” z tabeli Y o wartość “amount” z tabeli X. W sumie co to za filozofia? (zakładamy, że stock może być ujemny):
Zapytanie działa, cieszymy się, ale co w przypadku kiedy “amount” jest większy od “stock”? Okazuje się, że MySQL zamiast zapisać wartość ujemną do pola, które zdefiniowaliśmy jako SIGNED, przekręca licznik i wstawia nam 7-cyfrową wartość dodatnią! Powodem tej sytuacji jest bit znakowy, wykorzystywany w polach typu SIGNED i jego brak w polu typu UNSIGNED. Aby zapytanie działało dokładnie tak jakbyśmy tego chcieli, musimy użyć funkcji CAST i wtedy będziemy operować na dwóch identycznych typach.
Ot taka ciekawostka, której można się nie spodziewać, a jednak jak już się na to trafi, to wszystko wydaje się oczywiste :)
Ostatnio w jednym z naszych projektów potrzebowałem wyciągnąć z bazy produktów po jednym produkcie według item_code. Miałem listę tych kodów do wyciągnięcia, powiedzmy że obejmowały zakres od 1809 do 1820. Banał.
SELECT * FROM items WHERE item_code = 1809;
I niespodzianka - 3 wyniki, ich item_code’y to 1809, 1809CI, 1809S. Oczywiście wywaliło to od razu skrypt, bo zamiast tablicy asocjacyjnej z kolumnami dla jednego wiersza, dostałem tablicę 3-elementową, po jednym elemencie dla każdego wiersza.
Krótkie wytłumaczenie, jeżeli jeszcze się ktoś nie domyślił - akurat ta baza jest na tyle durna, że item_code to pole varchar a nie int. Więc jeżeli w warunku jest item_code = 1809 a nie item_code = ‘1809′, to MySQL rzutuje całą kolumnę na integery, przez co do porównania wywala litery z końca kodu i nagle pasują mu aż 3 wpisy. Podanie szukanego kodu w uszach jako stringu daje spodziewany jeden jedyny rekord z kodem 1809.
Więc tylko ku przestrodze - nie wyszukujcie integerów w kolumnach tekstowych!