Типови података
NAPOMENA: Ovaj dokument je poglavlje iz knjige “The InterBase World” koju su napisali Aleksej Kovyazin i Serg Vostrikov.
Uprkos činjenici da su tipovi podataka detaljno opisani u dokumentaciji (videti [1, poglavlje 4.), neophodno je razmotriti niz pojmova koji će se često koristiti u narednim poglavljima ove knjige. Pored opštih informacija, biće razmotreni i primeri korišćenja tipova podataka u InterBase bazama podataka, kao i preporuke o njihovom korišćenju i konverziji. Detaljno ćemo razmotriti razlike u tipovima podataka koje postoje u 1. i 3. dijalektu InterBase baze podataka.
O podacima
Tipovi podataka su osnovni elementi svakog programskog jezika ili bilo kog DBMS servera. InterBase nije izuzetak. Kada kažemo da baza podataka čuva neke informacije, moramo shvatiti da se te informacije ne mogu čuvati na jednom mestu. Naprotiv, podaci moraju biti razvrstani i smešteni na svoju “policu”. Tipovi podataka definišu šta se može staviti na određenu “policu”, a šta ne. Kada govorimo o “polici”, pre svega mislimo na polja tabela baze podataka (videti poglavlje “Tabele. Primarni ključevi i generatori” (1. deo)), kao i na promenljive unutar okidača i procedura itd. Svaki tip podataka ima skup operacija koje se mogu izvršiti nad vrednostima tog tipa. Zato je važno odabrati pravi tip podataka prilikom projektovanja baze podataka. To će pomoći da se izbegnu mnogi problemi prilikom razvoja klijentskih programa. U InterBase-u postoji 12 tipova podataka koji mogu zadovoljiti zahteve programera u pogledu čuvanja podataka. Ovi tipovi su uslovno podeljeni u sledećih 6 grupa:
- za čuvanje celih brojeva - INTEGER i SMALLINT;
- za čuvanje realnih brojeva - FLOAT i DOUBLE PRECISION;
- za čuvanje brojeva sa fiksnom preciznošću - NUMERIC i DECIMAL;
- za čuvanje datuma, vremena i vremenske oznake - DATE, TIME i TIMESTAMP;
- za čuvanje znakova - CHARACTER (u skraćenom obliku - CHAR) i VARYING CHARACTER (VARCHAR);
- za čuvanje dinamički proširivih podataka - BLOB
Pored toga, moguće je definisati nizove vrednosti primitivnih tipova, tj. svih navedenih tipova osim BLOB-a.
Većina InterBase tipova podataka odgovara tipovima definisanim u SQL92 standardu, međutim, pored toga postoje i njihove sopstvene specifičnosti - nizovi primitivnih tipova podataka i BLOB. Nizovi u InterBase-u mogu sadržati skup podataka istog tipa u jednom polju. Na primer, možemo definisati niz vrednosti INTEGER tipa. Nizovi mogu imati više dimenzija. BLOB tip podataka je dinamički proširiv tip podataka, čije se ime često dešifruje kao Binary Large OBject. Treba reći da je BLOB izum InterBase programera koji se kasnije proširio i ustalio u svim savremenim SQL-serverima.
Sintaksa definisanja tipova podataka
Tipovi podataka se koriste za opisivanje polja u tabelama, promenljivih u okidačima i procedurama. Uobičajena sintaksa za definisanje svih mogućih tipova podataka u InterBase-u data je u nastavku.
< tip_podatka> =
{SMALLINT | INTEGER | FLOAT | DOUBLE PRECISION}[ ]
| {DATE | TIME | TIMESTAMP} [ ]
| {DECIMAL | NUMERIC} [( preciznost [, skala])] [ ]
| {CHAR | CHARACTER | CHARACTER VARYING | VARCHAR} [( int)]
[ ] [CHARACTER SET ime_znakova]
| {NCHAR | NATIONAL CHARACTER | NATIONAL CHAR}
[VARYING] [( int)] [ ]
| BLOB [SUB_TYPE { int | ime_podtipa}] [SEGMENT SIZE int]
[CHARACTER SET ime_znakova]
| BLOB [(dužina_segmenta [, podtip])]
Karakteristike tipova podataka kao što su veličina, preciznost i opseg mogućih vrednosti detaljno su opisane u tabeli 4.1 u [1., stoga se ovde nećemo ponavljati. Sada ćemo ukratko razmotriti glavne specifičnosti tipova podataka i fokusirati se na njihovu moguću primenu.
Celobrojni tipovi
SMALLINT i INTEGER spadaju u cele brojeve. Treba reći da SMALLINT predstavlja osakaćenu verziju INTEGER-a. Njegova dužina je 2 bajta, za razliku od 4 koliko je predviđeno za čuvanje INTEGER-a. Obično ne treba štedeti na prostoru na disku. Iz tog razloga, bolje je koristiti INTEGER tip za čuvanje celobrojnih vrednosti.
Oblast primene celobrojnih tipova je očigledna: neophodni su za polja koja sadrže samo cele brojeve - za čuvanje brojača, brojeva itd. Obično INTEGER tip imaju i polja koja sadrže primarne ključeve.
Realni tipovi podataka
FLOAT i DOUBLE PRECISION tipovi spadaju u realne (takođe se nazivaju brojevi sa pokretnim zarezom). Prvo, želim da upozorim čitaoca na korišćenje FLOAT tipa - njegova preciznost nije dovoljna za čuvanje većine razlomljenih vrednosti. Posebno se ne preporučuje čuvanje novčanih vrednosti u njemu - u FLOAT tipu promenljivih greške zaokruživanja se vrlo brzo pojavljuju i to može iznenaditi računovođu prilikom izračunavanja. Najbolji način za čuvanje brojeva sa pokretnim zarezom (na primer, u računovodstvenim sistemima i sistemima za naučna izračunavanja) u bazi podataka je čuvanje u DOUBLE PRECISION tipu.
Treba uzeti u obzir da u 3. dijalektu InterBase-a postoji mehanizam za čuvanje tipova sa fiksnom tačkom od 64 bajta. Ovaj mehanizam se koristi za čuvanje novčanih vrednosti. Korišćenje ovih tipova obezbeđuje najbolju preciznost.
Tipovi podataka sa fiksnom tačkom
NUMERIC i DECIMAL spadaju u ove tipove podataka. Pitanje o razlici između NUMERIC i DECIMAL se vrlo često postavlja. Oba ova tipa imaju identičan broj cifara - od 1 do 18 znakova, identičnu preciznost - od nule do broja cifara.
Podsetimo se da je: broj cifara ukupan broj cifara, a preciznost - broj znakova posle zareza.
Najzanimljivije je da se ovi tipovi razlikuju u maksimalnom broju cifara prema dokumentaciji, ali zapravo su realizovani praktično jednako i nema razlike između njih.
To možete lako proveriti pokretanjem uslužnog programa isql i izvršavanjem dole navedenog niza radnji. Kreiramo tabelu sledećeg izgleda:
SQL> CREATE TABLE test (
CON> Num_field NUMERIC(15,2),
CON> Dec_field DECIMAL(15,2));
Zatim dajemo komandu za prikaz strukture tabele:
SQL> show tables test;
I vidimo sledeće
NUM_FIELD NUMERIC(15, 2) Nullable
DEC_FIELD NUMERIC(15, 2) Nullable
Kao što vidite, InterBase obaveštava da obe date kolone imaju NUMERIC tip. Razlozi ovakvog ponašanja leže u realizaciji tipova podataka sa fiksnom tačkom. Stvar je u tome da InterBase ima samo tri mehanizma za čuvanje bilo kog celobrojnog izraza, i svi tipovi, kako god da se zovu, realizovani su prema ovim varijantama.
Evo tabele iz [1., koja ilustruje kako se različiti celobrojni tipovi (tabela 1.1) čuvaju. Kao što vidite, čuvanje podataka u 3. dijalektu je različito za brojeve sa velikim brojem cifara:
Tabela 1.1. Čuvanje brojeva sa fiksnom tačkom
| Broj cifara | Dijalekt 1 | Dijalekt 3 |
|---|---|---|
| od 1 do 4 | SMALLINT za NUMERIC INTEGER za DECIMAL |
SMALLINT |
| od 5 do 9 | INTEGER | INTEGER |
| od 10 do 18 | DOUBLE PRECISION | INT64 |
Sada možemo sa sigurnošću reći koje su glavne razlike između NUMERIC i DECIMAL tipova: u slučaju definisanja polja (ili promenljive) sa malim brojem cifara (do četiri), prvi se čuva kao 2-bajtni celi broj SMALLINT, a drugi - kao 4-bajtni INTEGER. Dakle, ako je broj cifara veći od četiri, DECIMAL i NUMERIC tipovi će biti ekvivalentni.
Obratite pažnju na razliku u realizaciji tipova sa velikim brojem cifara u prvom i trećem dijalektu. U prvom dijalektu, broj sa fiksnom tačkom se pretvarao iz celog u realni, gde su se primenjivali mehanizmi zaokruživanja. U trećem dijalektu ova specifičnost je eliminisana - veliki celi brojevi se čuvaju zaista kao celi brojevi - koristeći INT64 mehanizam koji može čuvati 64-bitne brojeve u opsegu +/-2^32. Stoga bi bilo bolje čuvati podatke o novčanim sredstvima u bazama podataka kreiranim korišćenjem 3. dijalekta. Samo korišćenje INT64 mehanizma će garantovati sigurnost malih novčanih ostataka.
Типови за чување датума и времена
Типови за чување датума и времена су промењени у верзији InterBase 6.x и његовим клононима у поређењу са 4.x и 5.x. Да се не бисмо збунили у историјским мрежама са овим типовима, размотрићемо ситуацију у InterBase 6. верзији. Затим ћемо на основу тога укратко поменути шта је било раније. Ово је учињено за оне кориснике који још увек раде са раним верзијама InterBase-а. Дакле, постоје 3 типа у InterBase 6.x за чување датума и времена - DATE, TIME и TIMESTAMP.
- Тип DATE чува датуме са прецизношћу до дана. Опсег могућих вредности - од 1. јануара 100. године н.е. до 29. фебруара 32768.
- Тип TIME чува податке о времену са прецизношћу до десетхиљадитих делова секунде. Опсег могућих вредности - од 00:00 до 23:59.9999.
- Тип TIMESTAMP представља комбинацију типова DATE и TIME.
Како радити са датумима? Ако је реч о раду на нивоу сервера у ускладиштеним процедурама или окидачима, све је прилично једноставно - увек можемо декларисати променљиву потребног типа и поставити је из табела и обрнуто. Међутим, потребно је пренети податке из базе података у апликацију и назад. У овом случају постоје два приступа: користити библиотеке које примењују оригинални формат InterBase датума за приступ објектима ових типова и конвертовати овај формат у обичне унутарјезичке типове датума/времена (FIBPlus је пример такве библиотеке), или користити механизам трансформације датума у низове, уграђен у InterBase.
Шта ћете урадити ако треба да издвојите само годину или месец из пуног датума? Мораћете да користите групу функција EXTRACT за ову сврху (доступне у свим клононима InterBase 6.x) које вам омогућавају да издвојите само потребан део из датума. Ове функције се користе на следећи начин:
EXTRACT (MONTH FROM DATE_FIELD)
EXTRACT (YEAR FROM DATE_FIELD)
Пуна листа параметара у функцији EXTRACT је следећа: YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, WEEKDAY, YEARDAY. Њихова функција произилази из њиховог имена, па их овде нећемо тумачити.
Типови података за чување текста
Постоје два типа у InterBase-у намењена за чување текстуалних информација - CHAR и VARCHAR. Њихова пуна имена - CHARACTER и CHARACTER VARYING, међутим нема разлога да се користе дуга имена - чак и команда Show tables у алату isql даје кратка имена типова.
Да бисте дефинисали поље или променљиву симболичког типа, потребно је у заградама после имена типа навести број симбола који ће се користити у дефинисаном објекту, или изоставити број симбола - тако ће се створити поље дужине 1 симбола.
CREATE TABLE testCHARLen(
Field1 CHAR(255),
Field2 CHAR);
Када се ова табела креира, Field1 ће имати дужину од 255 симбола, а Field2 - 1 симбол.
Типови CHAR и VARCHAR су у многим аспектима слични - оба могу да садрже до 32768 симбола, међутим постоје неке разлике. Иако се оба типа чувају у бази података на исти начин, InterBase ради са њима на различите начине. Следећи пример то демонстрира:
SQL> create table testCHAR ( c1 char(10), c2 varchar(10));
SQL> insert into testCHAR(c1,c2) values(‘Test’,‘Test’);
SQL> SELECT ‘(’||c1.|’)’, ‘(’||c2.|’)’ from testCHAR;
Као резултат, добићемо следеће:
(Test ) (Test)
Као што видите, после вредности ‘Test’, изабране из поља c1, појавили су се размаци. То значи да при избору података из поља типа CHAR враћена вредност бива допуњена размацима до пуне дужине поља. Тешко је претпоставити зашто је такво понашање, које доводи до значајног раста мрежног саобраћаја (оптерећења мреже), неопходно. У сваком случају, VARCHAR је симболички тип који се препоручује за употребу.
Једна од главних карактеристика симболичког типа је његов скуп знакова - CHARACTER SET. Скуп знакова је дефинисан за целу базу података и користи се подразумевано за сва симболичка поља ако није експлицитно редефинисан приликом креирања поља. Да бисте креирали симболичко поље са експлицитним навођењем скупа знакова, потребно је додати опис скупа знакова у опис колоне (у наредбама CREATE TABLE или ALTER TABLE). Скуп знакова WIN1251 се обично користи за подршку руског језика (ако желите детаљно да сазнате о употреби руског у InterBase-у погледајте поглавље “InterBase русификација” (део 1)). Ево примера табеле која садржи симболичко поље са експлицитно описаним скупом знакова WIN1251:
CREATE TABLE TestCHARSET(
Field1 VARCHAR(255),
Field2 VARCHAR(255) CHARACTER SET win1251);
Овде је Field1 поље без експлицитног навођења скупа знакова, па ће се за њега користити скуп знакова наведен приликом креирања базе података. За поље Field2 је очигледно одређено да ће чувати симболе у WIN1251 кодирању.
Поред навођења скупа знакова за симболичка поља, можете такође навести редослед сортирања (collation) који дефинише како ће се симболи овог скупа података сортирати. За руски језик постоје две варијанте сортирања - WIN1251 и PXW_CYRL. За више детаља о употреби COLLATION ORDER, погледајте поглавље “InterBase русификација”.
Пуну листу скупова знакова и COLLATION ORDER примењених за њих можете наћи у документацији [1, поглавље 13].
Пажња! Према документацији о InterBase 6 постоје 4 симболичка типа: осим горе поменутих типова постоје још 2 - NCHAR и NCHAR VARYING, међутим иста документација ниже објашњава да су последња два типа иста као CHAR и VARCHAR, само што се код њих подразумевано користи скуп знакова ISO8859.1. То значи да је заправо коришћење псеудо-типа NCHAR еквивалентно примени CHAR DEFAULT CHARACTER SET ISO8859.1. Слично је и за NCHAR VARYING, само што се уместо CHAR користи VARCHAR. Очигледно је да је примена ових псеудо-типова намењена корисницима у Западној Европи и САД, где је скуп знакова ISO8859.1 створен за подршку језика.
BLOB тип података
BLOB тип података је намењен за чување велике количине података променљиве величине. BLOB тип омогућава чување података који се не могу сместити у поља других типова - на пример, слике, музичке датотеке, видео фрагменти итд. Захтеви за дефинисање најједноставнијег поља типа BLOB у табели су исти као и за дефинисање поља било ког елементарног типа:
CREATE TABLE testBLOB(
myBlobField BLOB);
Као резултат, створиће се поље myBlobField у које је могуће сместити податке значајне величине. Упркос чињеници да се BLOB поља не разликују од осталих по начину дефинисања, њихова реализација унутар базе података се веома разликује. Не-BLOB поља се налазе на страници података (види поглавље “Структура InterBase базе података” (део 4)) близу једна другима, а док се на страници података чува само BLOB идентификатор, сам BLOB је смештен на посебној страници. Таква структура података омогућава чување података нефиксне величине.
BLOB тип има могућност дефинисања скупа неколико подтипова и специјалних процедура названих филтери (BLOB филтери) за рад са овим подтиповима. Постоје неки унапред одређени BLOB подтипови уграђени у InterBase. Сви ови подтипови имају ненегативне бројеве, на пример подтип 0 - подаци недефинисаног типа, подтип 1 - текст, подтип 2 - BLR (Binary Language Representation, види речник и поглавље “Структура InterBase базе података”) итд. Корисник такође може дефинисати BLOB подтипове који могу имати негативне вредности. Филтер се може применити на сваки тип. Он ће конвертовати поље једног подтипа у други.
Треба напоменути да је коришћење BLOB поља обично алтернатива чувању екстерних датотека у односу на базу података. Што се тиче BLOB филтера, они се користе прилично ретко због оријентације на уску категорију задатака.
Низови
DBMS InterBase је био један од првих у којима су се појавили низови. Подршка низова у бази података је проширење традиционалног релационог модела. Присуство низова омогућава поједностављење рада са скуповима података истог типа.
Низ је колекција вредности једног типа, која има заједничко име и омогућава приступ било ком елементу низа према његовом броју. Низи у InterBase-у могу бити једнодимензионални и вишедимензионални.
Да би се креирало поље низа бројева INTEGER у табели, треба написати нешто попут следећег:
CREATE TABLE test(
myOneDimArray INTEGER[12.,
myTwoDimArray INTEGER[5,4.,
myThreeDimArray INTEGER[2,10,8.);
Дакле, биће креирана три поља типа низа: myOneDimArray - поље које садржи једнодимензионални низ дужине 12 бројева, myTwoDimArray, које садржи дводимензионални низ (матрицу) - 5х4 цела броја, и myThreeDimArray - поље које садржи тродимензионални низ 2х10х8. Треба напоменути да су при оваквој дефиницији елементи низа нумерисани почевши од „један“, тј. први елемент има број 1, други - број 2, итд. Ако неко жели сам да постави границе низа, на пример од 0 до 5, треба да наведе дефиницију поља на следећи начин:
myArray INTEGER[0:5.
Низи су реализовани на основу поља типа BLOB, тако да не треба да бринете да ће вишедимензионални низ „запрљати“ вашу табелу великом количином података: InterBase ће уредно распоредити податке низа на одвојене странице како би оптимизовао операције улаза/излаза у овим пољима. Како користити низове? Они пружају згодан механизам за чување објеката истог типа. Међутим, у 80% случајева уместо низова, програмери преферирају да чувају вишеструке податке у подређеним (деталним) табелама, стога низови нису тако често коришћени у клијентским апликацијама InterBase DBMS-а. То се дешава јер библиотеке за приступ које се испоручују са Delphi-јем и C ++ Builder-ом, као што су BDE и IBX, не могу да раде са низовима. Према документацији за InterBase, могуће је радити са низовима користећи препроцесор gpre, али то није најпогоднији начин за програмера у Delphi/C ++ Builder-у. На срећу, у библиотеци FIBPlus постоји подршка за поља-низове у InterBase-у. О томе можете детаљно прочитати у поглављу „FIBPlus специјалне могућности“. Клијентска библиотека IBProvider, која омогућава креирање клијентских апликација за InterBase користећи развојне алате компаније Microsoft, такође подржава рад са низовима (види поглавље „Развој клијентских апликација InterBase DBMS-а користећи технологију Microsoft OLE DB“ (део 3)).
Закључак
Треба напоменути да је немогуће говорити о типовима података, а не ићи унапред, јер они продиру у све кључне области повезане са развојем апликација за базе података. Стога, приликом читања ове књиге, боље је користити дато поглавље као брзу референцу којој можете приступити сваки пут када треба да освежите основе InterBase-а.