INT(11) kontra INT
Na wielu forach i grupach widzę, iż często w kodzie zapytań tabel jest INT(11). Zdaję sobie sprawę, iż czasami jest to spowodowane skopiowaniem zapytania z jakiegoś programu, który automatycznie nam z jakiegoś powodu coś takiego dodaje. Częściej jednak jest to stosowane przez programistów z premedytacją wynikającą poprostu z niewiedzy. Postaram się tutaj tę sprawę wyjaśnić.
Weźmy jako przykład poniższy kod tworzący tabelę autorstwa pana X
create table `test` (
`ID` int(11) unsigned NOT NULL auto_increment,
`TYPE` int(1) unsigned NOT NULL default 0 COMMENT 'typy. mozliwe wartosci 1,2,3,4',
`BLABLA` varchar(64) NOT NULL default '' COMMENT 'blabla',
`PRODUCTS_COUNT` int(5) unsigned NOT NULL default 0 COMMENT 'liczba produktów. Nie przekroczy 50tys',
PRIMARY KEY (`ID`),
KEY `TYPE` (`TYPE`)
) ENGINE=InnoDB;
Jak widzicie wszystkie pola liczbowe są typu INT. Przy każdym z pól określono w nawiasie jakąś liczbę. Patrząc po tych liczbach, można wnioskować, iż autor tego zapisu chciał ograniczyć zakres pola. I tak np. (1) ma oznaczać liczby jednocyfrowe, czyli do 9, a zapis (5) ma niby oznaczać liczby 5-cio cyfrowe.
Otóż autor tego zapytania jest w błędzie. Liczby w nawiasach przy typach z rodziny INT służą tylko i wyłącznie w przypadku, gdy używamy ZEROFILL. A że opcji tej w większości przypadków się nie używa (sam jej raz przez pomyłkę użyłem a potem bardzo żałowałem) to nie bedę na jej temat nic pisał, uznając na potrzeby tego artykułu, że jej w ogóle nie ma.
Tak więc zapis INT(1) nie ogranicza nas w żaden sposób do maksymalnie liczby 9 i w żaden sposób taka kolumna nie będzie zajmowała jednego bajta tylko nadal 4 jak każdy INT. Jeśli chcemy ograniczyć nasze pole do jednego bajta to poprostu użyjmy TINYINT. Jeśli chcemy ograniczyć kolumnę do 50tys (a konkretnie 65535) to używamy nie INT(5) tylko SMALLINT. Dopiero takie użycie typów kolumn ogranicza ilość bajtów zajmowanych przez pole i dopiero wówczas mamy optymalnie pisany kod pod względem rozmiarów pól liczbowych
Ostatecznie więc nasze zapytanie tworzące tabelę powinno wyglądać tak:
create table `test` (
`ID` int unsigned NOT NULL auto_increment,
`TYPE` tinyint unsigned NOT NULL default 0 COMMENT 'typy. mozliwe wartosci 1,2,3,4',
`BLABLA` varchar(64) NOT NULL default '' COMMENT 'blabla',
`PRODUCTS_COUNT` smallint unsigned NOT NULL default 0 COMMENT 'liczba produktów. Nie przekroczy 50tys',
PRIMARY KEY (`ID`),
KEY `TYPE` (`TYPE`)
) ENGINE=InnoDB;
Przy okazji zwróćcie uwagę na unsigned, które jest przy każdym polu liczbowym. Jeśli pole będzie przyjmować tylko wartości dodatnie (i zero) to warto dla tego pola zaznaczyć, iż to pole właśnie takie będzie. Chociażby po to, że przez dodanie unsigned zwiększa nam się zakres przyjmowanych wartości bez zmiany ilości zajmowanych bajtów. I tak np. TINYINT może osiągnąć max 127, zaś UNSIGNED TINYINT już 255. Analogicznie pozostałe typy liczbowe.