Az egyes feladatoknál az SQL92-nek megfelelő elvi megoldást adom meg, de ettől az egyes adatbázis kezelő rendszerek az implementációban, a konkrét megvalósításban eltérhetnek. A jegyzetben található konkrét megoldásokhoz a Microsoft SQL Server 2005-ös rendszerében implementált SQL nyelvet használtam.
A feladatokat az alábbi modellnek megfelelően kell megoldani.
Create table Osztály(
Kód char(3) primary key,
Név char(20));
Create table Projekt(
Kód char(3) primary key,
Név char(20),
Tbér numeric(5) check (Tbér<30000),
Aktív char(1) check (Aktív in('I','N')));
Create table Dolgozó(
Kód char(3) primary key,
Név char(20),
Város char(20),
Beosztás char(20),
Kor numeric(2) check (Kor between 18 and 62),
Alapbér numeric(6) check (Alapbér>85000),
Oszt char(3) not null references Osztály);
Create table Résztvesz(
Dolg char(3) not null references Dolgozó,
Dátum date,
Proj char(3) not null references Projekt,
unique (Dolg, Dátum, Proj));
Az unique előírás így megadva azt jelenti, hogy az adott mezőket együtt figyelve nem lehet ismétlődés, vagyis egy dolgozókód egy adott dátummal az adott projekt mellett csak egyszer fordulhat elő.
A vezetés úgy dönt, hogy ne a dátumot tároljunk a Résztvesz táblában, hanem számként az évet és a hónapot.
Drop table Résztvesz;
Create table Résztvesz(
Dolg char(3) not null references Dolgozó,
Év numeric(4),
Hónap numeric(2) check (Hónap between 1 and 12),
Proj char(3) not null references Projekt,
unique (Dolg, Év, Hónap, Proj));
alter table Résztvesz add constraint évellenőr check (Év between 2011 and 2020)
alter table Résztvesz drop constraint évellenőr; alter table Résztvesz add constraint évellenőr check (Év between 2010 and 2020);
Create assertion maxlétszám check
(SELECT count(dolg) from Résztvesz group by Év, Hónap, Proj having count(dolg)>4)=0;
Jelentése: azon csoportok száma, ahol a projekten 4-nél többen dolgoznak nulla kell legyen!
Create assertion aktívprojekt check
(SELECT count(*) from résztvesz, projekt where proj=kód and aktív='N')=0
Azon rekordok száma a résztvesz táblában, ahol a projekt nem aktív, nulla kell legyen! Az előírások elvileg működnek, gyakorlatilag az assertion parancsot a nagyobb adatbázis kezelő rendszerek nem implementálták. Ehelyett használhatók olyan triggerek, amelyek adatbeszúráskor ellenőrzik az előírt feltételeket, és ha nem teljesednek, akkor visszavonják a kiadott insert utasítást. (Ez a rollback parancs, bővebben később!)
CREATE TRIGGER maxlétszám ON résztvesz FOR INSERT AS
IF (SELECT count(dolg) from Résztvesz group by Év, Hónap, Proj
having count(dolg)>4) >0
ROLLBACK;
CREATE TRIGGER aktívprojekt ON résztvesz FOR INSERT AS
IF (SELECT count(*) from résztvesz, projekt where proj=kód and
aktív='N')>0
ROLLBACK;
b01-Bolt, b02-Bérügy, s01-Számlázás, s02-Szállítás, r01-Raktár.
Az első rekordot beszúró parancs:
insert into Osztály values('b01', 'Bolt');
A többi parancs ugyanilyen szintaktikájú.
insert into Osztály values('b01', 'Beszerzés');
A parancs hibás, mert van már b01 kódú rekord, és az elsődleges kulcs előírás egyben egyediséget is jelent.
insert into Osztály values('b03');
Hibás, a values után minden értéket meg kell adni, itt kimaradt az osztály neve.
insert into Osztály values('b03',’’);
Hibás, így nem lehet üres értéket megadni.
insert into Osztály values('b03', null);
Működik, így kell az üres értéket megadni.
insert into Osztály (Kód) values('b04');
Működik, így lehet nem teljes adatsort felvinni.
insert into Dolgozó values('d44', 'Kék Alma', 'Miskolc', 'számlázó', 31, 180000, 's01');
insert into Dolgozó values('d09', 'Zöld Galamb', null, 'eladó', 27, 85000, 'b01');
insert into Dolgozó values('d16', 'Fekete Farkas', 'Eger', 'raktáros', null, 160000, 'r01');
insert into projekt values('fas', 'Fásítás', 10000, 'I')
insert into projekt values('bt2', 'Bolt takarítás', 29000, 'N')
insert into projekt values('rt1', 'Raktár takarítás', 10000, 'I')
insert into résztvesz values ('d12', 2010, 9, 'fas')
insert into résztvesz values ('d33', 2010, 10, 'rt1')
insert into résztvesz values ('d04', 2010, 12, 'rt1')
insert into Dolgozó values('d66', 'Barna Barna', null, 'számlázó', 31, 180000, 's01');
insert into Dolgozó (Kód, Név, Beosztás, Kor, Alapbér, Oszt) values('d67', 'Fehér Hannibál', 'számlázó', 31, 180000, 's01');
update dolgozó set Város='Miskolc' where Város is null;
Kérdések:
Az update parancs hatására mindkét rekordban megváltozik a város Miskolcra?
Igen, a nem megadott és a null-ként bevitt érték egyformán viselkedik.
Hogyan lehet a d25 és a d32 közötti kódú rekordokban kijavítani a várost Miskolcra?
update dolgozó set Város='Miskolc' where Kód between 'd25' and 'd32';
Hogyan lehet kitörölni Kék Alma rekordjából a várost?
update dolgozó set Város=null where Név='Kék Alma';
Hogyan lehet évváltáskor mindekinél a kort megnövelni 1-el?
update dolgozó set Kor=Kor+1;
Mindig, minden rekordra működik az előző parancs?
Nem, az előző parancs csak akkor módosítja a rekordot, ha a kor módosítás után nem éri el a 62-t, erről gondoskodik a korra előírt check feltétel.
Hogyan lehet kitörölni Kék Alma rekordját?
delete from dolgozó where Név='Kék Alma';
Bármikor ki lehet törölni Kék Almát?
Nem lehet bármikor törölni a rekordot: ha Kék Alma kódja szerepel a résztvesz táblában – mivel ott idegen kulcs – a rekord a dolgozó táblából nem törölhető.
A nem Béla keresztnevű raktárosok vagy eladók neve
Select név from dolgozó where név not like '% Béla' and beosztás ='eladó' or név not like '% Béla' and beosztás='raktáros';
Hány olyan dolgozó van, akinek a kódjában a középső karakter 2-es?
select count(*) from dolgozó where kód like '_2_';
A 2010 3. negyedévében futó projektek neve (egy név csak egyszer szerepeljen!)
Select distinct név from projekt, résztvesz where proj=kód and év=2010 and hónap in (7, 8, 9); – A distinct kulcsszó biztosítja az egyediséget, ezért egy név csak egyszer íródik ki.
Osztályok és dolgozóik neve, ábécé sorrendben
Select osztály.név, dolgozó.név from osztály, dolgozó where oszt=Osztály.kód order by osztály.név, dolgozó.név;
A 04-re vagy 07-re végződő kódú 30-as korú dolgozók neve, alapbére, alapbér szerinti csökkenő sorrendben
Select név, alapbér from dolgozó where kód like '_04' and kor like '3_' or kód like '_07' and kor like '3_' order by alapbér desc;
A bérügy dolgozóinak neve, éves alapfizetése
Select dolgozó.név, 12*alapbér Éves_alapfizetés from osztály, dolgozó where oszt=Osztály.kód and osztály.név='Bérügy';
Az összes különböző beosztás kiírása (csak létező beosztások!)
Select distinct beosztás from dolgozó where beosztás is not null;
A raktáros beosztásúak átlag alapbére
Select avg(alapbér) from dolgozó where beosztás='raktáros';
A nem miskolci dolgozók száma, városonként csoportosítva
Select város, count(*) from dolgozó where város != 'Miskolc' group by város;
A legmagasabb alapbérű dolgozó(k) neve, alapbére
Select név, alapbér from dolgozó where alapbér = (select max(alapbér) from dolgozó);
Select osztály.név, avg(alapbér) from osztály, dolgozó where oszt=Osztály.kód group by osztály.név order by avg(alapbér);
Osztályok szerinti átlagfizetés, átlagfizetés szerinti növekvő sorrendben
select dolgozó.név from dolgozó, résztvesz, projekt where dolg=dolgozó.kód and proj=projekt.kód and projekt.név='Fásítás';
Azok neve, akik dolgoztak már a fásítás projektben
select név from dolgozó where név not in(select dolgozó.név from dolgozó, résztvesz, projekt where dolg=dolgozó.kód and proj=projekt.kód and projekt.név='Fásítás');
Azok neve, akik nem dolgoztak még a fásítás projektben
select osztály.név, projekt.név from osztály, dolgozó, résztvesz, projekt where oszt=osztály.kód and dolg=dolgozó.kód and proj=projekt.kód and év=2010 and hónap=12 group by osztály.név, projekt.név;
2010 decemberében mely osztályok, milyen projektekben vettek részt
Select dolgozó.név, sum(tbér)+sum(alapbér)/count(alapbér) from dolgozó, résztvesz, projekt where dolg=dolgozó.kód and proj=projekt.kód and év=2010 and hónap=12 group by dolgozó.név;
A 2010, decemberi fizetések: alapbér és a projektek után járó teljesítménybér.
Azon osztályok neve és létszáma, ahol 10-nél kevesebben dolgoznak
Select osztály.név, count(oszt) from osztály, dolgozó where oszt=Osztály.kód group by osztály.név having count(oszt) <10;
A legmagasabb átlagos alapbérű osztály neve, és átlag alapbére
create view osztatlagfiz as select oszt, avg(alapbér) átlag from dolgozó group by oszt;
select oszt, átlag from osztatlagfiz where átlag=(select max(átlag) from osztatlagfiz);
Ha már nem kell: drop view osztatlagfiz;
Az egyes osztályokon hány 300000 Ft-nál többet kereső személy van
select osztály.név, count(*) from osztály join dolgozó on oszt=osztály.kód where alapbér>300000 group by osztály.név;
Az egyes projektekre hányszor jelentkeztek (kellenek azok a projektek is, amelyekre még sosem jelentkeztek!)
select projekt.név, count(proj) from projekt left outer join résztvesz on projekt.kód=proj group by projekt.név;
Kék Alma az egyes projektekre hányszor jelentkezett (kellenek azok a projektek is, amelyekre még sosem jelentkezett!)
select projekt.név, count(proj) from projekt left outer join résztvesz on projekt.kód=proj left outer join dolgozó on dolg=dolgozó.kód and dolgozó.név='Kék Alma' group by projekt.név;
Ki hány projektekre jelentkezett már (azok neve is kell, akik még nem jelentkeztek sosem projektre!)
select név, count(dolg) from dolgozó left outer join résztvesz on dolgozó.kód=dolg group by név;
Az egyes osztályokról hányszor jelentkeztek már projektre (azon osztályok neve is kell, ahonnan még sosem jelentkeztek projektre!)
select osztály.név, count(dolg) from osztály left outer join dolgozó on osztály.kód=oszt left outer join résztvesz on dolgozó.kód=dolg group by osztály.név;
Grant select on dolgozó to Péter5;
Grant select on dolgozó to public;
Grant insert, update on projekt, résztvesz to Péter5;
Revoke insert on projekt from Péter5;
Deny all on résztvesz to Péter5;