13
Skripta za labose iz baza podataka I. (samo za dio POSTGRE-sqla) Namjena skripte je prolazak na labosima. Ako slučajno padnete ja nisam kriv jer ima i stvari izvan skripte :P . Sretno ! Skripta je rađena prema vježbama 5 i 9 iz primjera + će biti dodano još stvari za svaki slučaj :D a) Sve naredbe završavaju sa ; b) Brisanje tablice DROP TABLE "ime tablice"; za početak ćemo stvoriti bazu podataka (što se na kolokviju neće možda morati) CREATE DATABASE vjezba5; sad ćemo se na nju priključiti \CONNNECT vjezba5; Sad ćemo rješavati zadatke Kako nemamo bazu od 1. vježbe sve ćemo nanovo napravit :( Napravit ćemo odmah onu izmjenu sa sekvencama: CREATE TABLE izdavac( sifra VARCHAR(10) PRIMARY KEY, naziv VARCHAR(50) NOT NULL); Mjenjamo u : CREATE TABLE izdavac( sifra SERIAL PRIMARY KEY, naziv VARCHAR(50) NOT NULL);

Skripta Za Baze-lab

Embed Size (px)

Citation preview

Skripta za labose iz baza podataka I.

(samo za dio POSTGRE-sqla)

Namjena skripte je prolazak na labosima. Ako slučajno padnete ja nisam kriv jer ima i stvari izvan

skripte :P . Sretno !

Skripta je rađena prema vježbama 5 i 9 iz primjera + će biti dodano još stvari za svaki slučaj :D

a) Sve naredbe završavaju sa ;

b) Brisanje tablice DROP TABLE "ime tablice";

za početak ćemo stvoriti bazu podataka (što se na kolokviju neće možda morati)

CREATE DATABASE vjezba5;

sad ćemo se na nju priključiti

\CONNNECT vjezba5;

Sad ćemo rješavati zadatke

