Sunteți pe pagina 1din 32

LOGISTICĂ INFORMATICĂ

ÎNDRUMAR DE LABORATOR

Liviu Şerbănescu
UNIVERSITATEA HYPERION

1
L1 - GESTIUNE SIMPLĂ PENTRU
O MAGAZIE CU COMPONENTE ELECTRONICE.
SISTEMUL DE INTRĂRI

-- << descriere identificator>> --- se preia prin aplic. de interfata


-- GESTIUNE COMPONENTE ELECTRONICE
create schema c5;
-- creare tabel MASTER pentru Borderoul de receptie
CREATE TABLE c5.br_( nrbr serial PRIMARY KEY, datain date DEFAULT CURRENT_DATE,
po int, datapo date);
CREATE TABLE c5._br( nrbr int, idx serial, itemcode varchar(30), descriere varchar(100), qty int
DEFAULT 1, um varchar(10),
sn varchar(20), status varchar(15) DEFAULt 'NOU', furnizor varchar(30), dep varchar(20), loc
varchar(20),int id,
CONSTRAINT k__br PRIMARY KEY(nrbr,idx), CONSTRAINT f1__br FOREIGN KEY(nrbr)
REFERENCES c5.br_(nrbr));

ALTER TABLE c5._br ADD COLUMN id int; -- adauga apoi inca o coloana (uitata)

select * from c5.br_;


select * from c5._br;

-- creare nomenclator
CREATE TABLE c5.nom(idn serial PRIMARY KEY, itemcode varchar(30), descriere
varchar(100),um varchar(10),furnizor varchar(30));

-- adaugare inregistrari in nomenclator


