-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathP10.sql
310 lines (248 loc) · 8.38 KB
/
P10.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
drop procedure Company.uspDeleteEmployee
go
create procedure Company.uspDeleteEmployee
@ssn char(9)
as
begin
delete from Company.[Works_on] where Essn=@ssn
delete from Company.[Dependent] where Essn=@ssn
update Company.[Department] set Mgr_ssn=null where Mgr_ssn=@ssn
update Company.[Employee] set Super_ssn=null where Super_ssn=@ssn
delete from Company.[Employee] where Ssn=@ssn
end
go
declare @ssn char(9)
exec Company.uspDeleteEmployee @ssn='12652121'
go
--(b) Crie um stored procedure que retorne um record-set com os funcionários gestores de departamentos, assim como o ssn
-- e número de anos (como gestor) do funcionário mais antigo dessa lista.
drop procedure uspDeptManager
go
create procedure uspDeptManager
@ssn char(9) output,
@nOfYears int output
as
begin
select Ssn, Fname, Minit, Lname, Bdate, [Address], Sex, Salary, Super_ssn, Dnumber, Dname, Mgr_start_date
from Company.Employee join Company.Department on Ssn=Mgr_ssn
select @ssn = Mgr_ssn, @nOfYears=max(DATEDIFF(year, Mgr_start_date, getdate()))
from Company.Department
where Mgr_ssn is not null
group by Mgr_ssn, Mgr_start_date
order by Mgr_start_date desc, Mgr_ssn asc
end
go
declare @Ssn char(9)
declare @numberOfYears int
exec uspDeptManager
@ssn = @Ssn output,
@nOfYears=@numberOfYears output
print @ssn
print @numberOfYears
go
-- (c) Construa um trigger que não permita que determinado funcionário seja definido como gestor de mais do que um departamento
drop trigger Company.OnlyOneDeptMgr
go
create trigger Company.OnlyOneDeptMgr on Company.Department
after insert, update
as
begin
set nocount on
declare @mgrSsn char(9)
declare @n int
select @mgrSsn=Mgr_ssn from inserted;
set @n = ( select count(Mgr_ssn)
from Company.Department
where Mgr_ssn=@mgrSsn
)
if (@n>1)
begin
raiserror ('Não podes ser mgr de mais que um dept', 16,1);
rollback tran;
end
end
go
insert into Company.Department values ('My Dept1',8,null,'2018-01-01')
go
-- (d) Crie um trigger que não permita que determinado funcionário tenha um vencimento superior ao vencimento do gestor do seu departamento.
-- Nestes casos, o trigger deve ajustar o salário do funcionário para um valor igual ao salário do gestor menos uma unidade.
drop trigger Company.dontEarnMorethanDeptMgr
go
create trigger Company.dontEarnMorethanDeptMgr on Company.Employee
after insert, update
as
begin
set nocount on
declare @Mgr_salary decimal(6,2)
declare @Dno int
declare @ssn char(9)
declare @sal decimal(6,2)
select @Dno=Dno, @sal=Salary, @ssn=Ssn from inserted;
select @Mgr_salary=Salary
from Company.Department join Company.Employee on Mgr_ssn=Ssn
where Dnumber=@Dno
if (@sal > @Mgr_salary)
begin
update Company.Employee
set Salary=@Mgr_salary-1
where Ssn=@ssn
end
end
go
insert into Company.Employee values ('Vasco', 'A', 'Ramos', '123456789', '1999-07-08', 'Rua ola', 'M', '2500', null, 2);
go
-- (e) Crie uma UDF que, para determinado funcionário (ssn), devolva o nome
-- e localização dos projetos em que trabalha.
drop function Company.EmplProjects
go
go
create function Company.EmplProjects (@ssn char(9)) returns Table
as
return (select Pname, Plocation
from (Company.Employee join Company.Works_on on Ssn=Essn) join Company.Project on Pno=Pnumber
where Ssn=@ssn
)
go
select *
from Company.EmplProjects ('342343434');
go
-- (f) Crie uma UDF que, para determinado departamento (dno),
-- retorne os funcionários com um vencimento superior à média dos vencimentos desse departamento;
drop function Company.EmpBestSalaries
go
go
create function Company.EmpBestSalaries (@dno int) returns Table
as
return (select Ssn, Fname, Minit, Salary, Dno
from Company.Employee
where Dno=@dno and salary > (select avg(Salary)
from Company.Employee
where Dno=@dno
)
)
go
select * from Company.EmpBestSalaries (2)
go
-- (g) Crie uma UDF que, para determinado departamento, retorne um record-set com os projetos desse departamento.
-- Para cada projeto devemos ter um atributo com seu o orçamento mensal de mão de obra e outra coluna com o valor acumulado do orçamento.
drop function Company.employeeDeptHighAverage
go
go
create function Company.employeeDeptHighAverage (@dnumber int) returns @ProjBudget Table
(pName varchar(30), pnumber int not null, plocation varchar(15), dnum int, budget decimal, totalbudget decimal)
as
begin
declare @pName as varchar(30), @pnumber as int, @prevPnumber as int, @plocation as varchar(15),
@dnum as int, @budget as decimal, @totalbudget as decimal, @hours as decimal, @salary as decimal;
declare c cursor fast_forward
for select Pname, Pnumber, Plocation, Dnum, [Hours], Salary
from (Company.Project join Works_on on Pnumber=Pno) join Company.Employee on Essn=Ssn
where Dnum=@dnumber;
open c;
fetch c into @pName, @pnumber, @plocation, @dnum, @hours, @salary;
select @prevPnumber = @pnumber, @budget = 0, @totalbudget = 0;
while @@fetch_status = 0
begin
if @prevPnumber <> @pnumber
begin
insert @ProjBudget values (@pName,@prevPnumber,@plocation,@dnum,@budget,@totalbudget);
select @prevPnumber = @pnumber, @budget = 0;
end
set @budget += @salary*@hours/40;
set @totalbudget += @salary*@hours/40;
fetch c into @pName, @pnumber, @plocation, @dnum, @hours, @salary;
end
close c;
deallocate c;
return;
end
go
select * from Company.employeeDeptHighAverage (3);
go
-- (h) Pretende-se criar um trigger que, quando se elimina um departamento,
-- este passe para uma tabela department_deleted com a mesma estrutura da department.
-- Caso esta tabela não exista então deve criar uma nova e só depois inserir o registo.
-- Implemente a solução com um trigger de cada tipo (after e instead of).
-- Discuta vantagens e desvantagem de cada implementação.
-- (h1) Usando after!
drop trigger Company.deleteDepartmentAfter
go
go
create trigger Company.deleteDepartmentAfter on Company.[Department]
after delete
as
begin
-- begin transaction
begin transaction
-- get department number
declare @dNumber int
select @dNumber=Dnumber from deleted;
--check if exists a table for the deleted departments
--if not, create it
if (not exists( select * from information_schema.tables where table_schema='Company' and table_name='Department_deleted'))
begin
create table Company.Department_deleted
(
Dname varchar(30) not null,
Dnumber int not null,
Mgr_ssn char(9) null,
Mgr_start_date date null,
primary key(Dnumber)
)
alter table Company.Department_deleted add constraint deptDeletedEmp foreign key (Mgr_ssn) references Company.Employee (Ssn);
end
begin try
-- insert into the deleted department table
insert into Company.Department_deleted
select * from deleted
end try
begin catch
raiserror ('Error deleting department', 16, 1)
end catch
commit transaction
end
go
select * from Company.Department_deleted
delete from Company.Department where Dnumber=8
-- (h2) Usando instead of!
drop trigger Company.deleteDepartment
go
go
create trigger Company.deleteDepartment on Company.[Department]
instead of delete
as
begin
-- begin transaction
begin transaction
-- get department number
declare @dNumber int
select @dNumber=Dnumber from deleted;
--check if exists a table for the deleted departments
--if not, create it
if (not exists( select * from information_schema.tables where table_schema='Company' and table_name='Department_deleted'))
begin
create table Company.Department_deleted
(
Dname varchar(30) not null,
Dnumber int not null,
Mgr_ssn char(9) null,
Mgr_start_date date null,
primary key(Dnumber)
)
alter table Company.Department_deleted add constraint deptDeletedEmp foreign key (Mgr_ssn) references Company.Employee (Ssn);
end
begin try
-- insert into the deleted department table
insert into Company.Department_deleted
select * from deleted
-- delete the department
delete from Company.Department where Dnumber=@dNumber;
end try
begin catch
raiserror ('Error deleting department', 16, 1)
end catch
commit transaction
end
go
select * from Company.Department_deleted
delete from Company.Department where Dnumber=8