Kako nemamo bazu od 1. vježbe sve ćemo nanovo napravit :(

Napravit ćemo odmah onu izmjenu sa sekvencama:

CREATE TABLE izdavac( sifra VARCHAR(10) PRIMARY KEY, naziv VARCHAR(50) NOT NULL);

Mjenjamo u :

CREATE TABLE izdavac( sifra SERIAL PRIMARY KEY, naziv VARCHAR(50) NOT NULL);

s tim smo napravili tablicu koja se zove izdavac te postavili da se sifra sama povećava.

Naziv je atribut koji je alfanumeričkog tipa duljine 50 znakova i ne smije biti prazan.

(napomena kod serial, POSTGREsql će nakon unosa samo izbaciti obavijest da je kreirana

sekvenca; NOTICE: CREATE TABLE will create implicit sequence "izdavac_sifra_seq" for serial

column "izdavac.sifra")

CREATE TABLE knjiga(sifra SERIAL PRIMARY KEY,

ISBN VARCHAR(15),

naziv VARCHAR(50) NOT NULL,

godina SMALLINT NOT NULL CHECK (GODINA BETWEEN 1970 AND

2050),

izdavac INTEGER REFERENCES izdavac ON DELETE

RESTRICT ON UPDATE CASCADE);

Navedene naredbe kreiraju tablicu knjiga te se također kreira sekvenca zbog seriala, za godinu se

provjerava da nije prazna te da li je između 1970 i 2050, izdavac je vanjski ključ na tablicu Izdavac .

ON DELETE RESTRICT -> sustav zabranjuje brisanje vrijednosti primarnog ključa u tablici roditelj ako

se ista virijednost koristi u tablici potomak. Ili na hrvatski: Ako postoji negdje u nekoj tablici vanjski

ključ koji se odnosi na primarni iz tablice roditelja. Na zahtjev brisanja u roditelju, akcija se neće izvršiti

zbog toga što negdje postoji ključ. ON UPDATE CASCADE -> svaka promjena na elementu u tablici

roditelj će se odraziti na svim ostalim primjercima istog drugim tablicama. Također promjena je kod

izdavača koji sad mora biti integer jer je primarni ključ promjenjen u serial (int).

CREATE TABLE autor( sifra SERIAL PRIMARY KEY,

ime VARCHAR(20) NOT NULL,

prezime VARCHAR(20) NOT NULL);

Kreiranje tablice autora.

CREATE TABLE autor_knjige(

knjiga INTEGER REFERENCES KNJIGA,

autor INTEGER REFERENCES AUTOR,

PRIMARY KEY(knjiga,autor));

Skrenuti pažnju pri dvostrukom primarnom ključu !!!!

CREATE TABLE clan( sifra SERIAL PRIMARY KEY,

ime VARCHAR(20) NOT NULL,

prezime VARCHAR(20) NOT NULL,

adresa VARCHAR(20) NOT NULL);

Tablica clan

CREATE TABLE posudba (clan INTEGER REFERENCES clan,

datum_posudbe DATE,

datum_vraćanja DATE,

knjiga INTEGER REFERENCES knjiga,

PRIMARY KEY(clan,knjiga,datum_posudbe));

I za kraj tablica posudba. Sad kad smo napravili sve tablice bacamo se na zadatke

Popunite postojeću tablicu članova sa barem 15 slogova. Koristite imena Vaših kolega, te neka se u

tablici članova nalazi i barem 5 autora (drugim riječima, neki autori su ujedno i članovi; moguće ih je

upisati korištenjem INSERT INTO ... SELECT ... naredbe, ili korištenjem INSERT naredbe).

za početak uvrštavanje u članove:

NAPOMENA: Uvijek kraj sebe imat strukturu tablice da znate kako se po redosljedu upisuje

CREATE TABLE clan( sifra SERIAL PRIMARY KEY,

ime VARCHAR(20) NOT NULL,

prezime VARCHAR(20) NOT NULL,

adresa VARCHAR(20) NOT NULL);

INSERT INTO clan VALUES(default,'ime1','prezime1','adresa1');

Navedenom naredbom se upisuje u člana navedeni elementi. 1. element je sifra, tu

stavljamo default jer se ona sama puni (sekvenca). Ostali atributi su VARCHAR pa njih stavljamo u

jednostruke navodne znakove. Provjera dal je dobro upisano:

select * from clan;

sifra | ime | prezime | adresa

-------+------+----------+---------

1 | ime1 | prezime1 | adresa1

(1 row)

A to daje ono što smo unijeli.

I sad tako još 14 puta samo za različite vrijednosti.

select count(*) from clan; vam broji koliko ste ih unijeli tako da znate di ste stali :D

E sad tu piše da se kao 5 članova ubaci i kao autore, pa to se radi ovako:

INSERT INTO autor(ime,prezime) SELECT ime,prezime FROM clan LIMIT(5);

u prijvodu doslovno Unesi u autora(izaberi stupce) ono sto izaberes od imena i prezima iz tablice

autor uz limit od 5 prijenosa.

Kreirajte privremenu sekvencu proizvoljnog imena, te isprobajte funkcije za rad sa sekvencama.

CREATE TEMPORARY SEQUENCE sekvenca

START 150

INCREMENT 2;

sekvenca sa početkom 150 i koja ima inkrement 2.

SELECT NEXTVAL('sekvenca');

Prikazuje iduću vrijednost sekvence nakon inkrementa (152)

SELECT SETVAL('sekvenca',358); Postavlja sekvencu na 358

Kreirajte upit koji vraća ukupan broj slogova u tablici članova.

SELECT COUNT(*) FROM clan;

Kreirajte upit koji vraća prezimena i imena članova sortirano prema prezime i imenu.

SELECT prezime,ime FROM clan ORDER BY 1; sortira prema 1-> prvi atribut u selectu

Kreirajte upit koji vraća prezimena i imena članova čije prezime počinje slovom "B" ili "R".

SELECT prezime FROM clan WHERE prezime LIKE'r%' OR prezime LIKE 'b%';

Pritom % mjenja ostatak riječi dok ako želite proizvoljan broj stavljate 'C_____'

Implementirajte sljedeću tablicu:

Dobavljač

� šifra (cjelobrojna vrijednost, povećava se samostalno, primarni ključ relacije)

� naziv (znakovni niz do 50 znakova, ne smije poprimiti null)

� adresa (znakovni niz neograničene duljine)

� telefonski_broj (znakovni niz od točno 9 znakova, ne smije poprimiti null)

� e-mail adresa (znakovni niz do 30 znakova)

� status (1 znak, P ili N; značenje je da su informacije o dobavljaču potpune ili da nisu

potpune, default vrijednost je P)

� ocjena (cjelobrojna vrijednost, smije poprimiti vrijednosti isključivo u intervalu 1 – 5, ne

smije poprimiti null)

CREATE TABLE dobavljac(

sifra SERIAL PRIMARY KEY,

naziv VARCHAR(50) NOT NULL,

adresa TEXT,

telefonski_broj CHAR(9) NOT NULL,

e_mail VARCHAR(30),

status VARCHAR(1) DEFAULT 'P',

ocjena INTEGER CHECK (ocjena BETWEEN 1 AND 5) NOT NULL);

telefonski_broj -> piše da kad je char da mora imat točno toliko znakova

check kod ocjene provjera da li je između 1 i 5

status default za svaki se postavlja P

Implementirajte jedinstveni indeks nad atributom naziv u tablici Dobavljač

CREATE INDEX i ON dobavljac(naziv);

U tablicu unesite barem 15 slogova tako da neki dobavljači imaju definiranu adresu i e-mail adresu, a

drugi ne.

onaj insert into, gdje ne želite da ima maila i adrese stavite '' (prazan string)

Ažurirajte tablicu tako da svim dobavljačima koji nemaju definiranu e-mail adresu stavite status na 'N'.

UPDATE dobavljac SET status='N' where e_mail='';

Kreirajte upit koji će vratiti nazive i e-mail adrese onih dobavljača koji imaju ocjenu manju od 4.

SELECT naziv,e_mail FROM dobavljac WHERE ocjena<4;

Kreirajte upit koji će vratiti broj dobavljača koji imaju definiranu adresu.

SELECT COUNT(*) FROM dobavljac WHERE adresa<>'';

Kreirajte upit koji će vratiti broj dobavljača prema statusu.

SELECT COUNT(*),status FROM dobavljac GROUP BY status;

Kreirajte upit koji će vratiti nazive i telefonske brojeve onih dobavljača čiji telefonski broj započinje sa

znakovima '09' sortirano silazno prema ocjeni.

SELECT naziv,telefonski_broj FROM dobavljac WHERE telefonski_broj LIKE

('09%') ORDER BY -1*ocjena;

-1*ocjena je samo zato da bi se sortiralo od najvise prema najnizoj, ako želite da se sortira od

najmanje samo maknite -1*

Izbrišite dobavljače čiji status je 'N' i čija je ocjena manja od 3.

DELETE FROM dobavljac WHERE (status='N' AND ocjena<3);

Kreirajte tablicu dobavljac2 na temelju podataka (sifra, naziv i adresa) koji postoje u tablici dobavljač

(like).

i sad ako sam dobro shvatio sta treba :D

SELECT sifra,naziv,adresa INTO dobavljac2 FROM dobavljac;

VJEŽBA 9

CREATE TABLE kompanija(id SERIAL PRIMARY KEY,

naziv VARCHAR(50) NOT NULL,

adresa VARCHAR(50));

CREATE TABLE tipfilma(id SERIAL PRIMARY KEY,

oznaka VARCHAR(30) NOT NULL,

opis VARCHAR(50));

CREATE TABLE film(id SERIAL PRIMARY KEY,

naslov VARCHAR(50) NOT NULL,

trajanje TIME NOT NULL,

godina INTEGER NOT NULL,

tip INTEGER REFERENCES tipfilma ON DELETE RESTRICT ON UP

DATE CASCADE,

kompanija INTEGER REFERENCES kompanija);

CREATE INDEX i ON film(tip);

TRANSAKCIJE ZA tipfilma;

vjezba9=# BEGIN ISOLATION LEVEL SERIALIZABLE;

BEGIN

vjezba9=# INSERT INTO tipfilma VALUES (default,'akcija','');

INSERT 0 1

vjezba9=# INSERT INTO tipfilma VALUES (default,'komedija','');

INSERT 0 1

vjezba9=# INSERT INTO tipfilma VALUES (default,'drama','');

INSERT 0 1

vjezba9=# INSERT INTO tipfilma VALUES (default,'triler','');

INSERT 0 1

vjezba9=# INSERT INTO tipfilma VALUES (default,'vestern','');

INSERT 0 1

vjezba9=# commit;

COMMIT

ZA KOMPANIJU TRANSAKCIJA

vjezba9=# BEGIN ISOLATION LEVEL SERIALIZABLE;

BEGIN

vjezba9=# INSERT INTO kompanija VALUES(default,'kompanija1','adresa1');

INSERT 0 1

vjezba9=# INSERT INTO kompanija VALUES(default,'kompanija2','adresa2');

INSERT 0 1

vjezba9=# INSERT INTO kompanija VALUES(default,'kompanija3','adresa3');

INSERT 0 1

vjezba9=# INSERT INTO kompanija VALUES(default,'kompanija3','');

INSERT 0 1

vjezba9=# INSERT INTO kompanija VALUES(default,'kompanija4','');

INSERT 0 1

vjezba9=# delete from kompanija where id=4;

DELETE 1

vjezba9=# INSERT INTO kompanija VALUES(default,'kompanija5','');

INSERT 0 1

vjezba9=# select * from kompanija;

id | naziv | adresa

----+------------+---------

1 | kompanija1 | adresa1

2 | kompanija2 | adresa2

3 | kompanija3 | adresa3

5 | kompanija4 |

6 | kompanija5 |

(5 rows)

vjezba9=# commit;

COMMIT

za film

vjezba9=# BEGIN ISOLATION LEVEL SERIALIZABLE;

BEGIN

vjezba9=# INSERT INTO film VALUES(default,'naslov1','01:25:00',1995,2,2)

INSERT 0 1

vjezba9=# INSERT INTO film VALUES(default,'a1','02:25:00',1995,2,1);

INSERT 0 1

vjezba9=# INSERT INTO film VALUES(default,'b3','01:23:00',1985,1,1);

INSERT 0 1

vjezba9=# INSERT INTO film VALUES(default,'z1','01:45:00',2000,4,2);

INSERT 0 1

vjezba9=# INSERT INTO film VALUES(default,'d1','02:25:00',2000,5,3);

INSERT 0 1

vjezba9=# INSERT INTO film VALUES(default,'a4','01:55:00',2001,5,1);

INSERT 0 1

vjezba9=# INSERT INTO film VALUES(default,'g4','01:55:00',2001,5,3);

INSERT 0 1

vjezba9=# INSERT INTO film VALUES(default,'g6','02:55:00',2008,1,2);

INSERT 0 1

vjezba9=# commit;

COMMIT

NAPOMENA ako izbaci error ERROR: current transaction is aborted, commands ignored until end of

transaction block

samo unesite commit; I pocnite nanovo sa begin isolation level serializable;

sad odgovori idu pitanje po pitanje za malo teže stvari ću stavit I objašnjenja:

- select naslov from film order by 1;

- select naslov from film where godina>2000 order by 1;

- select sum(trajanje)/count(*) from film;

- select max(trajanje),min(trajanje) from film;

- select naziv from kompanija where adresa='';

- select naslov from film where naslov like('d%');

- select naziv from kompanija where not exists(select kompanija from film where

kompanija=kompanija.id);

-Tražimo naziv kompanija koje nemaju film;

uzmi naziv kompanije gdje ne postoji da je (kompanija je vanjski kljuc na

primarni ključ tablice kompanija) taj vanjski ključ jednak primarnom

ključu u tablici kompanija (ID.kompanija)

- select count(*) from kompanija;

- select count(*) from kompanija where adresa<>'';

- select count(*) from film group by kompanija;

- select naziv,film.naslov from kompanija,film where film.kompanija=kompanija.id; uzmi naziv I naslov

filma tamo gdje je u tablici film vanjski ključ kompanija jednak identifikacijskom broju kompanije

- (12)select naziv,film.naslov,tipfilma.oznaka from kompanija,film,tipfilma where

(film.kompanija=kompanija.id) and (film.tip=tipfilma.id); slicno kao prethodno samo je dodana jos ta

oznaka pa smo morali dodat uvijet I jos jednu tablicu

- (10)select count(*) from film group by kompanija;

naziv | naslov | oznaka

------------+---------+----------

kompanija2 | naslov1 | komedija

kompanija1 | a1 | komedija

kompanija1 | b3 | akcija

kompanija2 | z1 | triler

kompanija3 | d1 | vestern

kompanija1 | a4 | vestern

kompanija3 | g4 | vestern

kompanija2 | g6 | akcija

(8 rows)

- select count(*),kompanija.naziv from film,kompanija where film.kompani

ja=kompanija.id group by kompanija.naziv; //dodano kompanija.naziv da se vidi da to radi kako treba

count | naziv

-------+------------

3 | kompanija2

3 | kompanija1

2 | kompanija3

(3 rows)

- select naziv,count(*) from kompanija,film where kompanija.id=film.kom

panija group by naziv having count(*)>=3;//izbroji sve nazive gdje kompanija.id=film.kom

panija I poslozi ih prema nazivu tamo gdje se nađe da je izbrojano 3 ili vise puta isto (nezz bas kako bolje

objasnit )

naziv | count

------------+-------

kompanija2 | 3

kompanija1 | 3

(2 rows)

-pogledi

1) create view prvi as

select count(*) from film group by kompanija;

2) create view drugi as

select naziv,film.naslov from kompanija,film where film.kompanija=kompanija.id;

CREATE VIEW

3) create view treci as

select naziv,count(*) from kompanija,film where kompanija.id=film.kompanija group by naziv having

count(*)>=3;

CREATE VIEW