INSERT INTO c5.nom(itemcode, descriere, um, furnizor) VALUES ('ITEM1','DESCRIERE
ITEM 1', 'buc', 'FURNIZOR1'),
('ITEM2','DESCRIERE ITEM 2', 'buc', 'FURNIZOR2'), ('ITEM3','DESCRIERE ITEM 3', 'buc',
'FURNIZOR1'), ('ITEM3','DESCRIERE ITEM 3', 'buc', 'FURNIZOR2');

-- adauga un nou BR (linie noua in c5.br_)


INSERT INTO c5.br_(po,datapo) VALUES ( NULL, NULL);
-- actualizare informatii
UPDATE c5.br_ SET datain='<<data>>', po=<<po>>, datapo='<<datapo>>' WHERE
nrbr=<<nrbrSelectat>>;
-- adauga un nou Item/echipament in BR
INSERT INTO c5._br(nrbr, itemcode) VALUES (1, NULL);

-- update campuri din nomenclator in _BR (selectia din nomenclator)


UPDATE c5._br itemcode=nom.itemcode, descriere=nom.descriere, um=nom.um,
furnizor=nom.furnizor
FROM c5.nom WHERE nom.idn=<<nomLinSelectata>> and nrbr=
<<_brNrBrSelectat>>;
-- update si ptr. celelalte campuri
UPDATE c5._br SET qty=<<cantitate>>, sn=<<serialNo>>, status=<<STARE
ECHIPAMENT>>, dep=<<DEPOZIT>>, loc=<<LOCATIE>>
WHERE nom.idn=<<nomLinSelectata>> and nrbr= <<_brNrBrSelectat>>;

2
----- A FOST COMPLETAT BR-ul
--- URMEAZA VALIDAREA ACESTUIA : linia va fi adaufata in tabelul de intrari si cel de stoc,
din BR va fi stearsa

-- cream secventa care va genera codul id , unic ptr. fiecare linie de intrare
CREATE SEQUENCE c5.id_seq INCREMENT 1 MINVALUE 1001 START 1001;

-- creare tabel intrari


CREATE TABLE c5.inx(id int PRIMARY KEY, nrbr int, itemcode varchar(30), descriere
varchar(100), qty int , um varchar(10),
sn varchar(20), status varchar(15) , furnizor varchar(30), dep varchar(20), loc varchar(20), datain
date, po int, datapo date);

-- creare tabel stoc


CREATE TABLE c5.st(dep varchar(20), loc varchar(20), id int, qtyfiz int, qtydisp int,
CONSTRAINT k_st PRIMARY KEY(dep,loc,id),
CONSTRAINT f1_st FOREIGN KEY(id) REFERENCES c5.inx(id));

-- OPERATIA DE VALIDARE ptr. un anumit NrBR

BEGIN TRANSACTION; -- se executa ori tot blocul ori NIMIC -- daca apare o eroare NU se
executa nimic.
UPDATE c5._br SET id=nextval('c5.id_seq') WHERE _br.nrbr=1;--<<NrBR>>
-- 1. adaugare in tabelul c5.inx datele din BR
INSERT INTO c5.inx(id, nrbr, itemcode, descriere, qty, um, sn, status, furnizor, dep, loc, datain,
po, datapo)
SELECT _br.id, br_.nrbr, _br.itemcode, _br.descriere, _br.qty, _br.um, _br.sn, _br.status,
_br.furnizor, _br.dep, _br.loc, br_.datain, br_.po, br_.datapo
FROM c5.br_,c5._br WHERE br_.nrbr=_br.nrbr and br_.nrbr=1;--<<NrBR>>;
-- 2. adaugare in tabelul c5.st datele din BR
--initial QtyDisp=QtyFizica=QtyIN
INSERT INTO c5.st(dep, loc, id, qtyfiz, qtydisp) SELECT _br.dep, _br.loc, _br.id, _br.qty,
_br.qty
FROM c5._br WHERE _br.nrbr=1;--<<NrBR>>;

-- 3. stergem liniile din BR


-- se sterg mai intai inreg. corespunzatoare BR-ului selectat din tabelul SLAVE
DELETE FROM c5._br WHERE _br.nrbr=1;--<<NrBR>>;
-- se sterg inreg din tabelul MASTER
DELETE FROM c5.br_ WHERE br_.nrbr=1;--<<NrBR>>; 1 se inlocuieste cu <<NrBR>> in
tot bblocul
COMMIT

3
L2 - GESTIUNE SIMPLĂ PENTRU
O MAGAZIE CU COMPONENTE ELECTRONICE.
SISTEMUL DE LIVRĂRI

-- pregatim marfa pentru a fi livrata => se creaza BP -- Borderou de preparare


-- sunt create doua tabele mater (informatii la nivel de BP)-slave(item cu item)
CREATE TABLE c5.bp_(nrbp serial PRIMARY KEY,dataLiv date DEFAULT
CURRENT_DATE, destinatar varchar(30));
-- o linie de intrare va aparea o singura data in c5._bp => brbp,id poate contitui cheia primara ptr.
c5._bp
--qtyrez qty rezervata ==> toata sau partial se transorma in qtyLiv (cant. livrata)
CREATE TABLE c5._bp(nrbp int,id int, dep varchar(20),loc varchar(20), qtyrez int,
CONSTRAINT k__bp PRIMARY KEY(nrbp,id,dep,loc),
CONSTRAINT f1__bp FOREIGN KEY(nrbp) REFERENCES c5.bp_(nrbp));
-- dep si loc intra in cheia primara de la _bp pentru a se putea livra un echipament ce se afla
imprastiat pe mai multew locatii si depozite
-- adaugarea unui camp cu cantitatea efectiv confirmata in vederea livrarii qtyconf = qtyliv
ALTER TABLE c5._bp ADD COLUMN qtyconf int;

-- adaugarea in c5.bp_

INSERT INTO c5.bp_(destinatar) VALUES ( NULL);


-- completam informatiile in BP_
UPDATE c5.bp_ SET dataliv=<<data livrarii>>, destinatar=<<destinatar>> WHERE nrbp=
<<NrBP SELECTAT DIN GRID>>;
-- adaugarea in c5._bp
-- se creaza un tabel temporar cu liniile ce urmeaza a fi inserate c5._bp
-- REzultatul interogarii stocului va fi intr-un tabel temporar:
CREATE TEMPORARY TABLE tmpstsel_1 as
SELECT inx.id, nrbr, itemcode, descriere, um, sn, status, furnizor,datain, po, datapo, st.dep,
st.loc, qtyfiz , qtydisp
FROM c5.inx,c5.st WHERE inx.id=st.id;--- and alte conditii de selectie

--select * from tmpstsel_1;


-- selectam item cu item in tasbelul de selectie

CREATE TEMPORARY TABLE tmpstsel_2(LIKE tmpstsel_1);


ALTER TABLE tmpstsel_2 ADD COLUMN qtyrez int;

select * from tmpstsel_2;

--adaugarea in cel de-al doilea tabel temporar


INSERT INTO tmpstsel_2 select tmpstsel_1.* FROM tmpstsel_1 where id=<<id linie
selectata in GRID>>;

-- adaugare din tmpstsel_2 in _bp + condidiile necesare de validare

BEGIN TRANSACTION;
-- verifica existenta unor cantitati insuficente
-- EXISTS intoarce TRUE (exista cel putin o inregistrare) sau FALSE (NU exista inregistrari)

4
-- ne raportam direct la stocul actualizat din c5.st
SELECT EXISTS(SELECT * FROM tmpstsel_2 st2,c5.st WHERE st2.dep=st.dep and
st2.loc=st.loc and st2.id=st.id AND st2.qtyrez>st.qtydisp);
-- daca este true se apeleaza ROLLBACK si se renunta la tranzactie
INSERT INTO c5._bp(nrbp,id,dep,loc,qtyrez)
SELECT <<NrBP SELECTAT>>, tmpstsel_2.id,tmpstsel_2.dep,tmpstsel_2.loc,
tmpstsel_2.qtyrez FROM tmpstsel_2 st2, c5.st
WHERE st2.dep=st.dep and st2.loc=st.loc and st2.id=st.id AND qtyrez<=qtydisp;
UPDATE c5.st SET qtydisp=qtydisp-st2.qtyrez FROM tmpstsel2 st2 WHERE st2.dep=st.dep
and st2.loc=st.loc and st2.id=st.id AND qtyrez<=qtydisp;
COMMIT;

---- LIVRAREA
--- BP trece in BL NrBL=NrBP
-- sunt create doua tabele mater (informatii la nivel de BL)-slave(item cu item)
CREATE TABLE c5.bl_(nrbl int PRIMARY KEY,dataLiv date DEFAULT CURRENT_DATE,
destinatar varchar(30));
-- o linie de intrare va aparea o singura data in c5._bp => brbp,id poate contitui cheia primara ptr.
c5._bp
--qtyrez qty rezervata ==> toata sau partial se transorma in qtyLiv (cant. livrata)
CREATE TABLE c5._bl(nrbl int,id int,dep varchar(20),loc varchar(20), qtyliv int, CONSTRAINT
k__bl PRIMARY KEY(nrbl,id),
CONSTRAINT f1__bl FOREIGN KEY(nrbl) REFERENCES c5.bl_(nrbl));

-- adaugarea in c5.bl_
BEGIN TRANSITION;
INSERT INTO c5.bl_ select *FROM c5.bp_ WHERE nrbl=<<NrBP selectat>>
-- confirmarea toate cantitatilor rezervate
UPDATE c5._bp SET qtyconf=qtyrez;
-- sau conf. linie cu linie
UPDATE c5._bp SET qtyconf=<<Qty Confirmata de la tastatura>> WHERE qtyconf<=qtyrez;
-- insereaza in _BL
INSERT INTO c5._bl(nrbl,id,dep,loc,qtyliv) select <<NrBP selectat>>, id,dep,loc, qtyconf FROM
c5._bp WHERE nrbp=<<NrBPselectat>>
-- scade din stoc
UPDATE c5.st set qtydisp=qtydisp+(qtyrez-qtyconf), qtyfiz=qtyfiz-qtyconf FROM c5._bp
WHERE _bp.dep=st.dep and _bp.loc=st.loc and _bp.id=st.id;
-- stergem liniile daca qtyfiz=0
DELETE FROM c5.st WHERE st.qtyfiz<1;
-- stergem liniile din BP
-- se sterg mai intai inreg. corespunzatoare BR-ului selectat din tabelul SLAVE
DELETE FROM c5._bp WHERE _bp.nrbp=<<NrBP>>;
-- se sterg inreg din tabelul MASTER
DELETE FROM c5.bp_ WHERE bp_.nrbp=<<NrBP>>;
COMMIT

5
L3 - PROIECTAREA ȘI IMPLEMENTAREA
ÎN BD A NOMENCLATOARELOR

Obiectiv: Reprezentari în cadrul bazelor de date a nomenclatoarelor de produse - proiectarea şi


implementarea interogărilor SQL aferente;

DROP schema IF EXISTS logx CASCADE; -- CASCADE STERGE SI LEGATURILE CU


CELELALTE OBIECTE
create schema logx;
-- creare tabel nomenclator
DROP TABLE IF EXISTS logx.nom;
CREATE TABLE logx.nom(idcode varchar(20) PRIMARY KEY, refteh varchar(30),refcom
varchar(20), descr varchar(100),
utiliz varchar(30) DEFAULT CURRENT_USER, data date DEFAULT
CURRENT_DATE, ora time DEFAULT CURRENT_TIME);
INSERT INTO logx.nom(idcode,descr) VALUES ('A1','DescrA1'),('A2','DescrA2'),
('B1','DescrB1'),('B2','DescrB2'),('C1','DescrC1'),('C2','DescrC2');
--select * from logx.nom;
-- creare tabel locatii
DROP TABLE IF EXISTS logx.loc;
CREATE TABLE logx.loc(dep char(3), ampl varchar(10), CONSTRAINT loc_pk PRIMARY
KEY(dep,ampl));
INSERT INTO logx.loc( dep, ampl)
VALUES ('ABC','AA1'),('ACC','AA1'),('ABD','AA1'),('ACD','AA1');
--creare functie de adaugare in nomenclator
---------------------------------------------------------------------------------------------
CREATE OR REPLACE FUNCTION logx.nom_add(_idcode_ text,_refteh_ text,_refcom_ text,
_descr_ text)
RETURNS text AS
$$
DECLARE
f boolean;
ach text;
BEGIN
--testare existenta idcode in nom
SELECT EXISTS(SELECT * FROM logx.nom WHERE idcode=_idcode_) INTO f;
IF f THEN
SELECT 'Exista deja in nom.'||_idcode_||'-- refteh:'||refteh||' recom:'||refcom||' Descriere:'||descr
||' User:'||utiliz||'-Data:'||data||'-Ora:'||ora
FROM logx.nom WHERE idcode=_idcode_ INTO ach;
return ach;
END IF;
INSERT INTO logx.nom(idcode, refteh, refcom, descr)
VALUES (_idcode_, _refteh_, _refcom_, _descr_);
RETURN 'OK';
END
$$ LANGUAGE 'plpgsql';
-----------------------------------------------------------------------------
select logx.nom_add('S1','R1','COM1','O descriere');

6
L4 - PROIECTAREA ȘI IMPLEMENTAREA
SISTEMULUI DE INTRARI IN GESTIUNE

Obiectiv: Proiectarea şi realizarea interogărilor SQL aferente sistemului de intrări în gestiune;

--creare tabel BR
DROP TABLE IF EXISTS logx.br;
CREATE TABLE logx.br(nrbr int,datain date DEFAULT CURRENT_DATE,idcode varchar(20),
po varchar(10), ruta varchar(10),
stare varchar(15), furnizor varchar(50), serialno varchar(50), depinit char(3), amplinit
varchar(10),
qty int, val numeric, idx serial PRIMARY KEY);
ALTER TABLE logx.br ADD CONSTRAINT br_f1 FOREIGN KEY (idcode) REFERENCES
logx.nom (idcode);
ALTER TABLE logx.br ADD CONSTRAINT br_f2 FOREIGN KEY (depinit,amplinit)
REFERENCES logx.loc (dep,ampl);

/*
--creare tabel BR
DROP TABLE IF EXISTS logx.br;
CREATE TABLE logx.br(nrbr int,datain date DEFAULT CURRENT_DATE,idcode varchar(30),
po varchar(10), ruta varchar(10),
stare varchar(15), furnizor varchar(50), serialno varchar(50), depinit char(3), amplinit
varchar(10),
qty int, val numeric, idx serial PRIMARY KEY);
ALTER TABLE logx.br ADD CONSTRAINT br_f1 FOREIGN KEY (idcode) REFERENCES
logx.nom (idcode);
--ALTER TABLE logx.br ADD CONSTRAINT br_f2 FOREIGN KEY (depinit,amplinit)
REFERENCES logx.loc (dep,ampl);

--functie creare tabele tmp br


*/

INSERT INTO logx.br(


nrbr, datain, idcode, stare, furnizor, serialno, qty,depinit,amplinit) VALUES
(1,'2012-04-17','A1','nou','Furniz1','SS1',1,'ABC','AA1'),
(1,'2012-04-17','A2','nou','Furniz1','SS2',1,'ABC','AA1'),
(1,'2012-04-17','B2','retur','Furniz1',NULL,10,'ACC','AA1'),
(2,'2012-04-18','B2','retur','Furniz1',NULL,15,'ABC','AA1'),
(2,'2012-04-18','C1','defect','Furniz1','SS3',1,'ABC','AA1'),
(3,'2012-04-18','C1','defect','Furniz1','SS3',1,'ABC','AA1'),
(3,'2012-04-18','B2','nou','Furniz2',NULL,25,'ABC','AA1');

--creare tabel IN
CREATE TABLE logx.inx(id char(11) PRIMARY KEY, nrbr int,datain date DEFAULT
CURRENT_DATE,idcode varchar(20), po varchar(10), ruta varchar(10),
stare varchar(15), furnizor varchar(50), serialno varchar(50), depinit char(3), amplinit
varchar(10),
qty int, val numeric);
ALTER TABLE logx.inx ADD CONSTRAINT in_f1 FOREIGN KEY (idcode) REFERENCES

7
logx.nom (idcode);
ALTER TABLE logx.inx ADD CONSTRAINT in_f2 FOREIGN KEY (depinit,amplinit)
REFERENCES logx.loc (dep,ampl);
-- creare tabel stoc
CREATE TABLE logx.stx(dep char(3),ampl varchar(10), id char(11), qtyfiz int,qtydisp int,
CONSTRAINT st_pk PRIMARY KEY(dep,ampl,id));
ALTER TABLE logx.stx ADD CONSTRAINT st_f1 FOREIGN KEY (id) REFERENCES
logx.inx (id);
ALTER TABLE logx.stx ADD CONSTRAINT st_f2 FOREIGN KEY (dep,ampl) REFERENCES
logx.loc (dep,ampl);

8
L5 - PROIECTAREA ȘI IMPLEMENTAREA
SISTEMULUI DE EDITARE PENTRU INTRARI

-----------------------------------------------------------------------------------------------------
CREATE OR REPLACE FUNCTION logx.creare_msbr()
RETURNS void as
$$
BEGIN
drop table if exists _br; -- sterge tabelul copil
drop table if exists br_; -- sterge tabelul parinte
create temporary table br_(nrbr int PRIMARY KEY,datain date DEFAULT
CURRENT_DATE,furnizor varchar(30));
--tabelul copil _br va contine si indexul idxbr(daca exista) din tabelul logx.br
create temporary table _br(nrbr int,idx serial, idxbr int,po varchar(10), ruta varchar(10),
stare varchar(15), serialno varchar(50), depinit char(3), amplinit varchar(10),
qty int, val numeric,
idcode varchar(20), refteh varchar(30),refcom varchar(20), descr varchar(100),
CONSTRAINT k__br PRIMARY KEY(nrbr,idx));
ALTER TABLE _br ADD CONSTRAINT f1__br FOREIGN KEY(nrbr) REFERENCES
br_(nrbr);
END
$$
LANGUAGE 'plpgsql';
---------------------------------------------------------------------------------------------------------

---------------------------------------------------------------
--functie preluare date in br_ si _br din br
CREATE OR REPLACE FUNCTION logx.prel_msbr()
RETURNS void as
$$
BEGIN
INSERT INTO br_(nrbr,datain,furnizor) SELECT DISTINCT nrbr,datain,furnizor FROM logx.br;
INSERT INTO _br(nrbr,po,ruta,stare,serialno,depinit,amplinit,qty,val,idcode,refteh,refcom,descr)
SELECT br.nrbr,br.po,br.ruta,br.stare,br.serialno,br.depinit,br.amplinit,br.qty,br.val,
nom.idcode,nom.refteh,nom.refcom,nom.descr
FROM logx.br,logx.nom WHERE br.idcode=nom.idcode;
END;
$$
LANGUAGE 'plpgsql' ;
--------------------------------------------------------------------------

--select * from br_;


--select * from _br;

--testare preluare din br in _br si br_


SELECT * FROM logx.br;
--creare br_ si _br
select logx.creare_msbr();
--preluare br in br_ si _br ;
select logx.prel_msbr();

9
select * from br_;
select * from _br;

--simulam o modificare in tabelul br_


update br_ set furnizor='Furnizor555' where nrbr=2;
--simulam o modificare in tabelul _br
update _br set stare='defectX' where idx=3;

select * from br_;


select * from _br;
--salvam modificarile din borderoul cu nr.2
select logx.save_msbr2(2);
select * from logx.br;
--salvam modificarile din borderoul cu nr.3(in acest caz idx corespunde bord. de rec. cu nr.3)
select logx.save_msbr2(3);
select * from logx.br;

-- O line de intrare este unica prin numarul ID, acesta este format din 3 caractere ce dau codul
-- depozitului initial si un numar unic in sistem;
-- creare secventa parte numerica ID
CREATE SEQUENCE logx.id_seq
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
--verificare index
select nextval('logx.id_seq');
--- generare ID nou
------------------------------------------------------------------------------------------
CREATE OR REPLACE FUNCTION logx.id_nou(_dep_ text)
RETURNS text AS
$$
DECLARE
i int;
BEGIN
SELECT nextval('logx.id_seq') INTO i;
return _dep_||i::text;
END;
$$
LANGUAGE 'plpgsql';
------------------------------------------------------------------------------------------
--test id_nou
select logx.id_nou('ABC') as id_nou;

--VALIDAREA BR
------------------------------------------------------------------------------------------
CREATE OR REPLACE FUNCTION logx.valid_br(_nrbr_ int)
RETURNS text AS

10
$$
DECLARE
f boolean;
BEGIN
--verificare introducere itemcode
SELECT EXISTS(SELECT * FROM logx.br WHERE idcode IS NULL) INTO f;
IF f THEN return 'Introduceti itemcode!'; END IF;
--verificare introducere cantitati
SELECT EXISTS(SELECT * FROM logx.br WHERE qty<1) INTO f;
IF f THEN return 'Introduceti cantitatea!'; END IF;
--verificare introducere um
SELECT EXISTS(SELECT * FROM logx.br WHERE datain IS NULL) INTO f;
IF f THEN return 'Introduceti DATA!'; END IF;
--etc
--NOTA: functia se executa intr-o singura tranzitie
--adaugare in logx.inx
INSERT INTO logx.inx(
id, nrbr, datain, idcode, po, ruta, stare, furnizor, serialno,
depinit, amplinit, qty, val)
SELECT logx.id_nou(depinit), nrbr, datain, idcode, po, ruta, stare, furnizor, serialno, depinit,
amplinit, qty, val
FROM logx.br WHERE nrbr=_nrbr_;

INSERT INTO logx.stx(


dep, ampl, id, qtyfiz, qtydisp)
SELECT depinit,amplinit,id,qty,qty FROM logx.inx;
RETURN 'OK';
END;
$$
LANGUAGE 'plpgsql';
------------------------------------------------------------------------------------------
--verificare validare
select * from logx.inx;
select logx.valid_br(1) as rez;
select * from logx.inx;
select * from logx.stx;

---- --== END RECEPTIA ------

11
L6 - PROIECTAREA ȘI IMPLEMENTAREA
MECANISMULUI DE REZERVARE

Obiectiv: Proiectarea şi realizarea interogărilor SQL aferente sistemului de rezervări;

--- IESIRI / LIVRAREA ----


/*
Livrarea marfurilor se realizeaza in doua etape
1. Se realizeaza rezervarea marfurilor prin constiutuirea BP (borderou de preparare)
2. Se realizeaza validarea BP si transformarea in BL (borderou de livrare)

ST: QtyDisp -- cantitate disponibila


ST: QtyFiz --cant. fizica
BP: QtyRez -- cant rezervare
BL: QtyConf -- cant. confirmata

Rezervare: QtyDisp=QtyDisp-QtyRez
Livrare (validare BP) :
QtyDisp=QtyDisp+(QtyDisp-QtyConf)
QtyFiz=QtyFiz-QtyConf

unde
QtyFiz>=QtyDisp
QtyRez<=QtyDisp
QtyConf<=QtyRez

*/

CREATE TABLE logx.bp_(nrbp int PRIMARY KEY,databp date,destin varchar(30));


CREATE TABLE logx._bp(nrbp int,id varchar(11),qtyrez int DEFAULT 0,qtyconf int DEFAULT
0,dep varchar(3), ampl varchar(10),
CONSTRAINT k__bp PRIMARY KEY(nrbp,id,dep,ampl),
CONSTRAINT f1__bp FOREIGN KEY(id) REFERENCES logx.inx(id) ,
CONSTRAINT f2__bp FOREIGN KEY(dep,ampl) REFERENCES logx.loc(dep,ampl),
CONSTRAINT f0__bp FOREIGN KEY(nrbp) REFERENCES logx.bp_(nrbp));
select * from logx.loc;
select * from logx.inx;
INSERT INTO logx.bp_ VALUES(1,'2013-05-17','Dest1'),(2,'2013-05-18','Dest1');
INSERT INTO logx._bp(nrbp,id,qtyrez,dep,ampl) VALUES(1,'ABC6',7,'ABC','AA1'),
(1,'ABC6',7,'ACC','AA1');
select * from logx.bp_;
select * from logx._bp;

--prelare in tabele temporare master-slave a informatiilor din bp_ si _bp


/*void bp_prel(_nrbp_ int)
{ create temporary table tmpbp_ as select * from bp_;
create temp table tmp_bp as select * from _bp where brbp=_nrbp_

*/
---preluarea se realizeaza din tmpselst, tabel cu structura variabila ce contine

12
-- minimal campurile: dep,ampl,id,qty
--este creat un nou BP
---1.creaare nrBP
-- creare secventa parte numerica ID
CREATE SEQUENCE logx.bp_seq
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
--verificare index
select nextval('logx.bp_seq');

---------------------------------------------------------------------------------------------
create or replace function logx.bp_nou(_destin_ text,_databp_ date DEFAULT
CURRENT_DATE)
returns void as
$$
begin
insert into logx.bp_(nrbp,databp,destin) VALUES ((select
nextval('logx.bp_seq')),_databp_,_destin_);
end
$$
language 'plpgsql';
---------------------------------------------------------------------------------------------
--verificare
select * from logx.bp_;
select logx.bp_nou('UNDEVA');
-----------------------------------------------------------------------------------------------------
create or replace function logx.prelSelST1(_nrbp_ int)
returns void as
$$
begin
--adauga linii in BP
insert into logx._bp(nrbp,dep,ampl,id,qtyrez)
select _nrbp_ as nrbp, tmpselst.dep,tmpselst.ampl,tmpselst.id,tmpselst.qty
FROM tmpselst,logx.stx
-- verificam inca o data stocul inainte de rezervare
WHERE stx.dep=tmpselst.dep AND stx.ampl=tmpselst.ampl AND stx.id=tmpselst.id AND
stx.qtydisp>=tmpsetst.qty;
--operatia de rezervare
UPDATE logx.stx SET qtydisp=qtydisp-tmpselst.qty FROM tmpselst
WHERE stx.dep=tmpselst.dep AND stx.ampl=tmpselst.ampl AND stx.id=tmpselst.id AND
stx.qtydisp>=tmpsetst.qty;
end
$$
language 'plpgsql';
-----------------------------------------------------------------------------------------------------
create or replace function logx.prelSelST2(_nrbp_ int) --prezinta siguranta mai mare
returns void as

13
$$
begin
--adauga linii in BP
insert into logx._bp(nrbp,dep,ampl,id,qtyrez)
select _nrbp_ as nrbp, tmpselst.dep,tmpselst.ampl,tmpselst.id,tmpselst.qty
FROM tmpselst,logx.stx
-- verificam inca o data stocul inainte de rezervare
WHERE stx.dep=tmpselst.dep AND stx.ampl=tmpselst.ampl AND stx.id=tmpselst.id AND
stx.qtydisp>=tmpselst.qty;
--operatia de rezervare
UPDATE logx.stx SET qtydisp=qtydisp-_bp.qtyrez FROM logx._bp
WHERE stx.dep=_bp.dep AND stx.ampl=_bp.ampl AND stx.id=_bp.id AND
stx.qtydisp>=_bp.qtyrez;
delete from tmpselst;
end
$$
language 'plpgsql';
-----------------------------------------------------------------------------------------------------

--testare
select * from logx.stx;
DROP TABLE IF EXISTS tmpselst;create temporary table tmpselst as select dep,ampl,id, 3 as qty
from logx.stx where id='ACC8';
select * from tmpselst;--liniile rezervate
select * from logx._bp;--tabel copil BP inainte de rezervare
select logx.prelSelST2(5);--in borderoul nr. 5 sunt rezervate liniile din tmpselst;

----------------------------------------------------------------------------------------------

---creare fisiere tmp ptr. interfatare

create temporary table itmp_bp_ as select * from logx.bp_;


create temporary table itmp__bp as select * from logx._bp;
ALTER TABLE itmp_bp_ ADD CONSTRAINT k_itmpbp_ PRIMARY KEY(nrbp);
ALTER TABLE itmp__bp ADD CONSTRAINT k__itmpbp PRIMARY KEY(nrbp,dep,ampl,id);

14
L7 - PROIECTAREA ȘI IMPLEMENTAREA
SISTEMULUI DE LIVRARE

Obiectiv: Proiectarea şi realizarea interogărilor SQL aferente sistemului de livrari;

CREATE TABLE logx.outx(nrbl int,destin varchar(30),id varchar(11),qtyliv int,dep varchar(3),


ampl varchar(10),
CONSTRAINT k_out PRIMARY KEY(nrbl,id,dep,ampl),
CONSTRAINT f1__out FOREIGN KEY(id) REFERENCES logx.inx(id) ,
CONSTRAINT f2__out FOREIGN KEY(dep,ampl) REFERENCES
logx.loc(dep,ampl));

--VALIDAREA BORDEROULUI DE PREPARARE.


--salvarea cantitatilor confirmate
--din itmp_bp trec in _bp
create or replace function logx.save_bp(_nrbp_ int)
returns text as
$$
begin
update logx._bp set _bp.qtyrez=itmp__bp.qtyrez from itmp__bp
WHERE _bp.nrbp=itmp__bp.nrbp and _bp.id=itmp__bp.id and _bp.nrbp=_nrbp_;
return 'OK';
end
$$
language 'plpgsql';

--BP se transforma in BL (borderou de livrare)


create or replace function valid_bp(_nrbp_ int)
returns text as
$$
DECLARE
f boolean;
BEGIN
select EXISTS(select * from _bp where _bp.nrbp=_nrbp_ and _bp.qtyconf>_bp.qtyrez) INTO f;
IF f THEN return 'Exista cantitati confirmate mai mari decat cantitatile rezervate'; END IF;
-- adauga in iesiri (tabelul outx ce contine borderourile de livrare)
INSERT INTO logx.outx(nrbl, destin, id, qtyliv, dep, ampl)
SELECT _bp.nrbp,bp_.destin,_bp.id,_bp.qtyliv,_bp.dep,_bp.ampl
FROM logx.bp_,logx._bp WHERE bp_.nrbp=_bp.nrbp AND _bp.nrbp=_nrbp_;
--actualizare stoc -- identificarea se face pentru intreaga cheie primara din tabelul logx.stx
UPDATE logx.stx SET qtyfiz=stx.qtyfiz-_bp.qtyconf, qtydisp=stx.qtydisp+_bp.qtyrez-
_bp.qtyconf
FROM logx._bp WHERE stx.dep=_bp.dep AND stx.amp=_bp.amp AND stx.id=_bp.id AND
_bp.nrbp=_nrbp_;
--sterge din BP
DELETE FROM logx._bp WHERE _bp.nrbp=_nrbp_;
DELETE FROM logx.bp_ WHERE bp_.nrbp=_nrbp_;
RETURN 'OK';
END
$$language 'plpgsql';

15
L8 - PROIECTAREA ȘI IMPLEMENTAREA
SISTEMULUI DE TRANSFER

Obiectiv: Proiectarea şi realizarea interogărilor SQL aferente sistemului de transfer între depozite;

---TRANSFER INTRE DEPOZITE


-- creare tabel transfer
CREATE TABLE logx.tr(nrbt int,datatr date,nrlin serial,dep_srs char(3),ampl_srs
varchar(10),dep_dest char(3),ampl_dest varchar(10), id char(11), qtytr int, CONSTRAINT k_tr
PRIMARY KEY(nrbt,nrlin));
ALTER TABLE logx.tr ADD CONSTRAINT tr_f1 FOREIGN KEY (id) REFERENCES logx.inx
(id);
ALTER TABLE logx.tr ADD CONSTRAINT tr_f21 FOREIGN KEY (dep_srs,ampl_srs)
REFERENCES logx.loc (dep,ampl);
ALTER TABLE logx.tr ADD CONSTRAINT tr_f22 FOREIGN KEY (dep_dest,ampl_dest)
REFERENCES logx.loc (dep,ampl);

-- crearea tabelelor master-slave ce vor contine informatiile necsare din Borderourile de transfer
-- pe masura ce sunt validate, liniile de aceste doua tabele vor fi sterse
DROP TABLE IF EXISTS logx._tr;DROP TABLE IF EXISTS logx.tr_;
CREATE TABLE logx.tr_(nrbt int PRIMARY KEY,databt date,dep_dest char(3),ampl_dest
varchar(10),
CONSTRAINT f2_tr_ FOREIGN KEY(dep_dest,ampl_dest) REFERENCES
logx.loc(dep,ampl));
CREATE TABLE logx._tr(nrbt int,id varchar(11),qtytr int DEFAULT 1,dep_srs varchar(3),
ampl_srs varchar(10),
CONSTRAINT k__tr PRIMARY KEY(nrbt,id,dep_srs,ampl_srs),
CONSTRAINT f1__tr FOREIGN KEY(id) REFERENCES logx.inx(id) ,
CONSTRAINT f2__tr FOREIGN KEY(dep_srs,ampl_srs) REFERENCES
logx.loc(dep,ampl),
CONSTRAINT f0__tr FOREIGN KEY(nrbt) REFERENCES logx.tr_(nrbt));
select * from logx.loc;
select * from logx.stx;
INSERT INTO logx.tr_ VALUES(1,'2013-05-17','ACC','AA1'),(2,'2013-05-18','ACC','AA1');
INSERT INTO logx._tr VALUES(1,'ABC6',1,'ABC','AA1'),(1,'ABC7',1,'ABC','AA1');
select * from logx.tr_;
select * from logx._tr;

--functia de validare
CREATE OR replace function logx.tr_valid(_nrbt_ int)
RETURNS text AS
$$
DECLARE
f boolean;
BEGIN
--verifica daca toate cantitatile ce urmeaza a fi transferate sunt disponibile
SELECT EXISTS(SELECT * FROM logx.stx,logx._tr
WHERE stx.dep=_tr.dep_srs AND stx.ampl=_tr.ampl_srs AND stx.id=_tr.id AND
stx.qtydisp<qtytr)INTO f;
IF f THEN RETURN 'Exista cantitati ce nu sunt disponibile ptr. tranfer!'; END IF;

16
--adauga in tabelul cu transferurile efectuate
INSERT INTO logx.tr( nrbt, datatr, dep_srs, ampl_srs, dep_dest, ampl_dest,
id, qtytr)
SELECT tr_.nrbt, tr_.databt, _tr.dep_srs, _tr.ampl_srs, tr_.dep_dest, tr_.ampl_dest,
_tr.id, _tr.qtytr FROM logx.tr_,logx._tr
WHERE _tr.nrbt=tr_.nrbt AND _tr.nrbt=_nrbt_;
--daca exista inregistrari le actualiozeaza cu noile cantitati
UPDATE logx.stx SET qtyfiz=qtyfiz+_tr.qtytr, qtydisp=qtydisp+_tr.qtytr
FROM logx._tr,logx.tr_ WHERE tr_.dep_dest=stx.dep AND tr_.ampl_dest=stx.ampl
AND _tr.id=stx.id AND _tr.nrbt=tr_.nrbt AND _tr.nrbt=_nrbt_;
--daca nu exista inregistrarile noi (dep,loc,id) le adauga DOAR pe cele care NU se regasesc in
stoc(dep,ampl,id)
INSERT INTO logx.stx(dep, ampl, id, qtyfiz, qtydisp)
SELECT par.dep,par.ampl,par.id, _tr.qtytr, _tr.qtytr FROM
(SELECT tr_.dep_dest as dep, tr_.ampl_dest as ampl, _tr.id
FROM logx._tr,logx.tr_ WHERE _tr.nrbt=tr_.nrbt AND _tr.nrbt=_nrbt_
EXCEPT
SELECT stx.dep,stx.ampl,stx.id FROM logx.stx,logx.tr_ WHERE tr_.dep_dest=stx.dep AND
tr_.ampl_dest=stx.ampl
-- se poate si fara ultima conditie dar poate creste timpul de interogare
)par,logx._tr,logx.tr_
WHERE _tr.id=par.id AND tr_.dep_dest=par.dep AND tr_.ampl_dest=par.ampl AND
_tr.nrbt=tr_.nrbt AND _tr.nrbt=_nrbt_;
--ATENTIE: se va realiza mai intai UPDATE si apoi INSERT altfel cantitatile se pot dubla

-- SE REAlizeaza scaderea din stoc (pentru SURSA)


UPDATE logx.stx SET qtyfiz=qtyfiz-_tr.qtytr, qtydisp=qtydisp-_tr.qtytr
FROM logx._tr WHERE _tr.dep_srs=stx.dep AND _tr.ampl_srs=stx.ampl
AND _tr.id=stx.id AND _tr.nrbt=_nrbt_;

-- daca in urma scaderii ramante qtyfiz =0 aceste linii se vor sterge


DELETE FROM logx.stx WHERE qtyfiz=0;
--sterge liniile din tabelele naster-slave (tr_ si _tr) corespunzatoare _nrbt_
DELETE FROM logx._tr WHERE nrbt=_nrbt_;
DELETE FROM logx.tr_ WHERE nrbt=_nrbt_;
RETURN 'OK';
END
$$ language plpgsql;

select logx.tr_valid(1);
select * from logx.tr_;
select * from logx._tr;
select * from logx.stx;

17
L9 - PROIECTAREA ȘI IMPLEMENTAREA
RAPOARTELOR PRIVIND INTRĂRILE

Obiectiv: Proiectarea şi implementarea interogărilor SQL pentru rapoartele privind intrările, stocul
curent şi livrările

--- -- CONSTRUCTIA FUNCTIILOR PENTRU RAPOARTE

-- TIPURI DE RAPOARTE: intrari, stoc + istoric stoc, livrari(iesiri), transfer, fisa de magazie
-- Pentru toate rapoartele:
-- pentru fiecare camp de selectie vor exista 2 bife:
-- prima determina daca acel camp/parametru va aparea ca si coloana in tabelul rezultat ---
gruparea se realizeaza dupa ansambul coloanelor din tabelul rezultat
-- afisearea seriei va inhiba/ascunde campul cantitate (deoarece are peste tot valoarea 1 --- seria
fiind unica)
-- A doua bifa semnifica activarea sau dezactivarea filtrului pentru marimea/coloana/parametrul
corespunzator

-- RAPORTUL PENTRU INTRARI


/*
ARGUMENTE:
_nr_ : numarul de campuri ce sunt in fereastra de selectie
_nume_[]: vectorul cu numele campurilor/coloanelor
_tabel_[]: vector cu tabelele corespondente pentru fiecare camp/colana
_tip_[]: vectorul ce contine tipul fiecarui camp din fereastra de selectie:
C - sir de caractere - cautare exacta - case sensitive(tine cont de litera mare sa mica)
A - sir de caractere - cautare aproximativa - case insensitive(nu tine cont de litera mare sa
mica)
D1 - data calendaristica : valoare exacta
D2 - data calendaristica : data va fi preluata ca interval
N1 - data de tip numeric : valoare exacta
N2 - data de tip numeric : interval
_a_[] : vectorul cu bifele pentru afisarea campurilor
_s_[]: vectorul cu bifele pentru selectia/filtrarea campurilor
_ord_ : campul dupa care se face ordonarea (un singur camp)
_tipQ_ : tipul interogarii: IN-intrare,ST-stoc,OUT-iesire, TR-transfer

*/
CREATE OR REPLACE FUNCTION logx.q_x(_tipQ_ text,_nr_ smallint,_nume_ text[], _tip_
text[], _a_ boolean[], _s_ boolean[], _val1_ text[], _val2_ text[],_ord_ text)
returns text AS
$$
DECLARE
vald1_ date[];
vald2_ date[];
valn1_ numeric[];
valn2_ numeric[];
valAC_ text[];
valb_ boolean[];

18
exeQ text; -- contine sirul final pe baza caruia se realizeaza interogarea (comanda SQL finala)
codR text; -- raspunsul functiei : OK - iesire cu executie pana la capat a interogarii
achA text; -- sirul format pentru alcatuirea exeQ ce contine partea de afisare a
coloanelor/campurilor din cda SQL
achS text; -- sirul format pentru alcatuirea exeQ ce contine partea cu contitiile de selectie din cda
SQL
achG text; -- sirul format pentru alcatuirea exeQ ce contine partea cu GRUPUL din cadrul czii
SQL
achO text; -- sirul format pentru alcatuirea exeQ ce contine partea cu ORDER BY din cadrul czii
SQL
achDA text;--achDA: drepturi acces -- utilizatorii pot vedea doar anumite magazii --- DOAR
MAGAZIILE/DEPOZITELE cu drepturi de acces valide vor fi luate in rezultatul interogarii!
achLegTab text;--inner join
achFROM text;
achTmpTable text;--nume tabel rezultat
i int; f boolean;r int;
BEGIN
-- REZULTATUL interogarii va fi pus in tabelul TEMPORAR dat de achTmpTable

achA:='';achS:='';achG:='#';achO:='';codR:='OK';f:=false;
--achDA:=' AND ';
-- testare existenta date pentru filtru selectie
FOR i IN 1.._nr_
LOOP
IF _s_[i] AND _val1_[i]='' THEN codR='Selectie fara valoare pentru '||_nume_[i]||'!'; RETURN
codR; END IF;
IF _s_[i] AND (_tip_[i]='N2' OR _tip_[i]='D2') AND _val2_[i]='' THEN codR='Selectie fara
valoare pentru '||_nume_[i]||'!'; RETURN codR; END IF;
IF _a_[i] AND _nume_[i]=_ord_ THEN f:=true; END IF; IF _ord_='---' THEN f:=true; END
IF;
END LOOP;
IF NOT f THEN codR:='Campul dupa care se realizeaza ordonarea trebuie sa se regaseasca in
optiunile de afisare pentru coloane !'; RETURN codR; END IF;
--conversie date
FOR i IN 1.._nr_
LOOP
IF _tip_[i]='D1' THEN vald1_[i]:=_val1_[i];END IF;
IF _tip_[i]='D2' THEN vald1_[i]:=_val1_[i];vald2_[i]:=_val2_[i];END IF;
IF _tip_[i]='N1' THEN valn1_[i]:=_val1_[i];END IF;
IF _tip_[i]='N2' THEN valn1_[i]:=_val1_[i];valn2_[i]:=_val2_[i];END IF;
IF _tip_[i]='B' THEN valb_[i]:=_val1_[i];END IF;
IF _tip_[i]='A' OR _tip_[i]='C' THEN valAC_[i]:=_val1_[i];END IF;
END LOOP;
-- constructie cda SQL
FOR i IN 1.._nr_
LOOP
IF _a_[i] THEN
achA := achA ||','|| _nume_[i]; --intai va fi sum(qty)
if achG='#' then achG:=''; ELSE achG := achG ||','; end if;
achG := achG || _nume_[i];

19
END IF;
IF _s_[i] AND _tip_[i]='A' THEN achS:=achS||' AND '||_nume_[i]||' ILIKE ''%'||valAC_[i]||'%''';
END IF;
IF _s_[i] AND _tip_[i]='C' THEN achS:=achS||' AND '||_nume_[i]||' = '||quote_literal(valAC_[i]);
END IF;
IF _s_[i] AND _tip_[i]='B' THEN achS:=achS||' AND '||_nume_[i]||' IS '||_valb_[i]; END IF;
IF _s_[i] AND _tip_[i]='N1' THEN achS:=achS||' AND '||_nume_[i]||' = '||valn1_[i]; END IF;
IF _s_[i] AND _tip_[i]='N2' THEN achS:=achS||' AND '||_nume_[i]||' >= '||valn1_[i]||' AND '||
_nume_[i]||' <= '||valn2_[i]; END IF;
IF _s_[i] AND _tip_[i]='D1' THEN achS:=achS||' AND '||_nume_[i]||' = to_date('||
quote_literal(_valc_[i])||','||quote_literal('dd.mm.yyyy')||')';END IF;
IF _s_[i] AND _tip_[i]='D2' THEN achS:=achS||' AND '||_nume_[i]||' >= to_date('||
quote_literal(_valc_[i])||','||quote_literal('dd.mm.yyyy')||')
AND '||_nume_[i]||' <= to_date('||quote_literal(_vald_[i])||','||
quote_literal('dd.mm.yyyy')||')';END IF;
END LOOP;
IF _tipQ_ ='IN' THEN achTmpTable:='q_tmp_in'; achFROM:=' FROM logx.inx,logx.nom ';
achLegTab:=' nom.idcode=inx.idcode '; END IF;
IF _tipQ_ ='ST' THEN achTmpTable:='q_tmp_st'; achFROM:=' FROM
logx.inx,logx.nom,logx.stx '; achLegTab:=' nom.idcode=inx.idcode AND inx.id=stx.id '; END IF;
IF _tipQ_ ='OUT' THEN achTmpTable:='q_tmp_out';achFROM:=' FROM
logx.inx,logx.nom,logx.outx '; achLegTab:=' nom.idcode=inx.idcode AND inx.id=outx.id '; END
IF;
IF _tipQ_ ='TR' THEN achTmpTable:='q_tmp_tr';achFROM:=' FROM
logx.inx,logx.nom,logx.tr '; achLegTab:=' nom.idcode=inx.idcode AND inx.id=tr.id '; END IF;

IF achG IS NOT NULL THEN achG:=' GROUP BY '||achG; END IF;


achS:=' WHERE '||achLegTab||achS;
IF _ord_!='---' THEN achO:=' ORDER BY '||_ord_; ELSE achO:=''; END IF;
exeQ:='DROP TABLE IF EXISTS q_tmp_in ;
CREATE TEMPORARY TABLE '||achTmpTable||' AS SELECT SUM(qty) as qty '||achA||
achFROM||achS||achG||achO||';';
RAISE NOTICE 'Interogarea: % ',exeQ;
EXECUTE exeQ;
GET DIAGNOSTICS r := ROW_COUNT; RAISE NOTICE 'Q_tmp_IN: % inregistrari',r;
RETURN codR;
END
$$LANGUAGE plpgsql;

--TESTE
SELECT * FROM logx.inx;
SELECT logx.q_x('IN'::text,4::smallint,ARRAY['inx.idcode','inx.stare','inx.furnizor','nom.descr'],
ARRAY['C','C','C','A'], ARRAY[true,true,true,true], ARRAY[false,false,false,false],
ARRAY[NULL,NULL,NULL,NULL], ARRAY[NULL,NULL,NULL,NULL] ,'---'::text);
select * from q_tmp_in;
--descrierea sa contina secventa 'ra'
SELECT logx.q_x('IN'::text,4::smallint,ARRAY['inx.idcode','inx.stare','inx.furnizor','nom.descr'],
ARRAY['C','C','C','A'], ARRAY[true,true,true,true], ARRAY[false,false,false,true],
ARRAY[NULL,NULL,NULL,'ra'], ARRAY[NULL,NULL,NULL,NULL] ,'---'::text);
select * from q_tmp_in;

20
21
TESTE
#T1

Se dau doua tabele ce reprezintă nomenclatoare (nom1 şi nom2). Acestea conţin: cod produs (sir
alfanumeric), descriere, referinţă tehnică, data omologării. Să se scrie comenzile SQL pentru:

1. Crearea tabelului nom1

2. Adăugarea unei înregistrări în nom1, fara valoare ptr. referinţa tehnică

3. Adăugarea sirului „RDC” la inceputul descrierii pentru codurile care au ultimul caracter: 'q'

4. Ştergerea valorilor pentru data omologării care nu au referinţa tehnică introdusă

. 5.Afişarea numărului de coduri identice şi valoarea acestora.

6. Ştergerea din nomenclator a liniei/liniilor ce conţine/conţin cea mai veche omologare

7. Unificarea celor două nomenclatoare în unul singur (nomenclatoarele conţin şi date comune)

R:
create schema c8;
--1 -- drop table c8.nom1
CREATE TABLE c8.nom1(cod varchar(10), descr varchar(100), reft varchar(30), dataog date);
--2
--varianta 2.1
INSERT INTO c8.nom1(cod,descr, dataog) VALUES ('A1','DDD1',CURRENT_DATE-10);
--varianta 2.2
INSERT INTO c8.nom1(cod,descr,reft, dataog) VALUES
('A2q','DDD2',NULL,CURRENT_DATE-8);
--varianta 2.3
INSERT INTO c8.nom1(cod,descr,dataog) VALUES
('A3','DDD3',to_date('29.05.2004','dd.mm.yyyy'));
--varianta 2.4
INSERT INTO c8.nom1(cod,descr,dataog) VALUES ('A4q','DDD4','2005-07-30');
-- 3
UPDATE c8.nom1 SET descr='RDC'||descr WHERE LIKE '%q';
--4
--
UPDATE c8.nom1 SET dataog=NULL WHERE reft IS NULL;
-- 5
select cod, count(cod) AS nrcoduri FROM c8.nom1 GROUP BY cod;
--6
DELETE FROM c8.nom1 WHERE dataog=(SELECT MIN(dataog) FROM c8.nom1);
--7
-- select * from c8.nom1 -- select * from c8.nom2
SELECT cod,descr,reft, dataog FROM c8.nom1
UNION
(
SELECT cod,descr,reft, dataog FROM c8.nom2

22
EXCEPT
SELECT cod,descr,reft, dataog FROM c8.nom1
);

-- alta varianta

SELECT DISTINCT CASE WHEN nom1.cod IS NOT NULL THEN nom1.cod ELSE nom2.cod
END,
CASE WHEN nom1.descr IS NOT NULL THEN nom1.descr ELSE nom2.descr END,
CASE WHEN nom1.reft IS NOT NULL THEN nom1.reft ELSE nom2.reft END,
CASE WHEN nom1.dataog IS NOT NULL THEN nom1.dataog ELSE nom2.dataog END
FROM c8.nom1 FULL OUTER JOIN c8.nom2
ON nom1.cod=nom2.cod AND nom1.descr=nom2.descr AND nom1.reft=nom2.reft AND
nom1.dataog=nom2.dataog;
/*
Brandusa Daniel
select nom1.*,nom2.* FROM c8.nom1 FULL OUTER JOIN c8.nom2 ON nom1.cod=nom2.cod
*/

/* Condrache Lorand
drop table t1; drop table rezult;
create temp table t1 as
select * from c8.nom2
except
select * from c8.nom1;

create temp table rezult as


select * from c8.nom1;

insert into rezult(cod, descr,reft,dataog)


select * from t1;
select * from rezult;

*/

#T2

Pentru monitorizarea unui proces tehnologic sunt utilizate următoarele tabele: mas (măsurători) şi
par (parametri). Codurile punctelor de măsură (pctMas) sunt unice la nivel de modul, iar codurile
parametrilor măsuraţi (codPar) sunt unice la nivelul punctelor de măsură.
mas (afişate doar două înreg,selectate aleator) par (afişate doar 2 înreg oarecare)
data ora codUnicPar pct cod val operat modul pct cod codUnicPar u valMin valMax
Ma Par or Mas Par m
s
21.12.2009 08:00:00.002 MM01P1sQ01 P1 Q09 19.4 user1 MM01 P1 Q01 MM01P1sQ0 V -0.8 +30.6
1
19.12.2009 00:00:00.012 MM01P1jRM P1 N06 12 user2 MM02 P1 Q03 MM01P1mQ0 A -14.5 +15.9
01 3
De asemenea presupunem că mai există încă trei tabele mas1, mas2 şi mas3, având structura
identică cu mas.

23
1.Scrieţi comanda SQL pentru crearea tabelelor mas şi par (denumirile câmpurilor, tipurile de
date, cheile primare şi externe)

2. Scrieţi comanda SQL pentru inserarea unei înregistrari în tabelul mas

3. Scrieţi comanda SQL pentru afişarea tuturor măsurătorilor din ziua curentă (din tabelul mas)

4. Scrieţi comanda SQL pentru înlocuirea valorii 'Q01' a câmpului codPar, din tabelul mas, cu
valoarea 'S02'

5. Scrieţi comanda SQL pentru ştergerea înregistrărilor, anterioare zilei curente, care nu au câmpul
val completat

6. Scrieţi comanda SQL pentru afişarea valorilor medii pentru parametrii măsuraţi, în ziua
anterioară, de către operatorul user3

7. Scrieţi comanda SQL pentru afişarea numărului de măsurători, din ziua curentă, pentru fiecare
punct de măsură

8. Scrieţi comanda SQL pentru ştergerea din tabelul mas a valorilor ce depăşesc limita maximă
(din par)

9. Scrieţi comanda SQL care să înlocuiască valorile din câmpul val cu valoarea din câmpul
valMin pentru măsurătorile a căror valoare este sub limita minimă

10. Scrieţi comanda SQL care să afişeze câmpurile data, codUnicPar şi un nou camp denumit
interpretare. Acest nou câmp poate conţine: LOW pentru valorile situate în prima treime a
intervalului dat de câmpurile valMin şi valMax, MEDIUM pentru valorile situate în a doua
treime a intervalului dat de câmpurile valMin şi valMax şi MAX pentru valorile situate în ultima
treime a intervalului dat de câmpurile valMin şi valMax

11. Scrieţi comanda SQL care să adăuge datele din mas1 şi mas2 în tabelul mas (o singură
interogare)

12. Scrieţi comanda SQL care să adauge din tabelul mas3 în tabelul mas numai datele care nu se
regasesc şi în tabelul mas

13. Scrieţi comanda SQL care să construiască din tabelele mas1, mas2 şi mas3 un singur tabel
având structura: data, codUnicPar, pctMas, codPar, valMZ1,valMZ2,valMZ3 . Câmpurile valMZx
(x=1,2,3) reprezintă valorile medii pentru fiecare zi corespunzătoare fiecărui tabel. Fiecare tabel
conţine şi date (calendaristice) de măsurare care nu se regăsesc în celelalte tabele

14. Scrieţi o funcţie care preia numele operatorului şi întoarce numărul de înregistrări efectuate în
ziua curentă

24
15. Scrieţi o funcţie care preia un interval de tip dată calendaristică şi întoarce valorile
diferenţelor dintre două măsurători consecutive ale aceluiaşi parametru.

#T2
Pentru gestiunea datelor dintr-un laborator de analize fizico-chimice sunt utilizate tabelele :
ba(buletine de analize) şi czi (comenzile pentru analize). Tabelul ba conţine rezultatele analizei.
Tabelul czi conţine comanda solicitantului descrisă prin datele de identintificare ale solicitantului
şi denumirea analizelor solicitate (a denumirii parametrilor a căror valori vor fi determinate). Unei
comenzi îi pot corespunde mai multe buletine de analize. De asemenea, uneori, nu sunt executate
toate determinările solicitate (în tabelul ba, pentru o anumită comandă, nu se vor regăsi toate
denumirile parametrilor din tabelul czi )
ba (afişate doar două înreg,selectate aleator) czi (afişate doar 2 înreg oarecare)
Nr_ba data_ba Denumire_p UM valoare Nr_cd nr_cda solicitant data_cda Denumire_paramet
arametru a ru
A5B1 21.12.2009 amoniac mg/l 0.5 15 120 Marco srl 21.12.2009 conductivitate
A3C5 19.12.2009 aluminiu mg/l 0.002 201 180 Alfa srl Q03 pH

1.Scrieţi comanda SQL pentru crearea tabelelor ba şi czi (denumirile câmpurilor, tipurile de date,
cheile primare şi externe)

2. Scrieţi comanda SQL pentru inserarea unei înregistrari în tabelul ba

3. Scrieţi comanda SQL pentru afişarea tuturor comenzilor primite în ziua curentă

4. Scrieţi comanda SQL pentru modificarea denumirii solicitantului 'Alfa srl' cu ' SC Alfa SA'

5. Scrieţi comanda SQL pentru ştergerea înregistrărilor din tabelul ba, anterioare zilei curente,
care nu au câmpul UM completat

6. Scrieţi comanda SQL pentru afişarea valorilor medii pentru fiecare parametru determinat.
Perioada de calcul va fi dată de ultimele 10 zile (pornind de la data curentă )

7. Scrieţi comanda SQL pentru afişarea parametrilor ce au fost solicitaţi dar nu au fost determinaţi

8. Scrieţi comanda SQL pentru ştergerea din tabelul ba a înregistrărilor corespunzătoare


solicitantului 'Beta srl'

9. Scrieţi comanda SQL care să afişeze câmpurile nr_ba şi nr_cda pentru cazul în care diferenţa
între data_ba ţi data_dca este mai mare de o săptămână

10. Se dă un tabel ba2 având o structură identică cu tabelul ba. Să se scrie o interogare SQL care
să adauge în ba2 toate înregistrările din ba care nu se regăsesc în ba2.

#T3

25
Pentru monitorizarea unui proces tehnologic sunt utilizate următoarele tabele: mas (măsurători) şi
par (parametri). Codurile punctelor de măsură (pctMas) sunt unice la nivel de modul, iar codurile
parametrilor măsuraţi (codPar) sunt unice la nivelul punctelor de măsură.
mas (afişate doar două înreg,selectate aleator) par (afişate doar 2 înreg oarecare)
data ora codUnicPar val operator modul pctMas cod codUnicPar u valMin valMax
Par m
21.12.2009 08:00:00.002 MM01P1sQ0 19.4 user1 MM01 P1 Q01 MM01P1sQ0 V -0.8 +30.6
1 1
19.12.2009 00:00:00.012 MM01P1jRM 12 user2 MM02 P1 Q03 MM01P1mQ0 A -14.5 +15.9
01 3
De asemenea presupunem că mai există încă trei tabele mas1, mas2 şi mas3, având structura
identică cu mas.
1.Scrieţi comanda SQL pentru crearea tabelelor mas şi par (denumirile câmpurilor, tipurile de
date, cheile primare şi externe)

2. Scrieţi comanda SQL pentru inserarea unei înregistrari în tabelul mas

3. Scrieţi comanda SQL pentru afişarea tuturor măsurătorilor din ziua curentă (din tabelul mas)

4. Scrieţi comanda SQL pentru înlocuirea valorii 'Q01' a câmpului codPar, din tabelul mas, cu
valoarea 'S02'

5. Scrieţi comanda SQL pentru ştergerea înregistrărilor, anterioare zilei curente, care nu au câmpul
val completat

6. Scrieţi comanda SQL pentru afişarea valorilor medii pentru parametrii măsuraţi, în ziua
anterioară, de către operatorul user3

7. Scrieţi comanda SQL pentru afişarea numărului de măsurători, din ziua curentă, pentru fiecare
punct de măsură

8. Scrieţi comanda SQL pentru ştergerea din tabelul mas a valorilor ce depăşesc limita maximă
(din par)

9. Scrieţi comanda SQL care să înlocuiască valorile din câmpul val cu valoarea din câmpul
valMin pentru măsurătorile a căror valoare este sub limita minimă

10. Scrieţi comanda SQL care să afişeze câmpurile data, codUnicPar şi un nou camp denumit
interpretare. Acest nou câmp poate conţine: LOW pentru valorile situate în prima treime a
intervalului dat de câmpurile valMin şi valMax, MEDIUM pentru valorile situate în a doua
treime a intervalului dat de câmpurile valMin şi valMax şi MAX pentru valorile situate în ultima
treime a intervalului dat de câmpurile valMin şi valMax

11. Scrieţi comanda SQL care să adăuge datele din mas1 şi mas2 în tabelul mas (o singură

26
interogare)

12. Scrieţi comanda SQL care să adauge din tabelul mas3 în tabelul mas numai datele care nu se
regasesc şi în tabelul mas

13. Scrieţi comanda SQL care să construiască din tabelele mas1, mas2 şi mas3 un singur tabel
având structura: data, codUnicPar, pctMas, codPar, valMZ1,valMZ2,valMZ3 . Câmpurile valMZx
(x=1,2,3) reprezintă valorile medii pentru fiecare zi corespunzătoare fiecărui tabel. Fiecare tabel
conţine şi date (calendaristice) de măsurare care nu se regăsesc în celelalte tabele

14. Scrieţi o funcţie care preia numele operatorului şi întoarce numărul de înregistrări efectuate în
ziua curentă

15. Scrieţi o funcţie care preia un interval de tip dată calendaristică şi întoarce valorile
diferenţelor dintre două măsurători consecutive ale aceluiaşi parametru.

#T4

A. Se dă următorul sistem de gestiune a stocurilor dat de tabelele:


in(data date, id serial, serialno varchar(20), cod varchar(30), furnizor varchar(30), loc_ini
varchar(10)), st(serialno varchar(20), loc varchar(10)),
out(data date, destin varchar(30),serialno).
Seria este unica pentru fiecare produs.

A1. Să se adauge cheile primare corespunzătoare;

A2. Să se adauge cheile externe corespunzătoare;

A3. Să se scrie o interogare pentru ștergerea din stoc a produselor care apar în tabelul de
ieșiri/livrări (out);

Să se scrie o interogare care să furnizeze un raport cu:


A4. stocul curent pentru produsele ce conțin codul MXR10;

A5. intrarile în locația A10B11 în ultimele 10 zile;

A6. ieșirile/livrările din ziua curentă cu produsele ce aparțin furnizorului F1X ;

A7. numarul produselor existente în stoc ce conțin în serie secvența de caractere gsm;

A8. stocul anterior cu un an pentru produsele ce conțin codul BTWR11;

A9. produsele care se află în stoc de cel puțin un an.

#T5

Într-o magazie se primesc role de cablu. Fiecare rolă are: serie_rola - unică, lungime cablu,
cod_cablu, furnizor. Se dă următorul sistem de gestiune a stocurilor dat de tabelele de intrări(in),
stoc(st) și de ieșiri(out) :
in(data date, serie_rola varchar(20), cod_cablu varchar(30), lungime numeric, furnizor

27
varchar(30), amp_ini varchar(10)),
st(serie_rola varchar(20), lungime numeric, amp varchar(10)),
out(data date, destin varchar(30), serie_rola varchar(20), lungime numeric, amp varchar(10)).
Campul amp_ini reprezintă amplasamentul inițial din cadrul magaziei

1. Să se scrie interogările necesare pentru livrarea a 10.5 m de cablu cu codul “MXZ” din rola cu
seria “SR1” ( actualizare stoc, adăugare în tabelul de ieșiri) ;

2. Să se scrie o interogare pentru eliminarea din stoc a rolelor cu mai puțin de 5 m, intrate în stoc
de cel puțin un an.

Să se scrie o interogare care să furnizeze un raport cu:


3. Lungimea totală a cablului din stoc pentru fiecare cod de cablu în parte.

4. intrarile pe amplasamentul A10B11 în ultimele 10 zile (cod_cablu, lungime);

5. ieșirile/livrările din ziua curentă cu produsele ce aparțin furnizorului F1X (cod_cablu,


lungime);

6. numărul total de role din stoc ce conțin în serie_rola secvența de caractere 'LNK';

7. Stocul (cod_cablu, lungime) în urmă cu un an (la sfârștul zilei , cu un an în urmă);

#T6
Într-un depozit se primesc bare de 6 m lungime şi se livrează bare de 1m, 2m, 3m şi 6 m. Fiecare
bară intrată are ataşat: cod bară (unic la nivelul unui lot de bare), furnizor, diametru, tip_otel. Se
dă următorul sistem de gestiune a stocurilor dat de tabelele de intrări(in), stoc(st) şi de ieşiri(out) :
in(idx serial, data date, cod varchar(20), furnizor varchar(30), diametru int, tip_otel varchar(10),
nr_buc int, amp_ini varchar(10)),
st(idx int, lungime numeric, amp varchar(10), nr_buc int),
out(data date, destinatar varchar(30), idx int, lungime numeric, amp varchar(10), nr_buc int).
Campul amp_ini reprezintă amplasamentul iniţial din cadrul magaziei.

1. Să se adauge cheile primare corespunzătoare (se vor scrie doar cheile)

2. Să se adauge cheile externe (se vor scrie doar cheile)

Să se scrie o interogare care să furnizeze un raport cu:


3. Numărul total de bare intrat în ziua curentă (nr_buc).

4. Numărul total de bare pentru fiecare cod livrat în ziua curentă (cod, nr_buc, lungime);

5. Lungimea totală a barelor livrată în ziua curentă către fiecare destinatar (destinatar,
lungimea_totala)

6. Stocul curent pe fiecare furnizor (furnizor, cod, lungime, nr_buc)

7. Lungimea totala a barelor din stoc primite de la un anumit furnizor pe fiecare amplasament
(amp,cod, lungime_totala)

28
8. Stocul, pe fiecare cod în urmă cu un an (cod, lungime, nr_buc)

#T7
Într-o magazie se primesc componente electronice, fiecare componenta avand o serie
unica. Fiecare echipament este caracterizat prin: serie, referinta comerciala, referinta tehnica,
descriere, furnizor, valoare, furnizor. Se dă următorul sistem de gestiune a stocurilor dat de
tabelele de intrări(in), stoc(st), ieșiri(out), nomenclator (nom). Echipamentele sunt introduse in
gestiune unul cate unul. Magazia este organizata pe amplasamente. Referinta tehnica si descrierea
se regasesc numai in tabelul nom. Referinta comerciala este unica la nivelul nomenclatorului.

A1. Să se scrie structura celor patru tabele;

A2. Să se scrie o interogare pentru verificarea intrarilor pe fiecare amplasament pentru data
curenta.(amplasament, serialno, ref.comerciala, ref. Tehnica, descriere, furnizor).

B Să se scrie o interogare care să furnizeze un raport cu:


B3. Numarul de echipamente primit de la fiecare furnizor in ultima saptamana (furnizor,
nr_de_echipamente).

B4. Stocul cu echipamentele disponibile ce nu au campul cu descrierea completat.

B5. Valoarea echipamentelor livrate in ziua curentă, de pe amplasamentul A1, pe fiecare furnizor
in parte ;(furnizor, valoare_totala)

B6. Stocul in urma cu un an (serie, ref.comerciala, descriere)

C7. Explicati rezolvarea accesului concurential din momementul livrarii;

#T8
Se considera un sistem de baze de date ce monitorizeaza activitatea dintr-o parcare. In acest sens
se dau tabelele: Tmisc cu intrarile si iesirile din parcare si tabelul Tplati cu platile efectuate.
Tabelul Tmisc contine campurile: data_in, data_out,_ora_in,ora_out,nr_inmatr. Tabelul Tplati
contine campurile: data_out, ora_out, val, nr_inmatr. Plata se realizeaza in momentul iesirii din
parcare. Campurile ora sunt de tip time.

A1.Scrieţi cda. SQL pentru crearea tabelelor Tmisc si Tplati(den. câmpurilor, tipurile de date,chei
primare/externe)

A2. Scrieţi comanda SQL pentru inserarea unei înregistrari în tabelul Tmisc şi a unei
inreg(corelata cu prima) in tabelul Tplati

A3. Scrieti comanda SQL pentru determinarea timpului de stationare pentru o masina care
paraseste parcarea.

A4. Scrieţi comanda SQL pentru actualizarea unui numar de inmatriculare introdus gresit in
ambele tabele. Se corecteaza doar operatia realizata in ziua curenta.

29
A5. Scrieţi comanda SQL pentru afisarea numarului de autovehicule existent in parcare exact cu
24 de ore in urma.

A6. Scrieţi comanda SQL pentru afişarea incasarilor anuale pe fiecare masina.(nr_imatr, an,
valoare_incasata)

B1.Scrieţi o funcţie plpgsql care să verifice daca toate autoturismele ce au iesit din parcare si sunt
inregistrate in Tmisc au platit stationarea.

B2. Scrieţi o funcţie plpgsql care să întoarcă un tabel cu autoturismele ce au stationat, in total,
mai mult de 2 ore pe zi in ultima saptamana.

#T9
A. Într-o magazie se primesc componente electronice, fiecare componentă având o serie unica
(serialNo). Fiecare echipament este caracterizat prin: serialNo, codItem, descriere, furnizor,
valoare. Se dă următorul sistem de gestiune a stocurilor dat de tabelele de intrări(Tin), stoc(Tst),
ieșiri(Tout), nomenclator (Tnom). Echipamentele sunt introduse in gestiune unul cate unul.
Magazia este organizata pe amplasamente. Descrierea se regaseşte numai in tabelul Tnom.
CodItem este unic la nivelul nomenclatorului.
A1. Să se scrie structura celor patru tabele;

A2. Să se scrie o interogare pentru verificarea intrarilor pe fiecare amplasament (codAmp) pentru
data curentă (codAmp, serialNo, codItem, descriere, furnizor).

B Pentru magazia de la punctul A să se scrie o interogare care să furnizeze un raport cu:


B3. Numarul de echipamente primit de la fiecare furnizor în ultima săptamană (furnizor,
nr_de_echipamente).

B4. Stocul cu echipamentele disponibile la nivel de codItem (doar pe tipuri de echipamente –


codItem, codAmp, nr_de_echipamente)

B5. Valoarea echipamentelor livrate în urmă cu 3 zile, de pe amplasamentul A1, pe fiecare


furnizor in parte (furnizor, valoare_totala)

B6. Stocul în urma cu un an (serialNo, codItem, descriere)

C. Într-o magazie se primesc role cu cablu. Fiecare rolă este caracterizată de: cod_cablu, lungime
cablu, furnizor. Din magazie se poate livra rola întreagă sau doar un anumit număr de metri.
C1. Să se scrie o variantă a tabelelor necesare pentru gestiunea informatică a acestei magazii
(structura tabelelor).

C2. Să se scrie interogarea ce furnizează stocul curent (cod_cablu, număr_role, lungime_rolă,


amplasament). Numărul de role este raportat la fiecare lungime rămasă.

30
#T10

Într-un depozit sunt recepţionate/intrate componente pentru două categorii de produse. Aceste
componente sunt asamblate şi livrate din alte două depozite ( livrarea fiecărei categorii de
produse se realizează din câte un depozit).
Produsele sunt identificate prin ItemCode, ItemCateg (categoria produsului - două valori
posibile ), SerialNo(doar pentru o parte din acestea), UM, Valoare. Trecerea între magazia de
intrare şi magaziile de livrare se realizează prin operaţii de transfer.

Depozit
Virtual T
Depozit B
Depozit A
(zona de
asamblare) Depozit C

1. Să se specifice tabelele necesare şi legătura între acestea;


2. Să se specifice structura tabelelor implicate;
3. Să se detalieze operaţiile de transfer sau să se scrie codul SQL aferent acestora;
4. Să se detalieze operaţiile de livrare (creare borderou preparare + borderou livrare) sau să
se scrie codul SQL aferent acestora.

#T11
1. O aplicaţie de gestiune a stocurilor conţine tabelele: intrări, stoc(produse cu serii), stoc(produse
fără serii), livrări(produse cu serii), livrări(produse fără serii), transfer(produse cu serii) ,
transfer(produse fără serii), ecart(produse cu serii), ecart(produse fără serii). Să se scrie relaţia sau
relaţiile ce trebuie să existe între cantităţile existente în cadrul tabelelor.

2. O aplicaţie de gestiune a stocurilor conţine tabelele: comenzi, intrări, transfer(în cadrul aceluiaşi
depozit), transfer (între depozite diferite), ecart, ieşiri (definitive), ieşiri (temp.). Să se descrie
procedura / interogarea tabelelor astfel încât să se obţină afişarea stocului existent la o anumită
dată calendaristică (istoric stoc).

3. Descrieţi pe scurt structura tabelelor şi realizarea operaţiilor de transfer pentru o aplicaţie de


gestiune a stocurilor bazată pe stări şi evenimente(tranziţii).

4.Descrieţi pe scurt etapele realizării modelului ABC al stocurilor.

#T12

Se dă următoarea structură a unei magazii:


În depozitul A sunt stocate accesoriile (produse fără serie), iar în depozitul B sunt stocate produse
având serii unice. Fiecare tip de produs este caracterizat printr-un cod: ItemCode. Accesorile
conţin şi RefItemCode (ItemCod-ul produsului pentru care sunt fabricate). Intrările în cele două
magazii sunt realizate prin două tipuri de borderouri de recepţie distincte (serie/cantitate). În
momentul recepţiei este preluat din nomenclatorul de produse ItemCode. În nomenclator se mai
gaseşte ataşat descrierea produsului (ItemDescr). Produsele se livrează din depozitul C. În
momentul creării borderoului de preparare sunt ataşate automat şi accesoriile. Numărul acestora
pentru fiecare tip de produs cu serie este specificat în nomenclator. Amplasamentele sunt
codificate pe 5 caractere.
Depozitul A
Livrare
Recepţie Depozitul C
marfă
marfă 31
Depozitul B
1. Să se specifice tabelele necesare şi legătura între acestea;
2. Să se specifice structura tabelelor implicate;
3. Să se detalieze operaţiile de recepţie sau să se scrie codul SQL aferent acestora;
4. Să se detalieze operaţiile de transfer sau să se scrie codul SQL aferent acestora;
5. Să se s detalieze operaţiile de livrare (creare borderou preparare + borderou livrare) sau să
se scrie codul SQL aferent acestora.

32

S-ar putea să vă placă și