Upload
vukhue
View
218
Download
0
Embed Size (px)
Citation preview
RĪGAS TEHNISKĀ UNIVERSITĀTEDatorzinātnes un informācijas tehnoloģijas fakultāte
Lietišķās datorzinātnes institūts
2.praktiskais darbsmācību priekšmetā
“ Specializētās datu bāzes sistēmas”
Temporālās DB izstrāde
Izstrādāja: Artūrs Solomencevs<I DB3 1, 111RDB004>
Pārbaudīja:
2014./15. māc. gads
2
SatursUzdevums...................................................................................................................................4
Problēmas vides apraksts............................................................................................................5
Datu bāzes struktūra....................................................................................................................6
1. Laika sērijas........................................................................................................................7
1.1. Tabulu KOMANDAS un SPONSORI izveidošana....................................................7
1.2. Tabulas PRODUKTI izveidošana...............................................................................7
1.3. Tabulas ATALGOJUMI izveidošana.........................................................................8
1.4. Tabulas DATI_PAR_SPELETAJIEM izveidošana....................................................9
1.5. Tabulas SPELETAJI izveidošana.............................................................................11
2. Datu ievade RODB struktūrās..........................................................................................12
2.1. Datu ievade tabulās KOMANDAS un SPONSORI..................................................12
2.2. Datu ievade tabulā PRODUKTI...............................................................................13
2.3. Datu ievade tabulā ATALGOJUMI..........................................................................14
2.4. Datu ievade tabulā DATI_PAR_SPELETAJIEM....................................................16
2.5. Datu ievade tabulā SPELETAJI................................................................................18
3. Temporālo vaicājumu definējumi.....................................................................................20
3.1. 1. vaicājums..............................................................................................................20
3.2. 2. vaicājums..............................................................................................................20
3.3. 3. vaicājums..............................................................................................................21
3.4. 4. vaicājums..............................................................................................................21
3.5. 5. vaicājums..............................................................................................................22
3.6. 6. vaicājums..............................................................................................................22
4. RODB struktūru definēšana vaicājumu izpildei...............................................................23
4.1. 1. vaicājumam...........................................................................................................23
4.2. 2. vaicājums..............................................................................................................24
4.3. 3. vaicājums..............................................................................................................25
4.4. 4. vaicājums..............................................................................................................29
4.5. 5.vaicājums...............................................................................................................30
4.5.1. Java valodas izmantošana metožu definēšanai.................................................33
4.6. 6. vaicājums..............................................................................................................37
5. Vaicājumu realizēšana......................................................................................................42
5.1. 1 vaicājums...............................................................................................................42
3
5.2. 2. vaicājums..............................................................................................................43
5.3. 3.vaicājums...............................................................................................................44
5.4. 4. vaicājums..............................................................................................................45
5.5. 5. vaicājums..............................................................................................................49
5.5.1. Vaicājuma izpilde ar Java valodā aprakstītām metodēm..................................50
5.6. 6. vaicājums..............................................................................................................51
6. Struktūru salīdzinājums temporālā DB un vaicājuma pieraksta vienkāršības novērtējums
53
Secinājumi.................................................................................................................................55
Literatūras saraksts....................................................................................................................57
4
Uzdevums
Otrajā praktiskajā darbā tiek veikta temporālās datu bāzes projektēšana, realizēšana un
temporālo vaicājumu definēšana un izpilde. Tiek izmantota relāciju-objektu datu bāzes
sistēmu tehnoloģija.
1. Tiek definētas vismaz 3 savstarpēji saistītas laika sērijas. To datu glabāšanai tiek
izmantotas relāciju-objektu datu glabāšanas struktūras: tabula ar kolekciju, tabulas ar
atsaucēm (references).
2. Tiek veikta datu ievade relāciju – objektu DB struktūrās.
3. Tiek definēti 6 dažādas sarežģītības pakāpes datu izgūšanas temporālie vaicājumi,
kuru realizēšanai ir nepieciešams izmantot temporālās algebras darbības (tiek izmantotas
vismaz 3 tipiskākās temporālās algebras darbības). Atgādinājums: Temporālie vaicājumi
operē ar laika periodiem un intervāliem.
4. Temporāliem vaicājumiem tiek noskaidrots, kādas temporālās algebras darbības
jārealizē to izpildei.
5. Tiek izveidotas relāciju – objektu DB virtuālās struktūras (objektu skati), no kurām
tiks izgūti dati. Veidojot objektu tipus objektu skatiem, tiek definētas arī metodes temporālās
algebras darbību izpildīšanai. Metožu definēšanai tiek izmantota arī Java programmēšanas
valoda.
6. Tiek izpildīti temporālie vaicājumi, izmantojot objektu skatus un definētās metodes
temporālās algebras darbību realizēšanai. Rezultāti tiek izanalizēti, vai tie ir korekti.
7. Temporālo vaicājumu realizācijai tiek izmantota arī klona tabulu (windowing)
tehnoloģija.
8. Tiek izdarīti secinājumi, kā vienkāršāk un efektīvāk SQL valodā pierakstīt
temporālos vaicājumus.
9. Kopējie secinājumi.
5
Problēmas vides apraksts
Par problēmas vidi savā darbā izvēlējos kibersportu – Counter-Strike spēli un cilvēku
aktivitāti, saistītu ar to.
Kibersports – ir sacensības datora spēles vidē. Spēlētāji apvienojās komandās. Katrs
spēlētājs var būt tikai vienas komandas sastāvā. Katram spēlētājam ir kvalifikācijas līmenis,
kurš mainās laikā. Par spēlēšanu komandā spēlētāji saņem algu. No spēlētāja kvalifikācijas ir
atkarīga viņa alga. Biznesmeni arī var pelnīt naudu no kibersporta – sponsorēt komandas, lai
tie reklamētu viņu produkciju, piemēram, perifēriju, enerģētiskus dzērienus u.t.t. Par katru
reklamētu produktu sponsors maksā komandai mēnesī noteikto summu.
Datu bāzes struktūra
1. Laika sērijas
Laika sērijas satur tabulas PRODUKTI, ATALGOJUMI, DATI_PAR_SPELETAJIEM
un SPELETAJI.
1.1. Tabulu KOMANDAS un SPONSORI izveidošana
Vispirms izveidosim tabulas, kas nesatur temporālus datus: KOMANDAS un
SPONSORI.
Vaicājumi:
--Tabula KOMANDASCreate table KOMANDAS( Komandas_ID Number(10, 0) constraint pk_komandas primary key, Nosaukums Varchar2(20), Pilseta Varchar2(30));
-- Tabula SPONSORICreate table SPONSORI( Sponsora_ID Number(10, 0) constraint pk_sponsori primary key, Komandas_ID not null constraint fk_sponsori_komandas references KOMANDAS(Komandas_ID), Nosaukums Varchar2(30));
Rezultāts:
1.2. Tabulas PRODUKTI izveidošana
Tabula PRODUKTI satur kolekciju.
8
Vispirms jāizveido objekta tips MAKSAJUMS_T. Tipa objekti būs ievietoti kolekcijā.
Vaicājums:
-- Tipa MAKSAJUMS_T definēšanaCreate or replace type MAKSAJUMS_T as object( Summa_menesi Number(12, 2), NO Date, -- LIDZ Date -- NO un LIDZ atributi noteic laika perioda robežas);
Tālāk jādefinē kolekcijas tips:
-- Kolekcijas tipa definējumsCreate or replace type MAKSAJUMI_T as table of MAKSAJUMS_T;
Jāizveido tabula ar kolekciju:
-- Tabulas PRODUKTI izveidošanaCreate table PRODUKTI( Produkta_ID Number(10, 0) constraint pk_produkti primary key, Sponsora_ID not null constraint fk_produkti_sponsori references SPONSORI(Sponsora_ID), Nosaukums Varchar2(30), Maksajumi MAKSAJUMI_T -- kolekcija tabulā)nested table Maksajumi store as PRODUKTI_MAKSAJUMI_KOLEKCIJA;
1.3. Tabulas ATALGOJUMI izveidošana
Tā kā kolekcijas struktūra ir vienāda ar PRODUKTI tabulas kolekcijas struktūru,
tabulas veidošanai tiek izmantots iepriekš definētais tips MAKSAJUMI_T.
9
-- Tabulas ATALGOJUMI izveidošanaCreate table ATALGOJUMI( Atalgojuma_ID Number(10, 0) constraint pk_atalgojumi primary key, Komandas_ID not null constraint fk_atalgojumi_komandas references KOMANDAS(Komandas_ID), Kvalifikacija Varchar2(30), Algas MAKSAJUMI_T -- atkārtoti izmantojām tipu MAKSAJUMI_T)nested table Algas store as ATALGOJUMI_ALGAS_KOLEKCIJA;
1.4. Tabulas DATI_PAR_SPELETAJIEM izveidošana
Izveidosim objekta tipu, kura atribūti ir spēlētāja vārds, uzvārds un pavārds (zīmējumā
objekts, kas atrodas pie kolekcijas):
-- SPELETAJA_VARDI_T definējums:Create or replace type SPELETAJA_VARDI_T as object( Vards Varchar2(20), Uzvards Varchar2(30), Pavards Varchar2(30));
10
Izveidosim objekta tipu, kura objekti tiek iekļauti kolekcijā – kvalifikāciju sarakstā:
-- KVALIFIKACIJA_T tipa definējums:Create or replace type KVALIFIKACIJA_T as object( Kvalifikacija Varchar2(30), NO Date, LIDZ Date);
Izveidosim kolekcijas tipu:
-- Kolekcijas tipa definējumsCreate or replace type KVALIFIKACIJAS_T as table of KVALIFIKACIJA_T;
Jādefinē salikts tips, kas satur datus par spēlētāju un viņa kvalifikāciju sarakstu. Tātad
jāizveido tips, kas satur objektu un kolekciju:
-- Salikta tipa definējumsCreate or replace type DATI_PAR_SPELETAJU_T as object( Speletaja_vardi SPELETAJA_VARDI_T, -- vienkāršs objekts Kvalifikacijas KVALIFIKACIJAS_T -- kolekcija);
Tabulas izveidošana:
-- Tabulas DATI_PAR_SPELETAJIEM izveidošanaCreate table DATI_PAR_SPELETAJIEM of DATI_PAR_SPELETAJU_Tnested table Kvalifikacijas store as DATI_KVALIFIKACIJAS_KOLEKCIJA;
11
1.5. Tabulas SPELETAJI izveidošana
Tabula SPELETAJI satur objektu, kas atspoguļo laika periodu, kuru spēlētājs spēlē
komandā, un atsauci uz objektu, kas atrodas tabulā DATI_PAR_SPELETAJIEM.
Vispirms definēsim objekta tipu, kas atspoguļo laika periodu:
-- Tipa LAIKA_PERIODS_T definēšanaCreate or replace type LAIKA_PERIODS_T as object( NO Date, LIDZ Date);
Izveidosim tabulu:
-- Tabulas SPELETAJI definēšanaCreate table SPELETAJI( Speletaja_ID Number(10, 0) constraint pk_speletaji primary key, Komandas_ID not null constraint fk_speletaji_komandas references KOMANDAS(Komandas_ID), Spel_dati REF DATI_PAR_SPELETAJU_T, -- atsauce uz objektu Periods LAIKA_PERIODS_T);
Tabulas ar laika sērijām bija izveidotas. Datu glabāšanai tiek izmantotas relāciju-
objektu datu glabāšanas struktūras: tabula ar kolekciju, tabulas ar atsaucēm. Tālāk ievadīsim
datus.
12
2. Datu ievade RODB struktūrās
Vispirms ievadīsim komandu, kas noteic datuma formātu „diena-mēnesis-gads”:
alter session set NLS_DATE_FORMAT = 'DD-MM-RRRR' ;
Sāksim ar datu ievadi ar tabulām KOMANDAS un SPONSORI un turpināsim ar
tabulām, kas satur laika sērijas.
2.1. Datu ievade tabulās KOMANDAS un SPONSORI
-- Datu ievade tabulā KOMANDAS:begin Insert into KOMANDAS Values(1, 'Rallied', 'Ventspils'); Insert into KOMANDAS Values(2, 'Allien', 'Riga');end;
-- Datu ievade tabulā SPONSORI:begin Insert into SPONSORI Values(1, 1, 'Audi'); Insert into SPONSORI Values(2, 1, 'Red Bull'); Insert into SPONSORI Values(3, 2, 'Razer'); Insert into SPONSORI Values(4, 2, 'Monster');end;
Pārbaude:
Select A.*, B.*From KOMANDAS A, SPONSORI BWhere A.Komandas_ID = B.Komandas_ID;
Viss ir pareizi.
13
2.2. Datu ievade tabulā PRODUKTI
Tabulas aizpildīšanai izmantosim SQL*Loader programmu.
Faila produkti.ctl saturs:
load datainfile 'C:\RTU\studijas\4_1\Lielas_datu_bazes\2_lab\Loader\produkti_data.dat'into table PRODUKTIfields terminated by ',' optionally enclosed by '"'( Produkta_ID, Sponsora_ID, Nosaukums, Maksajumi NESTED TABLE TERMINATED BY ':' ( MAKSAJUMS_T COLUMN OBJECT(
Summa_menesi, NO DATE "DD-MM-RRRR", LIDZ DATE "DD-MM-RRRR" NULLIF
Maksajumi.MAKSAJUMS_T.LIDZ=BLANKS)
))Paskaidrojums:
LIDZ DATE "DD-MM-RRRR" NULLIF
Maksajumi.MAKSAJUMS_T.LIDZ=BLANKS
Nozīmē, ka, ja lauka vērtība netiek norādīta (vērtības vietā ir atstarpe), tad ierakstīt
lauka vērtību NULL. NULL vērtība atribūtā LIDZ nozīmē, ka periods turpinās patlaban un
nav zināms, kad tas beigsies.
Faila produkti_data.dat saturs:
1, 1, "Audi A6", 5000, 01-01-2014, 01-04-2014, 7000, 01-04-2014, 15-06-20142, 1, "Audi A8", 1250, 01-05-2014, 01-06-2014, 3000, 01-08-2014, :3, 2, "Redbull dzeriens", 500, 01-03-2014, 01-07-2014, 750, 01-07-2014, 01-10-
2014, 450, 01-01-2014, :4, 3, "Deathadder", 1250, 15-02-2014, 01-05-2014, 2000, 15-06-2014, 15-09-2014 :5, 3, "Mamba", 1500, 01-05-2014, 01-06-2014, 2500, 15-09-2014, : 6, 3, "Kraken", 5000, 01-01-2014, 01-06-2014, 3000, 15-08-2014, 15-09-2014 :7, 4, "Monster dzeriens", 250, 01-01-2014, 01-06-2014, 390, 01-06-2014, 01-01-2015 :
5000, 01-01-2014, 01-04-2014, 7000, 01-04-2014, 15-06-2014 – vērtību trijnieki atbilst objektiem, kuri tiek iekļauti kolekcijās.
14
Pēc programmas izpildes LOG failā tiek uzrakstīts:
Table PRODUKTI: 7 Rows successfully loaded. 0 Rows not loaded due to data errors. 0 Rows not loaded because all WHEN clauses were failed. 0 Rows not loaded because all fields were null.
Pēc žurnāla var secināt, ka datu ielāde notika veiksmīgi. Pārbaudīsim ar vaicājumu:
Select A.Produkta_ID, A.Sponsora_ID, A.Nosaukums, B.Summa_menesi, B.NO, B.LIDZFrom PRODUKTI A, Table(A.Maksajumi) B;
Tiešām visi ieraksti bija ievadīti. Arī NULL vērtības bija veiksmīgi ievadītas kolonā
LIDZ. Ierakstu skaits ir lielāks par, jo pēc funkcijas Table() pielietojuma katram kolekcijas
objektam atbilst viens ieraksts.
2.3. Datu ievade tabulā ATALGOJUMI
Šo tabulu arī būtu vieglāk aizpildīt ar programmas SQL*Loader palīdzību.
Faila atalgojumi.ctl saturs:
load datainfile 'C:\RTU\studijas\4_1\Lielas_datu_bazes\2_lab\Loader\atalgojumi_data.dat'into table ATALGOJUMIfields terminated by ',' optionally enclosed by '"'( Atalgojuma_ID, Komandas_ID, Kvalifikacija, Algas NESTED TABLE TERMINATED BY ':' ( MAKSAJUMS_T COLUMN OBJECT(
Summa_menesi, NO DATE "DD-MM-RRRR",
15
LIDZ DATE "DD-MM-RRRR" NULLIF
Algas.MAKSAJUMS_T.LIDZ=BLANKS)
))
Faila atalgojumi_data.dat saturs:
1, 1, "Augsta", 200, 01-01-2014, 01-05-2014, 250, 01-05-2014, 15-10-2014, 200, 15-10-2014, :
2, 1, "Meistars", 1000, 01-01-2014, 01-05-2014, 1500, 01-05-2014, 15-10-2014, 1250, 15-10-2014, :
3, 1, "Globala elite", 2000, 01-01-2014, 01-04-2014, 2700, 01-04-2014, :4, 2, "Augsta", 300, 15-01-2014, 20-07-2014, 350, 20-07-2014, :5, 2, "Meistars", 800, 01-01-2014, 01-03-2014, 750, 01-03-2014, 01-06-2014, 850,
01-06-2014, : 6, 2, "Globala elite", 1500, 01-01-2014, 01-06-2014, 1900, 01-06-2014, :
Žurnāla ieraksti pēc SQL*Loader izpildes:
Table ATALGOJUMI: 6 Rows successfully loaded. 0 Rows not loaded due to data errors. 0 Rows not loaded because all WHEN clauses were failed. 0 Rows not loaded because all fields were null.
Pēc žurnāla var secināt, ka datu ielāde notika veiksmīgi. Pārbaudīsim ar vaicājumu:
Select A.Atalgojuma_ID, A.Komandas_ID, C.Nosaukums, A.Kvalifikacija, B.Summa_menesi, B.NO, B.LIDZ
From ATALGOJUMI A, Table(A.Algas) B, KOMANDAS CWhere A.Komandas_ID = C.Komandas_ID;
Visi ieraksti bija veiksmīgi ievadīti.
16
2.4. Datu ievade tabulā DATI_PAR_SPELETAJIEM
Tā kā tabula satur saliktus objektus, izmantosim Insert komandu datu ievadei.
begin -- 1. komandas spēlētāji Insert into DATI_PAR_SPELETAJIEM Values(
SPELETAJA_VARDI_T('Kirills','Marcenkovs','Gercegs'), -- vienkāršs objekts KVALIFIKACIJAS_T( -- kolekcija KVALIFIKACIJA_T('Augsta', '01-01-2014', '25-03-2014'), -- kolekcijas elements KVALIFIKACIJA_T('Meistars', '25-03-2014', '15-07-2014'), KVALIFIKACIJA_T('Augsta', '15-07-2014', NULL) ));
Insert into DATI_PAR_SPELETAJIEM Values( SPELETAJA_VARDI_T('Olegs','Strelnikovs','brrr'), KVALIFIKACIJAS_T( KVALIFIKACIJA_T('Augsta', '01-01-2014', '01-02-2014'), KVALIFIKACIJA_T('Meistars', '01-02-2014', '01-04-2014'), KVALIFIKACIJA_T('Globala elite', '01-04-2014', NULL) ));
Insert into DATI_PAR_SPELETAJIEM Values( SPELETAJA_VARDI_T('Aleksejs','Rumjancevs','PyMuK'), KVALIFIKACIJAS_T( KVALIFIKACIJA_T('Meistars', '01-01-2014', '30-09-2014'), KVALIFIKACIJA_T('Globala elite', '30-09-2014', NULL) ));
Insert into DATI_PAR_SPELETAJIEM Values( SPELETAJA_VARDI_T('Pafnutijs','Lindermans','CrssK'), KVALIFIKACIJAS_T( KVALIFIKACIJA_T('Meistars', '01-01-2014', NULL) ));
Insert into DATI_PAR_SPELETAJIEM Values( SPELETAJA_VARDI_T('Marks','Zars','Koks'), KVALIFIKACIJAS_T( KVALIFIKACIJA_T('Augsta', '01-01-2014', '01-02-2014'), KVALIFIKACIJA_T('Meistars', '01-02-2014', NULL) ));
-- 2. komandas speletaji Insert into DATI_PAR_SPELETAJIEM Values(
SPELETAJA_VARDI_T('Vladimirs','Laktionovs','VoV4iK'), KVALIFIKACIJAS_T( KVALIFIKACIJA_T('Meistars', '01-01-2014', '30-07-2014'), KVALIFIKACIJA_T('Globala elite', '30-07-2014', NULL) ));
Insert into DATI_PAR_SPELETAJIEM Values( SPELETAJA_VARDI_T('Maksims','Puskins','Ku4er'), KVALIFIKACIJAS_T( KVALIFIKACIJA_T('Meistars', '01-01-2014', '01-05-2014'),
17
KVALIFIKACIJA_T('Augsta', '01-05-2014', '01-07-2014'), KVALIFIKACIJA_T('Meistars', '01-07-2014', NULL) ));
Insert into DATI_PAR_SPELETAJIEM Values( SPELETAJA_VARDI_T('Alina','Bondarenko','Alinators'), KVALIFIKACIJAS_T( KVALIFIKACIJA_T('Globala elite', '01-01-2014', NULL) ));
Insert into DATI_PAR_SPELETAJIEM Values( SPELETAJA_VARDI_T('Danila','Bodrovs','Bralis'), KVALIFIKACIJAS_T( KVALIFIKACIJA_T('Augsta', '01-01-2014', '01-04-2014'), KVALIFIKACIJA_T('Meistars', '01-04-2014', '01-10-2014'), KVALIFIKACIJA_T('Globala elite', '01-10-2014', NULL) ));
end;
Pārbaudīsim tabulas saturu:
Select A.Speletaja_vardi.Vards, A.Speletaja_vardi.Uzvards, A.Speletaja_vardi.Pavards, B.Kvalifikacija, B.NO, B.LIDZFrom DATI_PAR_SPELETAJIEM A, Table(A.Kvalifikacijas) B;
Vaicājuma rezultāts (visi ieraksti bija veiksmīgi ievadīti):
18
2.5. Datu ievade tabulā SPELETAJI
Tā kā tabula satur kolonu ar atsaucēm uz tabulas DATI_PAR_SPELETAJIEM
objektiem, datu ievadei izmantosim anonīmu PL/SQL bloku.
Declare -- atsauču deklarēšana ats_1 Ref DATI_PAR_SPELETAJU_T; ats_2 Ref DATI_PAR_SPELETAJU_T; ats_3 Ref DATI_PAR_SPELETAJU_T; ats_4 Ref DATI_PAR_SPELETAJU_T; ats_5 Ref DATI_PAR_SPELETAJU_T; ats_6 Ref DATI_PAR_SPELETAJU_T; ats_7 Ref DATI_PAR_SPELETAJU_T; ats_8 Ref DATI_PAR_SPELETAJU_T; ats_9 Ref DATI_PAR_SPELETAJU_T; Begin -- atsauču vērtību piešķiršana Select Ref(A) into ats_1 FROM DATI_PAR_SPELETAJIEM A Where A.Speletaja_vardi.Pavards = 'Gercegs'; Select Ref(A) into ats_2 FROM DATI_PAR_SPELETAJIEM A Where A.Speletaja_vardi.Pavards = 'brrr'; Select Ref(A) into ats_3 FROM DATI_PAR_SPELETAJIEM A Where A.Speletaja_vardi.Pavards = 'PyMuK'; Select Ref(A) into ats_4 FROM DATI_PAR_SPELETAJIEM A Where A.Speletaja_vardi.Pavards = 'CrssK'; Select Ref(A) into ats_5 FROM DATI_PAR_SPELETAJIEM A Where A.Speletaja_vardi.Pavards = 'Koks'; Select Ref(A) into ats_6 FROM DATI_PAR_SPELETAJIEM A Where A.Speletaja_vardi.Pavards = 'VoV4iK'; Select Ref(A) into ats_7 FROM DATI_PAR_SPELETAJIEM A Where A.Speletaja_vardi.Pavards = 'Ku4er'; Select Ref(A) into ats_8 FROM DATI_PAR_SPELETAJIEM A Where A.Speletaja_vardi.Pavards = 'Alinators'; Select Ref(A) into ats_9 FROM DATI_PAR_SPELETAJIEM A Where A.Speletaja_vardi.Pavards = 'Bralis'; -- datu ievade ar atbilstošām atsaucēm Insert into SPELETAJI Values(1, 1, ats_1, LAIKA_PERIODS_T('01-01-2014', NULL)); Insert into SPELETAJI Values(2, 1, ats_2, LAIKA_PERIODS_T('10-02-2014', '01-05-2014')); Insert into SPELETAJI Values(3, 1, ats_3, LAIKA_PERIODS_T('01-03-2014', NULL)); Insert into SPELETAJI Values(4, 1, ats_4, LAIKA_PERIODS_T('15-05-2014', NULL)); Insert into SPELETAJI Values(5, 1, ats_5, LAIKA_PERIODS_T('01-05-2014', '30-10-2014')); Insert into SPELETAJI
19
Values(6, 2, ats_6, LAIKA_PERIODS_T('01-01-2014', '01-05-2014')); Insert into SPELETAJI Values(7, 2, ats_7, LAIKA_PERIODS_T('01-05-2014', NULL)); Insert into SPELETAJI Values(8, 2, ats_8, LAIKA_PERIODS_T('01-01-2014', NULL)); Insert into SPELETAJI Values(9, 2, ats_9, LAIKA_PERIODS_T('01-04-2014', NULL));
End;
Pārbaudīsim, vai dati bija ievadīti veiksmīgi. Izmantosim operatoru Deref(), lai iegūtu
datus no objekta, uz kuru ir atsauce.
Select A.Speletaja_ID, Deref(A.Spel_dati).Speletaja_vardi.Pavards, B.Nosaukums, A.Periods.NO, A.Periods.LIDZFrom SPELETAJI A, KOMANDAS BWhere A.Komandas_ID = B.Komandas_ID;
Rezultāts:
Visi ieraksti bija veiksmīgi ievadīti. Ar sarkano rāmīti tiek apzīmēta kolona, kura bija
iegūta, izmantojot operatoru Deref(). Šajā tabulā periods nozīmē laika periodu, kurā spēlētājs
spēlēja attiecīgajā komandā.
Tātad visas tabulas ir aizpildītās ar datiem un varam sākt pildīt nākamo uzdevumu.
20
3. Temporālo vaicājumu definējumi
3.1. 1. vaicājums
Uzzināt, kādas kvalifikācijas ir spēlētājiem noteiktajā datumā.
Vajadzīgas temporālās algebras darbības:
Vaicājuma izpildei jārealizē atlase, lai atlasītu ierakstus (WHERE...). Atlase izmantos
Allena operatoru Y IETVER X.
Konkrēto datumu (vienu dienu) var uzskatīt kā laika intervālu, kura sākums un beigas
sakrīt.
3.2. 2. vaicājums
Atrast reklamētus produktus, kuriem, kuriem pēc iepriekšējā kontrakta pabeigšanas,
uzreiz bija parakstīts jauns kontrakts. Parādīt iepriekšēja kontrakta sākuma datumu,
„satikšanas” datumu un jauna kontrakta beigšanas datumu.
21
1. produkts mūs interesē, bet 2. produkts - nē.
Vajadzīgas temporālās algebras darbības:
Vaicājuma izpildei jārealizē atlase, lai atlasītu ierakstus (WHERE...). Vaicājums arī
izmantos projekciju no temporālās algebras darbībām. Atlase izmantos Allena operatoru X
SATIEK Y.
3.3. 3. vaicājums
Uzzināt spēlētāja atalgojuma vēsturi.
Vajadzīgas temporālās algebras darbības:
Lai būtu iespējams izpildīt šo vaicājumu, ir nepieciešams realizēt reizinājumu
(multiplication). Reizinājuma realizēšanai jāizmanto Allena operatoru X PĀRKLĀJ Y.
Vaicājumā vajadzēs reizināt trīs laika sērijas.
22
3.4. 4. vaicājums
Uzzināt, kādu naudas summu līdz mūsdienām nopelnīja komanda, reklamējot
produktus. Uzzināt naudas summu par produktiem atsevišķi un kopējo summu no sponsora.
Vajadzīgas temporālās algebras darbības:
Vaicājuma izpildei tiek realizēta intervāla sadalīšana Unfold. Rezultātu iegūšanai tiek
izmantota klona tabulu (windowing) tehnoloģija.
3.5. 5. vaicājums
Uzzināt, kā spēlēšana komandā ietekmēja spēlētāja kvalifikāciju. Parādīt kvalifikācijas
izmaiņas datumu.
Vajadzīgas temporālās algebras darbības:
Tiek realizēta atlase. No Allena operatoriem tiek izmantoti X PARKLAJ Y un X
SATIEK Y.
Vaicājuma izpildei metodes tiek realizēti arī Java valodā.
3.6. 6. vaicājums
Noteikt laika periodu, kurā sponsors maksā komandai, apvienojot laika periodus, kuros
sponsors maksā par noteiktiem produktiem. Ja rezultātā tiek iegūti vairāk par vienu periodu -
atspoguļot visus.
Vajadzīgas temporālās algebras darbības:
Tiek realizēts laika periodu apvienojums. Laika apvienojums tiek realizēts ar
agregācijas funkciju. Agregācijas funkcija pielieto Allena operatoru X PIRMS Y. Izrādās, ka
šī predikāta pielietojums no visiem predikātiem ir pietiekams, lai realizētu apvienojumu.
23
24
4. RODB struktūru definēšana vaicājumu izpildei
4.1. 1. vaicājumam
Objekta tipam tiek izveidota metode SATUR(datums X), kura realizē Allena operatoru
Y IETVER X.
Objekta tipa izveidošana:
-- Objekta tipsCreate or replace type OBJEKTS_1_V_T as object( Vards Varchar2(20), Uzvards Varchar2(30), Pavards Varchar2(30), Kvalifikacija Varchar2(30), NO Date, LIDZ Date,
-- metodes prototips MEMBER function SATUR(P_DATUMS in Date) return number );
-- Objekta tipa ķermena (body) izveidošanaCreate or replace type body OBJEKTS_1_V_T as MEMBER function SATUR(p_datums in Date) return number is begin if ((p_datums >= self.NO AND p_datums < self.LIDZ) OR
(self.LIDZ IS NULL AND p_datums >= self.NO)) then return 1; -- ja intervāls satur datumu, tad metode atgriez 1else return 0; -- pretējā gadījumā metode atgriež 0end if;
end SATUR;end;
Objekta skata izveidošana:
-- Objekta skats:Create or replace view SKATS_1 of OBJEKTS_1_V_T with object identifier(Uzvards, Pavards) as Select A.Speletaja_vardi.Vards, A.Speletaja_vardi.Uzvards, A.Speletaja_vardi.Pavards, B.Kvalifikacija, B.NO, B.LIDZ From DATI_PAR_SPELETAJIEM A, Table(A.Kvalifikacijas) B;
25
Pārbaudīsim skata un metodes darbību:
-- PārbaudeSelect A.Pavards, A.Kvalifikacija, A.NO, A.LIDZ, '10-09-2014' as Datums, CASE when Value(A).SATUR(to_date('10-09-2014', 'DD-MM-RRRR')) = 1 then 'SATUR'
when Value(A).SATUR(to_date('10-09-2014', 'DD-MM-RRRR')) = 0 then 'NESATUR' END as Serija_satur_datumuFrom SKATS_1 A;-- Ar resnu fontu tiek apzīmēts MEMBER metodes izsaukums.
Rezultāts:
Ja atribūta DATUMS vērtība ietilpst intervālā [NO..LIDZ), tad atribūts
SERIJA_SATUR_DATUMU saņem vērtību „SATUR”. Pretējā gadījumā – „NESATUR”.
Apskatot rezultātu, varu secināt, ka skats un metode strādā pareizi.
4.2. 2. vaicājums
Objekta tipam tiek izveidota ORDER metode SATIEK(laika_elements Y), kura realizē
Allena operatoru X SATIEK Y.
Objekta tipa izveidošana:
-- Objekta tipsCreate or replace type OBJEKTS_2_V_T as object( Produkta_ID Number(10, 0), Nosaukums Varchar2(30), NO Date, LIDZ Date,
26
-- metodes prototips ORDER MEMBER function SATIEK(p_object in OBJEKTS_2_V_T) return number );
-- Objekta tipa ķermeņa (body) izveidošanaCreate or replace type body OBJEKTS_2_V_T as ORDER MEMBER function SATIEK(p_object in OBJEKTS_2_V_T) return number is begin if (self.LIDZ = p_object.NO) then
return 1; -- Ja SELF satiek p_object, tad metode atgriez 1else return 0; -- Pretējā gadījumā atgriež 0end if;
end SATIEK;end;
Objekta skata izveidošana:
-- Objekta skats:Create or replace view SKATS_2 of OBJEKTS_2_V_T with object identifier(Produkta_ID, NO) as Select A.Produkta_ID, A.Nosaukums, B.NO, B.LIDZ From PRODUKTI A, Table(A.Maksajumi) B;
4.3. 3. vaicājums
Tā kā vajadzēs reizināt 3 laika sērijas, tiek izveidoti 3 objektu tipi un 3 objektu skati.
Objektu tipu izveidošana:
-- Objekta tips, kas atspoguļo atalgojumu kvalifikācijaiCreate or replace type OBJEKTS_3_ALGA_T as object( Komandas_ID Number(10, 0), Kvalifikacija Varchar2(30), Alga Number(12, 2), NO Date, LIDZ Date);
-- Objekta tips, kas atspoguļo spēlētāja kvalifikācijuCreate or replace type OBJEKTS_3_KVAL_T as object(
27
Komandas_ID Number(10, 0), Speletaja_ID Number(10, 0), Vards Varchar2(20), Uzvards Varchar2(30), Pavards Varchar2(30), Kvalifikacija Varchar2(30), NO Date, LIDZ Date);
-- Objekta tips, kas atspoguļo spēlētāja spēlēšānas periodu komandāCreate or replace type OBJEKTS_3_SPEL_T as object( Komandas_ID Number(10, 0), Speletaja_ID Number(10, 0), NO Date, LIDZ Date);
Objektu skatu izveidošana:
-- Skats ar objektiem OBJEKTS_3_ALGA_TCreate or replace view SKATS_3_ALGA of OBJEKTS_3_ALGA_T with object identifier(Komandas_ID, NO, LIDZ) as Select A.Komandas_ID, A.Kvalifikacija, B.Summa_menesi, B.NO, B.LIDZ From ATALGOJUMI A, Table(A.Algas) B; -- Skats ar objektiem OBJEKTS_3_KVAL_TCreate or replace view SKATS_3_KVAL of OBJEKTS_3_KVAL_T with object identifier(Komandas_ID, NO, LIDZ) as Select A.Komandas_ID, A.Speletaja_ID, Deref(A.Spel_dati).Speletaja_vardi.Vards, Deref(A.Spel_dati).Speletaja_vardi.Uzvards,
Deref(A.Spel_dati).Speletaja_vardi.Pavards, B.Kvalifikacija, B.NO, B.LIDZ From SPELETAJI A, Table(Deref(A.Spel_dati).Kvalifikacijas) B;
Šis skats tiek definēts ar operācijas Deref(A.Spel_dati) palīdzību, lai piekļūtu saliktiem objektiem. Kolona Spel_dati satur atsauces.
28
-- Skats ar objektiem OBJEKTS_3_SPEL_TCreate or replace view SKATS_3_SPEL of OBJEKTS_3_SPEL_T with object identifier(Speletaja_ID) as Select A.Komandas_ID, A.Speletaja_ID, A.Periods.NO, A.Periods.LIDZ From SPELETAJI A;
Šajā gadījumā metodes nebija definēta objektu tipiem. Izmantosim funkciju, kas realizēs
laiku sēriju reizinājumu. Funkcija atgriezis objektu, kura tips tiek definēts sekojoši:
-- Objekta, kuru atgriež reizinājuma funkcija, tipsCreate or replace type REZULTATS_3 as object( Vards Varchar2(20), Uzvards Varchar2(30), Pavards Varchar2(30), Kvalifikacija Varchar2(30), Alga Number(12, 2), NO Date, LIDZ Date);
-- Funkcija REIZINAJUMS create or replace function REIZINAJUMS(obj_alga OBJEKTS_3_ALGA_T, obj_kval OBJEKTS_3_KVAL_T, obj_spel OBJEKTS_3_SPEL_T) return
REZULTATS_3 is
-- Objekts, kas tiek atgriezts. Ja tas pēc atgriešanas saturēs NULL vērtības, tas-- nozīmē, ka visi trīs laika periodi nepārklājās. res REZULTATS_3 := REZULTATS_3(NULL, NULL, NULL, NULL, NULL, NULL, NULL);temp_NO Date; -- starprezultātiemtemp_LIDZ Date; -- starprezultātiembegin -- Nākamais operators pārbauda, vai ir pārklāšana starp diviem periodiem. -- Ja ir, pārklāšanas perioda robežas tiek ierakstītas -- mainīgajos temp_NO un temp_LIDZ if((obj_alga.NO < obj_kval.LIDZ OR obj_kval.LIDZ IS NULL) AND (obj_kval.NO < obj_alga.LIDZ OR obj_alga.LIDZ IS NULL)) then if (obj_alga.NO >= obj_kval.NO) then -- No divām NO izvēlās lielāko (vēlāko)
temp_NO := obj_alga.NO; else
29
temp_NO := obj_kval.NO; end if;
-- Jāpārbauda, vai LIDZ atribūti nav vienādi ar NULL.if (obj_alga.LIDZ IS NULL AND obj_kval.LIDZ IS NULL) then temp_LIDZ := NULL; -- Ja abi ir NULL, tad piešķiram NULLelsif (obj_alga.LIDZ IS NULL) then -- Ja tikai viens, tad piešķiram otro, ne NULL temp_LIDZ := obj_kval.LIDZ;elsif (obj_kval.LIDZ IS NULL) then -- Ja tikai viens, tad piešķiram otro, ne NULL temp_LIDZ := obj_alga.LIDZ;elsif (obj_alga.LIDZ <= obj_kval.LIDZ) then -- No divām izvēlās mazāko (agrāko) temp_LIDZ := obj_alga.LIDZ;else temp_LIDZ := obj_kval.LIDZ;end if;
-- Tālāk tiek pārbaudīts, vai ir pārklāšana starp 3. periodu un [temp_NO, temp_LIDZ)-- Ja ir, tad res (REZULTATS_3) objekta atribūtiem tiek piešķirtas vērtībasif((temp_NO < obj_spel.LIDZ OR obj_spel.LIDZ IS NULL) AND (obj_spel.NO < temp_LIDZ OR temp_LIDZ IS NULL)) then
if (temp_NO >= obj_spel.NO) then -- No divām NO izvēlās lielāko (vēlāko) res.NO := temp_NO; else res.NO := obj_spel.NO; end if; -- Līdzīgi pārbaudām, vai LIDZ atribūti nav vienādi ar NULL -- un piešķiram atbilstošās vērtības if (temp_LIDZ IS NULL AND obj_spel.LIDZ IS NULL) then res.LIDZ := NULL;
elsif (temp_LIDZ IS NULL) then res.LIDZ := obj_spel.LIDZ; elsif (obj_spel.LIDZ IS NULL) then res.LIDZ := temp_LIDZ; elsif (temp_LIDZ <= obj_spel.LIDZ) then -- No divām izvēlās mazāko (agrāko) res.LIDZ := temp_LIDZ; else res.LIDZ := obj_spel.LIDZ; end if;
-- Un visi pārējie atribūti arī tiek inicializēti
res.Vards := obj_kval.Vards; res.Uzvards := obj_kval.Uzvards;
res.Pavards := obj_kval.Pavards; res.Kvalifikacija := obj_kval.Kvalifikacija; res.Alga := obj_alga.Alga;
end if; end if;
30
return res; -- tiek atgriezts rezultāts end;
4.4. 4. vaicājums
Intervāla sadalīšanas (Unfold) realizācijas idejas pamats tiek paņemts no Viktorijas
Raizinas darba [1] (praktiskā darba 3. piemērs no piedāvātājiem). Pirmkārt jādefinē tips, kuru
atgriezīs funkcija UNFOLD. Funkcija atgriezīs laika periodu kolekciju, kurā katra perioda
ilgums būs viena diena. Tātad, tiek pieņemts, ka vienas laika granulas izmērs ir vienāds ar
1 dienu. Laika periods sastāv no diviem datumiem – no un līdz.
-- Objekta, kuru atgriezīs UNFOLD funkcija, tipsCreate or replace type LAIKA_PERIODI_T as table of LAIKA_PERIODS_T;
Funkcija UNFOLD saņem objektu MAKSAJUMS_T tipa, kas satur summu mēnesī un
laika periodu.
-- Funkcijas UNFOLD definīcijaCreate or replace function UNFOLD(maksajums in MAKSAJUMS_T) return LAIKA_PERIODI_T AS res LAIKA_PERIODI_T := LAIKA_PERIODI_T(); nakamais_datums Date := maksajums.NO; temp_datums Date := maksajums.NO; maksajums_LIDZ Date := maksajums.LIDZ; begin -- Vispirms jānoteic perioda gala robeža, kurš tiek sadalīts. If (maksajums_LIDZ IS NULL OR maksajums_LIDZ > SYSDATE) then
maksajums_LIDZ := SYSDATE - 1;end if;
WHILE (maksajums_LIDZ > nakamais_datums) LOOP res.extend; temp_datums := nakamais_datums; nakamais_datums := nakamais_datums + 1; -- Pievienot skaitli X datumam -- nozīmē pievienot X dienas res(res.count) := LAIKA_PERIODS_T(temp_datums, nakamais_datums);END LOOP;return res;
end UNFOLD;
31
4.5. 5.vaicājums
Objektu tipu definējumi:
-- Objekta tips, kas ietver Speletaja_ID un periodu, kad viņš spēlē komandāCreate or replace type OBJEKTS_5_PERIOD_T as object( Speletaja_ID Number(10, 0), Komandas_nosaukums Varchar2(20), NO Date, LIDZ Date);
-- Objekta tips, kas ietver datus par spēl., kvalifikāciju un laika perioduCreate or replace type OBJEKTS_5_KVAL_T as object( Speletaja_ID Number(10, 0), Vards Varchar2(20), Uzvards Varchar2(30), Pavards Varchar2(30), Kvalifikacija Varchar2(30), NO Date, LIDZ Date, MEMBER function PARKLAJAS(p_object in OBJEKTS_5_PERIOD_T) return number, ORDER MEMBER function SATIEK(p_object in OBJEKTS_5_KVAL_T) return number);
-- Objekta tips, kas izskaitļo un glabā sevi vaicājuma rezultātu.-- Rezultāts tiek izskaitļots, pielietojot konstruktoruCreate or replace type OBJEKTS_5_RESULT_T as object( Vards Varchar2(20), Uzvards Varchar2(30), Pavards Varchar2(30), Komandas_nosaukums Varchar2(20), Kvalifikacija_lidz Varchar2(30), Kvalifikacija_pec Varchar2(30), Izmaina Varchar2(35), Izmainas_datums Date, -- Konstruktora prototips CONSTRUCTOR FUNCTION OBJEKTS_5_RESULT_T( obj_kval_1 in OBJEKTS_5_KVAL_T, obj_kval_2 in OBJEKTS_5_KVAL_T, obj_period in OBJEKTS_5_PERIOD_T) RETURN SELF AS RESULT);
32
Skatu definējumi:
-- Skats ar OBJEKTS_5_PERIOD_T objektiemCreate or replace view SKATS_5_PERIOD of OBJEKTS_5_PERIOD_T with object identifier(Speletaja_ID) as Select A.Speletaja_ID, B.Nosaukums, A.Periods.NO, A.Periods.LIDZ FROM SPELETAJI A, KOMANDAS B Where A.Komandas_ID = B.Komandas_ID; -- Skats ar OBJEKTS_5_KVAL _T objektiemCreate or replace view SKATS_5_KVAL of OBJEKTS_5_KVAL_T with object identifier(Speletaja_ID, NO) as Select A.Speletaja_ID, Deref(A.Spel_dati).Speletaja_vardi.Vards, Deref(A.Spel_dati).Speletaja_vardi.Uzvards,
Deref(A.Spel_dati).Speletaja_vardi.Pavards,B.Kvalifikacija, B.NO, B.LIDZ
From SPELETAJI A, Table(Deref(A.Spel_dati).Kvalifikacijas) B;
Objektu tipu metožu ķermeņu definējumi:
-- OBJEKTS_5_KVAL_T ķermeņa definējums:Create or replace type body OBJEKTS_5_KVAL_T as MEMBER function PARKLAJAS(p_object in OBJEKTS_5_PERIOD_T) return number is begin if (((p_object.NO < self.LIDZ) OR (self.LIDZ is NULL)) AND
((self.NO < p_object.LIDZ) OR (p_object.LIDZ is NULL))) then return 1; else return 0; end if;
end PARKLAJAS; ORDER MEMBER function SATIEK(p_object in OBJEKTS_5_KVAL_T) return number is begin if (self.LIDZ = p_object.NO) then
return 1; else return 0; end if;
end SATIEK;end;
-- OBJEKTS_5_RESULT_T ķermeņa definējums:
33
-- Ķermenis satur konstruktora definējumu.Create or replace type body OBJEKTS_5_RESULT_T as CONSTRUCTOR FUNCTION OBJEKTS_5_RESULT_T( obj_kval_1 in OBJEKTS_5_KVAL_T, obj_kval_2 in OBJEKTS_5_KVAL_T, obj_period in OBJEKTS_5_PERIOD_T) RETURN SELF AS RESULT AS begin self.Vards := obj_kval_1.Vards; self.Uzvards := obj_kval_1.Uzvards; self.Pavards := obj_kval_1.Pavards; self.Komandas_nosaukums := obj_period.Komandas_nosaukums; self.Kvalifikacija_lidz := obj_kval_1.Kvalifikacija; self.Kvalifikacija_pec := obj_kval_2.Kvalifikacija;
-- Kvalifikācijas izmaiņas novērtējums if ((Kvalifikacija_lidz = 'Augsta') AND (Kvalifikacija_pec = 'Meistars'
OR Kvalifikacija_pec = 'Globala elite')) then self.Izmaina := 'Uzlabojas'; elsif (Kvalifikacija_lidz = 'Meistars') then
if (Kvalifikacija_pec = 'Augsta') then self.Izmaina := 'Pasliktinajas'; elsif (Kvalifikacija_pec = 'Globala elite') then self.Izmaina := 'Uzlabojas';
else self.Izmaina := 'Nepazistamas kvalifikacijas';
end if; elsif ((Kvalifikacija_lidz = 'Globala elite') AND (Kvalifikacija_pec = 'Meistars' OR Kvalifikacija_pec = 'Augsta')) then self.Izmaina := 'Pasliktinajas'; else self.Izmaina := 'Nepazistamas kval. izmaina';
end if;
self.Izmainas_datums := obj_kval_1.LIDZ;return;
end;end;
34
4.5.1. Java valodas izmantošana metožu definēšanai
To pašu uzdevumu pamēģināsim atrisināt, pielietojot Java programmēšanas valodu.
OBJEKTS_5_PERIOD_T objekta tipu iespējams atstāt to pašu, jo tas nesatur metodes.
OBJEKTS_5_KVAL_JAVA_T satur metodes, kurus realizēsim Java valodā.
-- Objekta tips, kas ietver datus par spēl., kvalifikāciju un laika periodu, kura metodes-- tiek definētas ar JavaCreate or replace type OBJEKTS_5_KVAL_JAVA_T as object( Speletaja_ID Number(10, 0), Vards Varchar2(20), Uzvards Varchar2(30), Pavards Varchar2(30), Kvalifikacija Varchar2(30), NO Date, LIDZ Date, MEMBER function PARKLAJAS(p_object OBJEKTS_5_PERIOD_T) return number as language Java
name 'ObjektsKvalifikacija.parklajas(oracle.sql.STRUCT) return oracle.sql.NUMBER',
MEMBER function SATIEK (o_object OBJEKTS_5_KVAL_JAVA_T) return number as language Java
name 'ObjektsKvalifikacija.satiek(oracle.sql.STRUCT) return oracle.sql.NUMBER');
Jāpārdefinē arī objekta tips, kura konstruktors izskaitļo rezultātu, jo konstruktors saņem
cita tipa objektus.
-- Objekta tips, kas izskaitļo un glabā sevi vaicājuma rezultātu.-- Resultāts tiek izskaitļots, pielietojot konstruktoruCreate or replace type OBJEKTS_5_RESULT_JAVA_T as object( Vards Varchar2(20), Uzvards Varchar2(30), Pavards Varchar2(30), Komandas_nosaukums Varchar2(20), Kvalifikacija_lidz Varchar2(30), Kvalifikacija_pec Varchar2(30), Izmaina Varchar2(35), Izmainas_datums Date, CONSTRUCTOR FUNCTION OBJEKTS_5_RESULT_JAVA_T ( obj_kval_1 in OBJEKTS_5_KVAL_JAVA_T, obj_kval_2 in OBJEKTS_5_KVAL_JAVA_T, obj_period in OBJEKTS_5_PERIOD_T) RETURN SELF AS RESULT );
35
Skatu definējumi:
-- Skats ar SKATS_5_KVAL_JAVA objektiemCreate or replace view SKATS_5_KVAL_JAVA of OBJEKTS_5_KVAL_JAVA_T with object identifier(Speletaja_ID, NO) as Select A.Speletaja_ID, Deref(A.Spel_dati).Speletaja_vardi.Vards, Deref(A.Spel_dati).Speletaja_vardi.Uzvards,
Deref(A.Spel_dati).Speletaja_vardi.Pavards,B.Kvalifikacija, B.NO, B.LIDZ
From SPELETAJI A, Table(Deref(A.Spel_dati).Kvalifikacijas) B;
Izmantosim iepriekš definēto skatu SKATS_5_PERIOD ar objektiem
OBJEKTS_5_PERIOD_T tipa.
Objektu tipu metožu ķermeņu definējumi:
Objektu tipa OBJEKTS_5_RESULT_JAVA_T ķermenis ir līdzīgs
OBJEKTS_5_RESULT_T objektu tipa ķermenim, izmainījās tikai parametru tipi.
Klases, kas realizē OBJEKTS_5_KVAL_JAVA_T objekta tipa metodes, apraksts Java
valodā :
Create or replace and compile Java source named "5_vaicajums_Java" asimport oracle.sql.STRUCT;import java.sql.*;import java.io.*;import oracle.sql.DATE;import java.lang.Object;import java.math.BigDecimal;
// implements SQLData ir vajadzīgs, lai Oracle DB objekts varētu būt pārveidots Java // klases objektāpublic class ObjektsKvalifikacija implements SQLData { private BigDecimal Speletaja_ID; private String Vards; private String Uzvards; private String Pavards; private String Kvalifikacija; private Date NO; private Date LIDZ; // Konstants objekts. Tiek piešķirts atribūtiem, kuriem datu bāzē ir NULL vērtības. // Piešķiršana jāizdara, lai Java metodes, piemēram compareTo normāli funkcionētu. private static final Date MAX_DATE = new Date(3000, 1, 1); // 01-01-3000 datums
36
// Metodes PARKLAJAS aprakst: public oracle.sql.NUMBER parklajas(oracle.sql.STRUCT p_object) { Object[] attributes; // Objektu masīvs ir vajadzīgs atribūtu izdalīšanai no // oracle.sql.STRUCT tipa objekta. DATE p_object_no; DATE p_object_lidz; // Laika perioda iegūšana no objekta p_object: try { attributes = p_object.getAttributes(); p_object_no = new DATE(attributes[2]); if (attributes[3] != null) p_object_lidz = new DATE(attributes[3]); else // Ja atribūta LIDZ vērtība = NULL, tad tai piešķiram konstantu // objektu MAX_DATE, kas ir definēts augstāk. p_object_lidz = new DATE(MAX_DATE); } catch (SQLException e) { // Ja kaut kas notika nepareizi, metode atgriež (-5) vērtību, // kuru autors izmantoja testiem. return new oracle.sql.NUMBER(-5); } DATE self_no = new DATE(this.NO); DATE self_lidz; if (this.LIDZ != null) self_lidz = new DATE(this.LIDZ); else self_lidz = new DATE(MAX_DATE); try { // Pārbaude, vai laika periodi pārklājās savā starpā: // Metode compareTo atgriež -1, ja izsaucoša objekta datums ir mazāks; // 0, ja datumi ir vienādi, un 1, ja izsaucošais ir lielāks. if ((p_object_no.compareTo(self_lidz) == -1) && (self_no.compareTo(p_object_lidz) == -1)) return new oracle.sql.NUMBER(1); else return new oracle.sql.NUMBER(0); } catch (NullPointerException e) { // Pārbaude, vai metodes izpildījās pareizi. return new oracle.sql.NUMBER(-6); } } // Metodes SATIEK apraksts: // Operatori ir līdzīgi, tāpēc komentārus lūdzu skatīt iepriekšējas metodes aprakstā. public oracle.sql.NUMBER satiek(oracle.sql.STRUCT p_object)
37
{ Object[] attributes; DATE p_object_no; try { attributes = p_object.getAttributes(); p_object_no = new DATE(attributes[5]); } catch (SQLException e) { return new oracle.sql.NUMBER(-5); }
DATE self_lidz; if (this.LIDZ != null) self_lidz = new DATE(this.LIDZ); else self_lidz = new DATE(MAX_DATE);
try { if (p_object_no.compareTo(self_lidz) == 0) return new oracle.sql.NUMBER(1); else return new oracle.sql.NUMBER(0); } catch (NullPointerException e) { return new oracle.sql.NUMBER(-6); } } String sql_type; // atribūts ir vajadzīgs SQLData implementācijai
// Pārējās metodes jāpārdefinē, lai SQLData implementācija būtu pilnīga
public String getSQLTypeName() throws SQLException { return sql_type; } // Metode atribūtu inicializēšanai. Atribūti jāinicialīze, // tāpēc ka ar tiem strādā metodes objekta atribūtiem. public void readSQL(SQLInput stream, String typeName) throws SQLException { sql_type = typeName; Speletaja_ID = stream.readBigDecimal(); Vards = stream.readString(); Uzvards = stream.readString(); Pavards = stream.readString(); Kvalifikacija = stream.readString(); NO = stream.readDate(); LIDZ = stream.readDate(); }
38
// Metode nestrādā mūsu uzdevumā, bet joprojām tā jāpārdefinē public void writeSQL(SQLOutput stream) throws SQLException { stream.writeBigDecimal(Speletaja_ID); stream.writeString(Vards); stream.writeString(Uzvards); stream.writeString(Pavards); stream.writeString(Kvalifikacija); stream.writeDate(NO); stream.writeDate(LIDZ); }
}
4.6. 6. vaicājums
Lai realizētu laika intervālu apvienojumu, tiek nolemts definēt agregāt-funkciju, kurā
tiek izrēķināta laika periodu kopa, kura atbilst vairāku laika periodu apvienojumam.
Vispirms jādefinē objekta tips ar metodēm - laika predikātiem, kurus izmantos agregāt-
funkcija. Vispirms autoram bija ideja, ka funkcijas realizācijai būs nepieciešami vairāki
Allena operatori: X PIRMS Y, X SATIEK Y, X PARKLAJ Y. Bet izrādās, ka pietiek ar X
PIRMS Y.
-- Objekta tips, kas satur laika perioda datusCreate or replace type OBJEKTS_6_PERIOD_T as object( NO Date, LIDZ Date, MEMBER function PIRMS(p_object in OBJEKTS_6_PERIOD_T) return number);
-- Objekta tipa OBJEKTS_6_PERIOD_T ķermenisCreate or replace type body OBJEKTS_6_PERIOD_T as MEMBER function PIRMS(p_object in OBJEKTS_6_PERIOD_T) return number is begin if (self.LIDZ IS NOT NULL AND self.LIDZ < p_object.NO) then
return 1; else return 0; end if;
end PIRMS;end;
-- Objekta, kuru atgriezis agregat-funkcija, tips (periodu kolekcija)Create or replace type OBJEKTS_6_PERIODI_T as table of OBJEKTS_6_PERIOD_T;
39
Agregāt-funkcijas definējums:
Lai izveidotu agregācijas funkciju, vispirms jāizveido interfeiss, kas satur
ODCIAggregate rutīnas. Interfeiss pēc savas būtības ir objekta tips ar metodēm, kuri apraksta
rutīnas.
-- Objekta tips, kas realizē agregācijas funkcijas darbībuCreate or replace type LaikaPerioduApveinojumaRutinas as object( res OBJEKTS_6_PERIODI_T, -- rezultāta laika periodu kolekcija -- ODCIAggregateInitialize - metode inicializē objektu. -- Mūsu gadījumā jāinicializē objekts res, kas ir laika periodu kolekcija Static function ODCIAggregateInitialize( sctx IN OUT LaikaPerioduApveinojumaRutinas) return number, -- ODCIAggregateIterate - metode definē, kas jādara ar kārtējo ierakstu MEMBER FUNCTION ODCIAggregateIterate( self IN OUT LaikaPerioduApveinojumaRutinas, p_object in OBJEKTS_6_PERIOD_T) return number,
-- ODCIAggregateTerminate metode apraksta, kas jādara, -- kad tika apstrādāti visi ieraksti MEMBER FUNCTION ODCIAggregateTerminate( self IN LaikaPerioduApveinojumaRutinas, return_object OUT OBJEKTS_6_PERIODI_T, flags IN number)
return Number, -- ODCIAggregateMerge apraksta, kā apvienot rezultātus, ja funkcijas -- izpildes process tiek izpildīts paralēli. Šī metode netiks pielietota darbā, jo datu -- daudzums nav pietiekami liels, lai aprēķinus vajadzētu darīt paralēli, -- bet metodes realizācija prasa papildus pūļus. MEMBER FUNCTION ODCIAggregateMerge( self IN OUT LaikaPerioduApveinojumaRutinas, ctx2 IN LaikaPerioduApveinojumaRutinas) return number);
Create or replace type body LaikaPerioduApveinojumaRutinas as Static function ODCIAggregateInitialize( sctx IN OUT LaikaPerioduApveinojumaRutinas) return number is begin -- inicializējam rezultāta objektu kā tukšu kolekciju sctx := LaikaPerioduApveinojumaRutinas(OBJEKTS_6_PERIODI_T());
return ODCIConst.Success; -- ar šo operatoru beidzās metodes izpilde end ODCIAggregateInitialize;
40
MEMBER FUNCTION ODCIAggregateIterate( self IN OUT LaikaPerioduApveinojumaRutinas, p_object in OBJEKTS_6_PERIOD_T) return number is i Number; n Number; m Number; begin i := 1; while (i <= res.count AND res(i).PIRMS(p_object) = 1) loop
i := i + 1;end loop;if (i > res.count) then -- ieraksta periods ir pēc visiem periodiem, -- kas atrodas rezultāta kolekcijā res.extend; res(i) := p_object; -- ievietojām periodu kolekcijas beigāselsif (p_object.PIRMS(res(i)) = 1) then -- ieraksta periods atrodas -- starp kolekcijas periodiem res.extend; -- Jāpārvieto elementi par vienu ierakstu uz priekšu... for n IN REVERSE (i + 1)..res.count loop res(n) := res(n - 1); end loop; -- ...un atbrīvotājā vietā ielikt jauno elementu res(i) := p_object;else -- ieraksta periods pārklāj vai satiek kolekcijā esošo periodu
-- (vai kolekcijas periods satiek vai pārklāj ieraksta periodu) if (res(i).NO > p_object.NO) then res(i).NO := p_object.NO; -- no abiem NO izvēlamies mazāko (agrāko) end if; if (res(i).LIDZ IS NOT NULL) then if (p_object.LIDZ IS NULL OR p_object.LIDZ > res(i).LIDZ) then res(i).LIDZ := p_object.LIDZ; -- no abiem LIDZ izvēlamies lielāko
if (res(i).LIDZ IS NULL) then res.trim(res.count - i); -- izdzēst visus elementus kas atrodas
-- pēc res(i), jo res(i).LIDZ = NULL -- => visi elementi pēc res(i) ietilpst
-- elementā res(i) end if; -- ja iepriekšēja operācija izpildās, tad vajag pārbaudīt, vai -- kolekcijā esošus laika periodus nevajag apvienot n := i + 1; while (n <= res.count) loop if (res(i).PIRMS(res(n)) = 0) then -- res(i) vai nu
-- satiek, vai nu pārklāj vai nu ietver res(n) if (res(n).LIDZ IS NULL OR res(n).LIDZ > res(i).LIDZ) then
41
res(i).LIDZ := res(n).LIDZ; end if; if (res(i).LIDZ IS NULL) then
res.trim(res.count - i); else -- jāizdzēš res(n)-to elementu un jāpārvieto visus kolekcijas
-- elementus par vienu ierakstu atpakaļ for m IN n..(res.count - 1) loop res(m) := res(m + 1); end loop;
-- un jāatbrīvo vieta kolekcijā res.trim; end if;
else n := res.count + 1; -- cikla izpildes pabeigšanaend if;
end loop; end if;
end if;end if;
return (odciconst.success); -- ar so operatoru beidzas metodes izpilde end ODCIAggregateIterate; MEMBER FUNCTION ODCIAggregateTerminate( self IN LaikaPerioduApveinojumaRutinas, return_object OUT OBJEKTS_6_PERIODI_T, flags IN number)
return Number is begin return_object := self.res;
return (odciconst.success); -- ar šo operatoru beidzas metodes izpilde end ODCIAggregateTerminate; MEMBER FUNCTION ODCIAggregateMerge( self IN OUT LaikaPerioduApveinojumaRutinas, ctx2 IN LaikaPerioduApveinojumaRutinas) return number is begin return ODCIConst.Success; -- tikai return operators, jo paralēlu izpildi nelietosim end ODCIAggregateMerge;end;
Kad interfeiss tiek izveidots, varam definēt agregācijas funkciju:
-- Agregācijas funkcijas definīcijaCreate or replace function APVIENOJUMS(input OBJEKTS_6_PERIOD_T) return OBJEKTS_6_PERIODI_T
42
AGGREGATE USING LaikaPerioduApveinojumaRutinas;
Nekādas objektu metodes vairs nav vajadzīgas, tāpēc šim vaicājumam netiek definēts
objektu skats.
43
5. Vaicājumu realizēšana
5.1. 1 vaicājums
Uzzināt, kādas kvalifikācijas ir spēlētājiem noteiktajā datumā.
Uzzināsim, kādas kvalifikācijas bija spēlētājiem 10. martā 2014. gadā (10-03-2014):
-- Vaicājums:Select A.Vards, A.Uzvards, A.Pavards, A.KvalifikacijaFrom SKATS_1 AWhere Value(A).SATUR(to_date('10-03-2014', 'DD-MM-RRRR')) = 1;
Rezultāts:
Pārbaudīsim rezultātu. Datu bāzē ir dati par 9 spēlētājiem, un par visiem spēlētājiem
bija izvadīti rezultāti. Pārrakstīsim vaicājumu, lai redzētu laika periodus, kuros spēlētājiem ir
tāda kvalifikācija, un pārbaudīsim, vai tiešām šis periods ietver datumu 10-03-2014.
-- PārbaudeSelect A.Vards, A.Uzvards, A.Pavards, A.Kvalifikacija, A.No, A.LIDZFrom SKATS_1 AWhere Value(A).SATUR(to_date('10-03-2014', 'DD-MM-RRRR')) = 1;
Tiešām, laika intervāli ietver datumu. Tātad vaicājuma izpildes rezultāts ir korekts.
44
5.2. 2. vaicājums
Atrast reklamētus produktus, kuriem pēc iepriekšējā kontrakta pabeigšanas, uzreiz bija
parakstīts jauns kontrakts. Parādīt iepriekšēja kontrakta sākuma datumu, „satikšanas”
datumu un jauna kontrakta beigšanas datumu.
-- Vaicājums:Select A.Produkta_ID, A.Nosaukums, A.NO, A.LIDZ as Satiksanas_punkts, B.LIDZFrom SKATS_2 A, SKATS_2 B -- paņemam vienu un to pašu tabulu divas reizesWhere A.Produkta_ID = B.Produkta_ID AND Value(A).SATIEK(Value(B)) = 1;
Rezultāts:
Pārbaudīsim rezultātu. Visvieglāk būtu apskatīt tabulu ar visiem datiem un atrast rindiņu
pārus, kuriem ir vienādi produkta nosaukumi un pirmā ieraksta LIDZ atribūta vērtība ir
vienāda ar otrā NO atribūta vērtību.
Select A.Produkta_ID, A.Sponsora_ID, A.Nosaukums, B.Summa_menesi, B.NO, B.LIDZFrom PRODUKTI A, Table(A.Maksajumi) B;
Tā kā apvestie ar rāmīšiem datumi sakrīt ar datumiem, kuri ir ierakstīti kolonā
SATIKSANAS_PUNKTS, varam secināt, ka vaicājums bija izpildīts korekti.
45
5.3. 3.vaicājums
Uzzināt spēlētāja atalgojuma vēsturi.
Uzzināsim spēlētāja, kura pavārds ir Gercegs, atalgojuma vēsturi:
-- Select vaicājums:Select E.res.Vards, E.res.Uzvards, E.res.Pavards, E.res.Kvalifikacija, E.res.Alga, E.res.NO, E.res.LIDZFrom (Select REIZINAJUMS(Value(A), Value(B), Value(C)) as res From SKATS_3_ALGA A, SKATS_3_KVAL B, SKATS_3_SPEL C
Where B.Pavards = 'Gercegs' AND B.Speletaja_ID = C.Speletaja_ID AND A.Komandas_ID = C.Komandas_ID AND A.Kvalifikacija = B.Kvalifikacija ) E
Where E.res.Vards IS NOT NULLOrder By E.res.NO; -- lai rindiņas būtu sakārtoti pēc datuma
Rezultāts:
Rezultāta pārbaude. Grafiski attēlošu spēlētāja Gercegs atalgojuma vēsturi, balsoties uz
datiem no tabulām SPELETAJI, DATI_PAR_SPELETAJIEM, ATALGOJUMI. Attēlā uz
laika ass mērogs 1 dalījums = 1 mēnesis.
Salīdzinot datus no attēla un no rezultāta tabulas, varam secināt, ka vaicājums izpildījās
veiksmīgi.
Vēl būtu labi pārbaudīt, vai vaicājums izpildās korekti, ja spēlētājs pārtrauc spēlēšanu
komandā. Kad spēlētājs pārtrauc savu karjeru, viņa atalgojuma vēsturei arī jābeidzas.
46
Uzzināsim spēlētāja, kura pavārds ir Koks, atalgojuma vēsturi (vaicājuma izmainās tikai
spēlētāja pavards apakšvaicājuma Where nodaļā):
-- Select vaicājums:Select E.res.Vards, E.res.Uzvards, E.res.Pavards, E.res.Kvalifikacija, E.res.Alga, E.res.NO, E.res.LIDZFrom (Select REIZINAJUMS(Value(A), Value(B), Value(C)) as res From SKATS_3_ALGA A, SKATS_3_KVAL B, SKATS_3_SPEL C
Where B.Pavards = 'Koks' AND B.Speletaja_ID = C.Speletaja_ID AND A.Komandas_ID = C.Komandas_ID AND A.Kvalifikacija = B.Kvalifikacija ) E
Where E.res.Vards IS NOT NULLOrder By E.res.NO; -- lai rindiņas būtu sakārtoti pēc datuma
Rezultāts:
Tiešām, Koks sāka spēlēt 01-05-2014 un pabeidz spēlēt 30-10-2014. No 01-02-2014
līdz mūsdienām viņš bija Meistars. Tā kā periods [01-05-2014, 30-10-2014) ietilpst periodā,
kad Koks bija Meistars, izvadīta kvalifikācija arī ir pareiza. Komandā Rallied, kurā spēlēja
Koks, alga meistariem laika periodā [01-05-2014, 15-10-2014) bija 1500 dolāri, un pēc tam
tika samazināta līdz 1250 dolāri. Tāpēc vaicājums arī šajā gadījuma tiek izpildīts korekti.
5.4. 4. vaicājums
Uzzināt, kādu naudas summu līdz mūsdienām nopelnīja komanda, reklamējot
produktus. Uzzināt naudas summu par produktiem atsevišķi un kopējo summu no sponsora.
Apskatīsim datus par komandu „Rallied”. Summu izskaitļošanai izmantosim klona
tabulas. Tiek pieņemts, ka norādīta kontraktā summa mēnesī par produkta reklamēšanu
nozīmē maksājumu par 30 dienām. Tātad, par 31. dienu tiek samaksāts papildu 1/30 daļa no
summas.
-- Vaicājums:Select C.Nosaukums as Sponsors, A.Nosaukums as Produkts, B.Summa_menesi as Summa_menesi, (Round(0.03333 * Sum(B.Summa_menesi) OVER(Partition by A.Produkta_ID), 2))
as Nopelnits_no_produkta, (Round(0.03333 * Sum(B.Summa_menesi) OVER(Partition by A.Sponsora_ID), 2))
as Nopelnits_no_sponsora, u.NO, u.LIDZ
47
From PRODUKTI A, Table(A.Maksajumi) B, Table(UNFOLD(Value(B))) u, SPONSORI C, KOMANDAS DWhere A.Sponsora_ID = C.Sponsora_ID AND D.Komandas_ID = C.Komandas_ID AND D.Nosaukums = 'Rallied'Order by C.Nosaukums, A.Nosaukums, u.NO;
Rezultāts satur 525 rindiņas, jo katrai rindiņai atbilst laika periods ar ilgumu = 1 diena.
Tā arī bija ieplānots, tāpēc apskatīsim rezultātu pa daļām:
No kolonu NO un LIDZ vērtībām ir redzams, ka UNFOLD funkcija izpildīja savu darbu
un laika periodi ir sadalīti laika granulās ar izmēru = 1 diena.
Apskatīsim, vai laika periods pilnīgi tiek atspoguļots:
Redzams, ka 90. ieraksts ir pēdējais, kad SUMMA_MENESI atribūta vērtība ir vienāda
ar 5000. 91. ieraktā tā jau ir vienāda ar 7000. Ir redzams, ka 90. ieraksta LIDZ vērtība ir
vienāda ar 91. ieraksta NO vērtību, kā arī jābūt. Datumu vērtības arī ir pareizās.
Apskatīsim, vai produkta „Audi A6” reklamēšanas kontrakta pēdējais datums ir
atspoguļots korekti:
Jā, „Audi A6” reklamēšanas kontrakts tiešām beidzas 15-06-2014, un pēc tam tiek
izvadīti dati par produktu „Audi A8”.
Apskatīsim, kā funkcija UNFOLD rīkojas, kad LIDZ atribūta vērtība ir NULL:
48
„Audi A8” patlaban tiek reklamēts, bet pēdējām ierakstam līdz vērtība ir šodienas
datums (28-10-2014). Viss pareizi, jo mēs gribējām uzzināt naudu summas, kurus komanda
jau bija nopelnījusi. Turklāt, ja nav perioda gala robežas, tad funkcijas UNFOLD darbība būtu
bezgalīga.
Tātad, par to, ka funkcija UNFOLD strādā korekti, esam pārliecinājušies. Tagad vajag
apskatīt analītisko funkciju darbību rezultātus. Pārrakstīšu vaicājumu, lai ar to būtu ērtāk
strādāt (sadalītu periodu vietā izvadīsim pilnus intervālus, taču summas joprojām tiek
izskaitļotas, apskatot visas 525 rindiņas):
-- Ērtākais vaicājums:Select DISTINCT C.Nosaukums as Sponsors, A.Nosaukums as Produkts, B.Summa_menesi as Summa_menesi, (Round(0.03333 * Sum(B.Summa_menesi) OVER(Partition by A.Produkta_ID), 2)) as
Nopelnits_no_produkta, (Round(0.03333 * Sum(B.Summa_menesi) OVER(Partition by A.Sponsora_ID), 2))
as Nopelnits_no_sponsora, B.NO, B.LIDZFrom PRODUKTI A, Table(A.Maksajumi) B, Table(UNFOLD(Value(B))) u, SPONSORI C, KOMANDAS DWhere A.Sponsora_ID = C.Sponsora_ID AND D.Komandas_ID = C.Komandas_ID
AND D.Nosaukums = 'Rallied'Order by C.Nosaukums, A.Nosaukums, u.NO;
Rezultāts:
NOPELNITS_NO_PRODUKTA atbilst naudas summai, kuru komanda „Rallied”
nopelnīja, reklamējot produktu ar nosaukumu PRODUKTS. NOPELNITS_NO_SPONSORA
ir naudas summa, kuru komanda nopelnīja, reklamējot sponsora produkciju. Pārbaudīsim
rezultātus par sponsoru „Audi” ar tuvinātiem aprēķiniem.
1) Audi A6 par 5000 dolāriem mēnesī tiek reklamēts periodā
[01-01-2014, 01-04-2014) ~ 3 mēnešus; 5000 * 3 = 15000.
2) Audi A6 par 7000 dolāriem mēnesī tiek reklamēts periodā
[01-04-2014, 15-06-2014) ~2.5 mēnešus; 7000 * 2.5 = 17500.
3) Audi A8 par 1250 dolāriem mēnesī tiek reklamēts periodā
[01-05-2014, 01-06-2014) ~ 1 mēnesi; 1250 * 1 = 1250.
49
4) Audi A8 par 3000 dolāriem mēnesī tiek reklamēts periodā
[01-08-2014, 28-10-2014) ~2.9 mēnešus; 3000 * 2.9 = 8700.
15000 + 17500 = 32500 ~ 32496.75 – nopelnīts, reklamējot Audi A6 (pareizi)
1250 + 8700 = 9950 ~ 10090.66 – nopelnīts, reklamējot Audi A8 (pareizi)
32500 + 9950 = 42450 ~ 42587.41 – saņemts no sponsora „Audi” (pareizi).
Tā kā aprēķini bija aptuveni, tiek konstatēta nebūtiskā atšķirība starp rezultātiem, taču
rezultāti ir pareizi.
Vēl gribu pievērst uzmanību sekojošam:
1. un 2. taisnstūrī vērtības ir vienādas. Tas ir tāpēc, ka bija izrēķināta summa, grupējot
ierakstus pēc produkta_ID: Sum(B.Summa_menesi) OVER(Partition by A.Produkta_ID).
Tā kā 1. un 2. rindiņām (1. sarkans taisnstūris) produkts ir viens un tas pats, summas arī ir
vienādas.
3. taisnstūrī arī ir vienādas vērtības un pats taisnstūris ir lielāks. Tas ir tāpēc, ka bija
izrēķināta summa, grupējot ierakstus pēc sponsora_ID, un sponsoram ir vairāki produkti:
Sum(B.Summa_menesi) OVER(Partition by A.Sponsora_ID).
Izmantojot klona tabulas, paliek iespēja apskatīt atsevišķas naudas vērtības kolonā
SUMMA_MENESI.
50
5.5. 5. vaicājums
Uzzināt, kā spēlēšana komandā ietekmēja spēlētāja kvalifikāciju. Parādīt kvalifikācijas
izmaiņas datumu.
-- Vaicājums:Select E.res.Vards as Vards, E.res.Uzvards as Uzvards, E.res.Pavards as Pavards, E.res.Komandas_nosaukums as Komanda, E.res.Kvalifikacija_lidz as Kval_lidz, E.res.Kvalifikacija_pec as Kval_pec, E.res.Izmaina as Izmaina, E.res.Izmainas_datums as Izmainas_datumsFrom (Select OBJEKTS_5_RESULT_T(Value(A), Value(B), Value(C)) as res From SKATS_5_KVAL A, SKATS_5_KVAL B, SKATS_5_PERIOD C
Where Value(A).Speletaja_ID = Value(B).Speletaja_ID AND Value(B).Speletaja_ID = Value(C).Speletaja_ID AND Value(A).PARKLAJAS(Value(C)) = 1 AND -- Pārklājums starp kvalifikācijas
-- sēriju un spēlēšanas sēriju. Value(B).PARKLAJAS(Value(C)) = 1 AND -- tas pats Value(A).SATIEK(Value(B)) = 1 -- Viens kvalifikācijas periods satiek citu. ) E;
Rezultāts:
Rezultāta pārbaude:
Kolonā IZMAINA ir spēlētāja kvalifikācijas izmaiņas novērtējums. 1. ierakstā
KVAL_LIDZ = ‘Augsta’ un KVAL_PEC = ‘Meistars’. Tātad spēlētāja kvalifikācija
izmainījās no „Augsta” uz „Meistaru” un IZMAINA atribūta vērtība ir „Uzlabojas” - tas ir
pareizi.
2. ieraksta kvalifikācija izmainījās no ‘Meistara’ uz ‘Augsto’, tātad pasliktinājās, par ko
arī pateic atribūts IZMAINA. Kvalifikācijas izmaiņas novērtējums nostrādāja korekti arī
citiem ierakstiem.
Pārbaudīju arī kvalifikāciju izmaiņu datumus - tie ir korekti. Visi ieraksti, kuriem bija
jābūt atspoguļotiem - ir atspoguļoti. Ja spēlētājam mainījās kvalifikācija, bet šis spēlētājs tajā
laikā nespēlēja komandā, tad informācija par to netika atspoguļota vaicājuma rezultātā, kā arī
bija vajadzīgs.
Pēc pārbaudes varu secināt, ka vaicājuma rezultāts ir pareizs.
51
5.5.1. Vaicājuma izpilde ar Java valodā aprakstītām metodēm
Vaicājums ir līdzīgs, jāizmaina tikai skatu nosaukumu un rezultāta objekta tipa
nosaukums. Rezultātam jābūt tādam pašam, kāds bija iegūts ar vaicājumu, kura realizācijai
netiek izmantota Java.
-- Vaicājums:Select E.res.Vards as Vards, E.res.Uzvards as Uzvards, E.res.Pavards as Pavards, E.res.Komandas_nosaukums as Komanda, E.res.Kvalifikacija_lidz as Kval_lidz, E.res.Kvalifikacija_pec as Kval_pec, E.res.Izmaina as Izmaina, E.res.Izmainas_datums as Izmainas_datumsFrom (Select OBJEKTS_5_RESULT_JAVA_T(Value(A), Value(B), Value(C)) as res From SKATS_5_KVAL_JAVA A, SKATS_5_KVAL_JAVA B, SKATS_5_PERIOD C
Where Value(A).Speletaja_ID = Value(B).Speletaja_ID AND Value(B).Speletaja_ID = Value(C).Speletaja_ID AND Value(A).PARKLAJAS(Value(C)) = 1 AND -- Pārklājums starp kvalifikācijas
-- sēriju un spēlēšanas sēriju. Value(B).PARKLAJAS(Value(C)) = 1 AND -- Tas pats. Value(A).SATIEK(Value(B)) = 1 -- Viens kvalifikācijas periods satiek citu. ) E;
Rezultāts:
Salīdzinot rezultātus, varam secināt, ka tie ir ekvivalenti. Tātad vaicājums izpildījās
pareizi ar Java valodā aprakstītām metodēm
52
5.6. 6. vaicājums
Noteikt laika periodu, kurā sponsors maksā komandai, apvienojot laika periodus, kuros
sponsors maksā par noteiktiem produktiem. Ja rezultātā tiek iegūts vairāk par vienu periodu -
atspoguļot visus laika periodus.
Uzzināsim informāciju par visām komandām un visiem sponsoriem:
-- VaicajumsSelect F.Nosaukums as Komanda, E.Nosaukums as Sponsors, D.NO, D.LIDZFrom (Select A.Sponsora_ID as Sp_ID, APVIENOJUMS(OBJEKTS_6_PERIOD_T(B.NO, B.LIDZ)) as Apvienojums From PRODUKTI A, Table(A.Maksajumi) B Group By Sponsora_ID) C, Table(C.Apvienojums) D, SPONSORI E, KOMANDAS FWhere E.Sponsora_ID = C.Sp_ID AND E.Komandas_ID = F.Komandas_ID;
Ar apakšvaicājumu tiek iegūti ieraksti ar sponsora ID un periodu kolekcijām (periodu
apvienojumu), kuros sponsors maksā komandai par reklāmu. Agregācijas funkcija
APVIENOJUMS saņem objektu, kura tips ir OBJEKTS_6_PERIOD_T, tāpēc lauku B.NO un
B.LIDZ pāris pārveidots šī tipa objektā. Lai Agregācijas funkcija nostrādātu, ieraksti tiek
sagrupēti pēc Sponsora ID.
Vaicājuma rezultāts:
Vaicājuma rezultāta pārbaude:
Attēlošu grafiski laika periodus, kuros tiek reklamēta sponsora „Audi” produkcija.
53
Attēlā otrajam periodam vēl nav zināms beigšanas datums. Rezultāts, kuru mēs ieguvām
ar grafisko attēlojumu atbilst vaicājuma rezultātam.
Izanalizējot pārējos apvienojuma rezultātus un datus no tabulas PRODUKTI, varu
secināt, ka vaicājums izpildījās pareizi - laika periodi bija veiksmīgi apvienoti. Rezultātos
redzam, ka sponsoriem „Audi” un „Razer” ir pa diviem ierakstiem. Tā arī jābūt, jo
apvienojuma rezultāts satur vairāk par vienu laika periodu (1. ieraksta laika periods ir PIRMS
2. ieraksta laika perioda, pēc Allena operatoriem).
Kopumā vaicājums ir izpildīts veiksmīgi.
Pastāv arī iespēja izmantot definēto agregācijas funkciju kopā ar klona tabulas
tehnoloģiju. Piemēram:
-- VaicājumsSelect F.Nosaukums as Komanda, E.Nosaukums as Sponsors, C.NO, C.LIDZ, D.NO as Apvien_NO, D.LIDZ as Apvien_LIDZFrom (Select A.Sponsora_ID as Sp_ID, B.NO, B.LIDZ, APVIENOJUMS(OBJEKTS_6_PERIOD_T(B.NO, B.LIDZ))
OVER (PARTITION BY A.Sponsora_ID) as Apvienojums From PRODUKTI A, Table(A.Maksajumi) B ) C, Table(C.Apvienojums) D, SPONSORI E, KOMANDAS FWhere E.Sponsora_ID = C.Sp_ID AND E.Komandas_ID = F.Komandas_ID AND F.Nosaukums = 'Rallied';
Rezultāts:
Funkcija strādā korekti kopā ar klona tabulu, tomēr izmantot to nav ērti, jo, ja rezultāta
laika periodu kolekcija satur vairāk par vienu elementu, tad pārējo atribūtu vērtības dublējas
(piemēram, kā 1. un 2. rindiņas rezultātā). Savukārt, rezultāts par sponsoru „Red Bull” ir
skaists, jo apvienojums atdeva vienu periodu.
54
6. Struktūru salīdzinājums temporālā DB un vaicājuma
pieraksta vienkāršības novērtējums
Glabāšanas struktūras.
Tabulu ar kolonu, kurā glabājas objekts, kas atspoguļo laika periodu, ir ērti izmantot
gadījumā, kad vienam subjektam atbilst viens laika periods. Piemēram, visi spēlētāji spēlē
tikai vienā komandā nepārtrauktu laika periodu. Šai struktūrai lielākais trūkums ir
neelastīgums. Savukārt, ar to viegli strādāt. Līdzīgi ir ar tabulu, kurā laika periods tiek
atspoguļots ar diviem atribūtiem NO un LIDZ. Darbā šī struktūra nebija realizēta. Vispār
priekšrocība izmantot objektus ir tāda, ka laika perioda tipam ir iespēja piešķirt metodes, kas,
piemēram, varētu realizēt Allena laika predikātus.
Tabula ar objektu kolekciju kolonā ir labāka par tabulu ar objektu kolonā, jo pastāv
iespēja vienam subjektam piešķirt laika apakšsēriju, nedublējot datus par subjektu (nedublējot
datus, kuri neatspoguļo laika periodu). Piemēram, kā ir parādīts attēlā augšā, vienai
kvalifikācijai var izveidot vairākus atalgojumus, kuri ir atšķirīgi dažādos laika periodos.
55
Vēl pastāv iespēja veidot objektu tabulu. Objekta struktūra var būt vai vienkārša, vai
sarežģīta – piemēram, objektā var iekļaut objektu kolekciju. Ar tādu glabāšanas struktūru
sarežģītāk strādāt, nekā ar visām iepriekš aprakstītām struktūrām, taču iespējas arī tiek
paplašinātas. Labums no tādas struktūras ir tāds, ka objekti atrodas atsevišķi no tabulām ar
vienkārša tipa atribūtiem, bet uz šiem objektiem var atsaukties no jebkuras tabulas. Darbā
dažu vaicājumu realizācijā vajadzēja atsaukties uz objektiem objektu tabulā, un bija jāpadomā
kā pareizi pierakstīt komandas, kā pareizi izmantot operatoru Deref(), lai dabūtu vajadzīgo.
Pieraksta piemērs: From Table(Deref(A.Spel_dati).Kvalifikacijas) B.
Kopumā, glabāšanas struktūras izvēle ir atkarīga no vajadzībām. Jācenšas sameklēt
risinājumu, kas atbilst visām prasībām un kuru, pēc iespējas, ir vienkāršāk realizēt. Tātad
jācenšas, lai darbs būtu efektīvs.
Vaicājumu pieraksta vienkāršība.
Visvienkāršāk un visefektīvāk strādāt ar temporāliem vaicājumiem, kad vajadzīgas
darbības (temporālas algebras darbības un citas) tiek izpildītas metodes vai funkcijas iekšienē.
Laika predikātus vienkāršāk realizēt kā metodes, kas atgriež 0 vai 1, un izmantot vaicājuma
Where daļā. Ja jārealizē sarežģītākas darbības, piemēram, laika periodu reizinājums,
apvienojums, sadalīšana, tad labāk, lai funkcija vai metode atgrieztu objektu, kas satur
rezultātam vajadzīgus datus, un Select daļā paņemt no objekta šos datus.
56
Secinājumi
Darba gaitā bija izstrādāta temporālo datu DB. Darbs koncentrējas uz laika sērijām, to
glabāšanas struktūru izveidi, temporālās algebras darbībām un laika predikātiem. Darbā tiek
pielietotas RODB struktūras un koncepcijas. Datu glabāšanai tiek veidoti: tabula ar objektu
kolonā, tabulas ar kolekciju kolonā, objektu tabula. Vaicājumu realizācijai tiek pielietoti:
objekti; objektu metodes (arī Java); objektu skati; funkcijas, kas apstrādā objektus un atgriež
rezultāta objektus.
Temporālās algebras pamatdarbības. Darbā tiek realizēta atlase, reizinājums,
apvienojums un intervāla sadalīšana. Projekcija ir klāt visos vaicājumos, jo mēs vienmēr
izvēlamies, kādus tabulas atribūtus attēlot rezultātā. Visām darbībām, izņemot sadalīšanu
(Unfold), bija jārealizē kādi Allena laika predikāti. Uz laika predikātiem balstās atlase;
reizinājums izmanto X PARKLAJ Y predikātu; apvienojums izmanto X PIRMS Y predikātu.
Sadalīšanas realizācija tieši neizmanto Allena operatorus, bet atgriež laika periodu kolekciju,
kur katrs laika periods SATIEK pēcteča laika periodu (izņemot pēdējo). Tātad divu laika
periodu savstarpējas attiecības ir pamats darbam ar temporālo DB.
Reizinājuma realizācija (3. vaicājums [5.3]). Darbā bija jāsareizina trīs laika sērijas.
Reizinājums tiek realizēts kā funkcija, kura saņem trīs objektus, kuri satur laika periodus.
Funkcija atgriež objektu, kas satur vajadzīgus datus un rezultāta laika periodu. Neskatoties uz
to, ka reizinājums ir realizēts, kā funkcija, nevis kā objekta metode, tā izpilda savu darbu, un
pieraksts vaicājumā nav sarežģīts.
Laika perioda sadalīšanas realizācija (4. vaicājums [5.4]). Realizācijas idejas pamats
tiek paņemts no Viktorijas Raizinas darba [1]. Autors uzzināja par to, ka PL/SQL funkcija var
arī atgriezt objektu kolekciju. Vaicājumā realizācijai kopā ar sadalījumu bija pielietota klona
tabulas tehnoloģija, lai saskaitītu naudas summas. Sadalījums un klona tabula parādīja labu
kopdarbību vaicājuma reailizācijā.
Laika periodu apvienojuma realizācija (6. Vaicājums [5.6]). Vaicājuma realizācijas
gaitā bija iemācīts definēt savu agregācijas funkciju. Bija izdomāts apvienojuma algoritms.
Rezultātā vaicājumu izdodas realizēt. Bija arī pārbaudīts, kā lietotāja definēta agregācijas
funkcija strādā ar klona tabulu. Tā strādā korekti.
Metožu definējums. Bija secināts, ka atlases realizācijai ļoti lietderīgi definēt objekta
tipu ar metodēm, kuri realizē vajadzīgus Allena operatorus. Pēc tam jāizveido skats ar
57
definēta tipa objektiem, un beigās izpildīt vaicājumu. Tāda pieeja ir efektīva, un vaicājuma
pieraksts ir skaidrs.
Metožu definējums Java valodā (5. Vaicājums [4.5.1]). Darbā viena vaicājuma
izpildei metodes bija definētas gan PL/SQL, gan Java valodā. Vaicājuma izpildes rezultāti
abos gadījumos bija vienādi. Ar Java programmas uzglabāšanu serverī bija problēma – Oracle
11g Express Edition datu bāzei nav Java virtuālas mašīnas, un tāpēc, lai izpildītu uzdevumu,
bija vajadzīgs „migrēt” uz Oracle 11g Enterprise Edition datu bāzi. Tā kā darbs bija detalizēti
dokumentēts, izveidot visas struktūras un ielādēt datus no jaunas nebija grūti. Secinājums –
labāk instalēt Oracle DB pilno versiju, nevis Express. Par metodes realizāciju Java valodā
autors domā, ka tā ir interesanta un dod vairākas iespējas, bet šim uzdevumam nav efektīva.
Laika predikātu realizācijai nav jāraksta sarežģītas programmas, bet Java valodā jāraksta
vairāk koda, nekā PL/SQL, jādomā par Oracle DB tipu attēlošanu Java programmas tipos.
Atsevišķa problēma bija NULL vērtības laika perioda LIDZ atribūtos. Piemēram, ja inicializēt
oracle.sql.DATE tipa objektu ar NULL vērtību, tad tiek mests SQLException izņēmums.
Metode DATE_object.compareTo(DATE date) met NullPointerException izņēmumu, ja
DATE_object vai date ir inicializēti ar NULL. Šai problēmai autors atradīja atrisinājumu –
piešķirt lielo datuma vērtību atribūtiem, kuriem ir NULL vērtības, Java programmas ietvaros,
un tad jau realizēt laika predikātu. Metodes realizācijai Java valodā palīdzēja raksts [2].
Pēc autora domām, darba galvenais ieguvums ir iemaņu strādāt ar relāciju-objektu datu
bāzi attīstīšana. Temporālie dati ir tādi dati, ar kuriem lietderīgāk strādāt, pielietojot objektus.
Tāpēc šīs darbs attīstīja objektorientētu domāšanas veidu datu bāzes jomā; kā pielietot
objektorientētas koncepcijas, lai palielinātu sava darba efektivitāti.
58
Literatūras saraksts
1. Viktorija Raizina. 2. praktiskais darbs priekšmetā Progresīvās Datu Bāzes „Temporālās datu bāzes izveidošana un temporālo vaicājumu realizēšana”, 2008, 3. Piemērs no piedāvātājiem http://datubaze.wordpress.com/macibu-kursi/db3/db3_prdarbi/2-praktiskais-darbs/
2. Kā realizēt procedūru, funkciju vai objekta tipa metodi, izmantojot Java valodu: http://docs.oracle.com/cd/B19306_01/java.102/b14187/chsix.htm#BABDIBID