SQL Queries for Employee Management
SQL Queries for Employee Management
from tab;
select *
from employees;
select *
from departments;
-- concat columns
select employee_id, first_name ||' is son of '|| last_name || ' take salary = ' || salary as emp_report
from employees;
-- alias
select employee_id, first_name ||' is son of '|| last_name || ' take salary = ' || salary as emp_report
from employees;
select employee_id, first_name ||' is son of '|| last_name || ' take salary = ' || salary as "Emp Report"
-- only alias uses the double qoutation " " …. Other wise we use a single qout
from employees;
-- arithmatic operations + - * /
select employee_id, last_name, salary, salary * 12 as annual_salary
from employees;
-- the arithmetic operations execution order is like math >> brackets then * and / then + and - >> * and / what
comes first is excuted first
select *
from employees
where salary >= 8000;
select *
from employees
where department_id = 30
and salary >= 8000;
-- example, show all employees work in dept 30, 60 salary >= 8000
select *
from employees
where (department_id = 30
or department_id = 60)
and salary >= 8000; -- ??????????????????????
select *
from employees
where lower ( last_name) like lower ('K%');
-- example, show all employees with last name has a character before the last r
select *
from employees
where last_name like '%r_';
-- is null
select *
from employees
where department_id = null; -- XXXXXXX = null de bnst5dmha m3a el update fqt
select *
from employees
where department_id is null;
-- functions
-- Character functions: upper , lower, length, instr, substr
-- you can use the upper and lower in select statement and in where condition
-- instr ====> searches for the charecter or a word in the column ==> (colimn_name, letter, no. of letter to begin
with)
-- substr ==> substring === > btqt3 el klma
-- ==========================================
-- +++++ day 2 +++++++
-- replace >>>>> replace (column_name, what you want to be replaced , to be replaced by ...) 3 parameters
--- we didn`t update the table we use it in the display only
select *
from employees
where employee_id in (104,105);
select *
from employees
where trim(first_name) = trim (lower( 'Bruce Austin'));
select *
from employees
where trim(first_name) = trim ( 'Bruce Austin');
--- you can use it like this aslo ===> where trim(first_name) = trim('Bruce Austin');
-- note ==> we used it in the display only we didn`t update it in the table yet
update employees
set first_name = trim(first_name)
where employee_id in (104, 105);
select employee_id, last_name, salary, round (salary, 2), round (salary, 0), round (salary),
trunc (salary, 2), trunc (salary, 0), trunc (salary)
from employees
where employee_id in (104, 105);
-- example: 140 seconds .... how many minutes ? how many remaing seconds?
select 140/60 as minutes, mod (140, 60)as remaining_seconds
from dual;
-- example: 14 months ... how many years? how many remaining months?
select 14/12 as years, mod (14, 12) as remaining_months
from dual;
--------------------------------------------------
select sysdate
from dual;
-- ######## VIP#########
-- to modify the date format
-- 2- to_char function [conversion function: convert from date to character ]
-- to control date format [to show the date in a specific format]
-- By that we converted it to a character and know we can not make date functions on it
-- Formatting Time
-- he will modify the am to pm if its pm
select to_char (sysdate, 'hh12:mi:ss am'),
to_char (sysdate, 'hh24:mi:ss')
from dual;
select *
from employees
where hire_date = to_date ('21-09-2005', 'dd-mm-yyyy');
-- 8-9-1997 is a character type ==> to convert from character type to date type use:
select to_date ('8-9-1997', 'dd-mm-yyyy')
from dual;
-- task : show the remaining days [Accurate] ; Note: Do not use 29,30,31, 365 366
to_number( to_char( ,'dd'),'99')
-- 4. last_day ==> date function : To get the last day in current month or for a specific month
-- example: 5-2-2024 ===> to get the last day for a specific month you have to add any date in that month
-- 5. next_day function: to get the nearst sunday for example from today
-- to get the nearst Mon from the begin of the next month
select next_day (last_day (sysdate), 'Mon') -- we didn`t add 1 to the last_day in case the beg of the next month
would be Mon
from dual;
select employee_id, last_name, salary, salary + 100 -- if their is any null value it would not be included
from employees;
select employee_id, last_name, salary, nvl(salary, 0) + 100 -- here we converted the null value into zero so it would
be included in the equation
from employees;
-- 1. case expression:
from employees;
-- 2. decode:
from employees;
-- 2. decode function
select employee_id, last_name, salary, job_id,
decode(job_id, 'AD_VP', salary + salary * 0.1,
'IT_PROG', salary + salary * 0.2,
'FI_MGR', salary + salary * 0.3,
salary) as salary_review
from employees;
select round (sysdate, 'Month'), round(sysdate, 'Year'), -- to round to the nearest big. (Up or down)of the month\
year \\\ up if after june
trunc (sysdate, 'Month'), trunc(sysdate, 'Year') -- to back to the big. of the month\ year
from dual;
-------------------------
--- conversion functions ..... cont.
--- 1. to_char - {convert date to char < to print date in a specific format > \
-- convert Number to char < > to print number in a specific format > 7500 : 7,500.00$
select sum(salary), max(salary), min(salary), count(*) -- the result will be in one row \\ so don`t use a select
statement of a column thaat reults a column with the agregate functions >>> error
from employees
where department_id = 30;
-- example: get sum of salary per each department >>> here we can use a selection of a column that result in many
rows with the aggregate functions as it will result in many rows itself
select department_id, sum(salary) -- you can`t select any column that doesn`t exist in the group by >>> so firstly
think in what you want to group by it
from employees
group by department_id;
-- AVG function
select avg(salary), sum(salary)/count(*) -->>>>> results are different >>> why??? >>> because of the null values
that didn`t include in AVG while it is included in the equation
from employees;
select avg( nvl(salary,0) ), sum(salary)/count(*) -->>>>> here we solved the problem as it included the
employees who have null values after converting it to 0
from employees;
select round (avg( nvl(salary,0) ), 2), sum(salary)/count(*) -- >>> round is to round the decimal to the nearest 2
digits
from employees;
-----------------------------#####-----------------
/*
join >>>> used to retrieve data from more than one table so you need to know the FKs
so if the tables needed to be displayed are in 2 tables >>> you have to usee the join
or if you have subquery inside subquery ... etc use the join to enhance the performance
1. inner join
2. outer join
3. self join
*/
-- 1. inner join
-- Between 2 tables
select
from >> 2 tables_to _be_ joined
where fk = pk
-- 3 tables
select employee_id, last_name, salary, employees.department_id, department_name, departments.location_id, city
from employees, departments, locations
where employees.department_id = departments.department_id
and departments.location_id = locations.location_id; -- number of condions for
joining = no. of tables - 1
-- [Link] join
select employee_id, last_name, salary, emps.department_id, department_name
from employees emps left outer join departments depts
on emps.department_id = depts.department_id; -- we can`t put the join condition in the where condion as we used
the keyword outer join in the from statement
--3. self join
select
from employees emps, employees mgrs
where fk = pk;
/*
Emps Mgrs
1 >> 1
M (fk) << 1
then the relation would be one to many and the fk will be in the many side */
------------------------------------------------------------------
------------------------------------------------------------------
---------------Sub query ______________________________
--## single row subquery >>> = > < <= >=
-- example: get all employees data works with employee (115) in his department
-- there is a missing information we do not have and we need wnd it is not in the same table so we need to
acquire it firstly
-- the sunquery must give me one result
select *
from employees
where department_id = (select department_id from employees where employee_id = 115)
and employee_id != 115; -- to exclude the employee no. 115 as we want the employees who work with him only
-- example: get the employee data with the max salary within all employees
select *
from employees
where salary = (select max (salary) from employees); -- we used the sub query as we can not use the aggregate
functions in the where condition
select *
from departments
where department_id = (select department_id from employees); -- ERROR because the ssub query gives me more
than one value >> multi rows
-- example: get all departments which have NO employees [When use not in : take care of Nulls in sub query]
select *
from departments
where department_id not in (select department_id from employees); -- NOT correct
-- >>> When use not in : take care of Nulls in sub query as it will give me the null only
select *
from departments
where department_id not in (select department_id from employees where department_id is not null); -- or use NVL
select *
from departments
where department_id not in (select Nvl (department_id, 0) from employees );
-- example: get employees datawith salary > ALL\Any salaries of employees work in dept 30
-- > any means greater than the minimum
-- > all means greater than the highest
select *
from employees
where salary > All (select salary from employees where department_id = 30); -- greater than the highest
select *
from employees
where salary > Any (select salary from employees where department_id = 30); -- greater than the minimum
--==========================================
--=================DAy 4++++++++++++++++++++
update employees
set salary = 11000
where employee_id = 207;
--ddl
alter table employees
modify email varchar2(100);
update employees
set email = employee_id ||'.'||first_name||'.'||last_name||'@gmai;.com',
salary = (select salary + 1000 from employees where employee_id = 112),
manager_id = (select manager_id from employees where employee_id = 107)
where employee_id = 207;
------------------ delete
-- children are rmoved firstly then the parent
--========================================
---------======== DDLS: Data Definition Language >>> Auto commit -----
--1. create
-- Example:
-- 1- depts tables [department_id number 4 pk \ department_name varchar2(100) not null]
-- 2- emps table [employee_id number 4 pk \ employee_name varchar2 100 \ employee_salary number 8,2
check sal > 500 \ employee_email varchar2 100 unique department_id number 4 fk]
/*onstraints in Databases:
primary key
foreign key
noy null
check
5.
6.
*/
--------------------------------
-- create table : using sub query : to make a backup from existing table[with data or eithout data]
-- No constraints passed ; not null
-- with data
-- with no data
create table employees3
as
select * from employees
where department_id = -1; -- to give us the strucure of the table only without data >> we put a condition that
will never be met
--------------------------------
----------------------------
-- 5. Alter DDL Command
-- drop column
alter table emps
drop column retired; -- remember it is auto commit (DDL)
------------------------------------------------
--6. Drop DDL Command: to remove all dta and structure of a table >>> auto commit
drop table employees_backup;
-- Flshback : To return back Table dropped >> can be used for a specific time (only for 4 hours)
Flashback table employees_backup to before drop;
drop table employees_backup purge; >>> it can not be flashed back now
--------------------------------------------------------------------
------------------------- Other schema Objects ---------------
-- 1. DB sequence >> to auto increment
-- identity : the same (auto increment) but its in the version 12c
select emps_seq.nextval
from dual; -- here we made a equence that didn`t saved in the table but when we use it again in the table it will
continue on these number
-----------------------------------------------------
-------------------- 2. ddDB Views ---------------
-- stored select statement in the database as an object to be used more than once easily
-----------------------\
-- if you update a view >> the table will be updated
--------------------------------
-- View Types:
-- 1. Simple view [pfrom 1 table - no functions - no group - allow DMLs]
-- 2. Complex view [from more than one table - may have functions - may have group by -no DMLs allowed]
select *
from simple_emps_view;
update simple_emps_view
set employee_salary = employee_salary + 1000; -- Now we udated the table itself
select *
from simple_vu_60;
update simple_vu_60
set department_id = 30; -- here the view will retrieve no data as we damaged the condition tyhe view is based on
>> so we will use the check option
update simple_vu_60
set department_id = 30; -- ERROR , here it will not work
------------------------------------------------------------------------------------------------------------------------
--======================= DAy 5=======================================
-- DB index:
-- stored object on a column
-- to speed up retrival of data
-- and to speed up join
-- when wew search >> it goes record by record >> aaaaaall recoerds >> this is a huge headache
-- so the solution is to use the indexes >> it maps to the the result of the column you indexed >> pointing to each
record in the column you indexed
-- the index is updated automatically when there is a change in the column indexed >> so you have to choose the
column that is not updated regularly
-- the index is used by the dbms in the retrieval >> you just create it
---------------------------------------------------------------------------------------------------------------------------------
-- 5. synonym db object : alias for a db object
-- if the table name is too large for example and you need to make it shorter for easy retrieve but without renaming it
-- here we can call the table by bothits original name and the synonym
-- you can say it is a permenant alias not for one select statement only
-- you can use them both the oorigianl and the synonym for all
create synonym locy for locations;
select * from locy;
select * from locations;
create public synonym pub_locy for [Link]; -- hr is the name of the schema
-- if you have many users and this table is not one of their tables now we gave them access to this table
-- public synonym is for retrieval onlyyyyyyyy
-- must be ran by admin >> by sys >>>> that is why we specified the schema
---------------------------------------------------------------------------------------------------------------------------------------
--
=======================================================================
===
-- we need to know data about our data
select * from all_tables; -- all tables that exist in the schema in all users
select * from user_tables; -- used by the dba all tables that exist even in the sys
select * from v$_tables; -- retrieve the data related to the performance >> to detect a problem for example
-- for columns
select * from user_ind_columns; -->>> indexes on columns
select * from user_cons_columns; -->>> constraints on columns
-- 1. system priveledges >> create - alter - drop >> (with admin option) >> DDL
-- 2. object priveledge >> select -insert - update - delete >> (with grant option) >> DML
--=====
-- Roles: Group of priveledges
-- steps:
-- 1. create role.
--2. grant priveleges to role.
-- 3. grant role to users.
--================================================================
-- plsql block
begin
-- begin section
-- variables >> columns in the select means 4 variables
end;
set serveroutput on
declare
v_last_name varchar2(100);
v_salary varchar2(100);
v_hire_date date;
v_department_id number(4);
begin
select last_name, salary, hire_date, department_id
into v_last_name, v_salary, v_hire_date, v_department_id
from employees
where employee_id = 107;
DBMS_OUTPUT.PUT_LINE('name is '||v_last_name|| ', take salary = '||v_salary);
DBMS_OUTPUT.PUT_LINE('hiredate = '||v_hire_date|| ', work in dept = '||v_department_id);
end;
set serveroutput on
declare
v_last_name varchar2(100);
v_salary number(8, 2);
v_hire_date date;
v_department_id number(4);
v_annual_salary number (10, 2);
v_upper_name varchar2(100);
v_years number(2);
v_department_name varchar2 (100);
begin
select last_name, salary, hire_date, department_id
into v_last_name, v_salary, v_hire_date, v_department_id
from employees
where employee_id = 107;
--====================================
--===========if========================
declare
v_salary number(8, 2);
v_tax number(3);
v_net_salary number(10, 2);
begin
select salary
into v_salary
from employees
where employee_id = 107;
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++
--
=======================================================================
======
--------------------------------------------------------------------------------------------------------------------------------------------
-- DAy 6---
set serveroutput on
declare
begin
set serveroutput on
declare
v_last_name varchar2(100);
v_salary number(8, 2);
v_department_id number(4);
v_annual_salary number (10, 2);
begin
--
=======================================================================
===========================================
set serveroutput on >>> --could be written one time per session >> in any tap
-- if you got the errpr " the buffer overflow limit" >>use this "set serveroutput on size 1000000" >> the highest limit
1000000
declare
i number(3) := 100;
v_last_name varchar2(100);
v_salary number(8, 2);
v_department_id number(4);
begin
Loop
select last_name, salary, department_id
into v_last_name, v_salary, v_department_id
from employees
where employee_id = i;
end;
------------------------------------------------------------------------------------------------------------------------------------------------
----------------------
-- 3. While Loop
declare
i number(3) := 100;
v_last_name varchar2(100);
v_salary number(8, 2);
v_department_id number(4);
begin
-- While condition_to_continue Loop -- as long as the condition is met >> the loop continues
While i < 121 Loop
select last_name, salary, department_id
into v_last_name, v_salary, v_department_id
from employees
where employee_id = i;
i := i + 1;
end Loop;
end;
-- the size of the variables >> must be based on the db tables >> the right way is to go to the schema and look for
the sizes
-- you can make the size be the same of the column and table by using this in the declaration section: by using the
percentage type >>"variable table_name.column_name %tpe;"
declare
i number(3) := 100;
v_last_nameemployees.last_name%type;
v_salary [Link]%type;
v_department_id employees.department_id&type;
begin
------------------------------------------------------------------------------------------------------------------------------------------------
---
-- 4. plsql records
declare
v_emp_record employees%rowtype;
v_annual_salary number(10, 2);
v_years number(2);
begin
select * -- we can use * here as we can store all the columns record in one variable so we don`t need to specify
the name of each column and then assign each in a specific variable
into v_emp_record -- one variable that stores a result of an entire row rather than one value
-- while the scalar variable stores a value with no internal components.
from employees
where employee_id = 107;
-- dbms_output.put_line(v_emp_record); -- ERROR \\ you have to erite the cell (column name) you need to print
dbms_output.put_line(v_emp_record.employee_id||' , last name= '||v_emp_record.last_name||' , salary
'||v_emp_record.salary);
dbms_output.put_line(' Annual salary= '||v_annual_salary||' , years hired '||v_years);
end;
-------------------------------------------------------------------------------------------------------------------------------------
-- 5. plsql record with loop
declare
v_emp_record employees%rowtype;
v_annual_salary number(10, 2);
v_years number(2);
begin
for i in 100..120 loop -- here he will print for employees from 100 to 120
select *
into v_emp_record
from employees
where employee_id = i;
end;
------------------------------------------------------------------------------------------------------------------------------------------------
-- 6. plsql cursor
set serveroutput on
declare
cursor emp_cursor is
select * from employees
where department_id = 60
and salary is not null
order by salary desc;
begin
-- Loop over cursor >> we use the for loop >> but not the original one >> for loop designed for the cursir >>
called cursor for loop
for v_emp_record in emp_cursor loop -- the record is declared by default >> built in declaration
dbms_output.put_line(v_emp_record.employee_id||', last name = '||v_emp_record.last_name||' ,salary =
'||v_emp_record.salary||' , dept id = '||v_emp_record.department_id);
end loop; -- the loop ill end when the cursor will be empty >> built in condition
set serveroutput on
declare
cursor emp_cursor is
select *from employees
where department_id = 30;
v_sal_text varchar2(50);
v_years number(2);
v_hire_text varchar2(50);
begin
for v_emp_record in emp_cursor loop
if v_emp_record.salary >= 10000 then
v_sal_text := 'High salary';
else
v_sal_text := 'Low salary';
end if;
end;
Answer :
declare
cursor emp_cursor is
select * from employees
where department_id = 30;
v_sal_text varchar2(50); v_years number(2); v_hire_text varchar2(50);
begin
for v_emp_record in emp_cursor loop
if v_emp_record.salary >= 10000 then
v_sal_text := 'High Salary';
else
v_sal_text := 'Low Salary';
end if;
v_years := months_between(sysdate, v_emp_record.hire_date)/12;
if v_years >= 15 then
v_hire_text := 'Old Employee';
else
v_hire_text := 'Young Employee';
end if;
-alter table employees -- >>> This is a nSQL statement to make a new column called retired that
we will use in the example
add retired varchar2 (1) default 'N';
-- Program loop for each employee : check for his hired years >= 15 : make retired : Y
select * from employees;
set serveroutput on
declare
cursor emp_cursor is
select * from employees;
v_years number(2);
begin
for v_emp_record in emp_cursor loop
v_years := months_between (sysdate, v_emp_record.hire_date)/12;
begin
v_salary := 5000;
v_salary := v_salary / 0; -- error 3 >> dividing by 0
v_salary := 'ahmed'; -- error 2 >> wrong value type
Exception -- Exception section >> to handle the exceptions || -- the first error only will appear as the code will stop
where ever it finds an error and not go further
when no_data_found then
rollback; -- very important to protect the database from any mistakes
dbms_output.put_line('Please enter a valid employy id');
when value_error then -- even if the size is not right it will give me this error
rollback;
dbms_output.put_line('Salary should be only numbers');
/*
when others then;
-- Log Error [store error in a table]
insert into err_table
(table columns, err_date)
values(sqlcode,, sqlerrm); -- built in functions
------------------------------------------------------------------------------------------------------------------------------
--2. non-predefined exceptions
begin
insert into departments
(department_id, department_name)
values
(401, null);
exception
when insert_except then
dbms_output.put_line('dept name cannot be empty');
end;
----------------------------------------------------------------------------------------------------------------------------------------------
-- 3. user define exceptions
declare
begin
update employees
set salary = salary + 1000
where department_id = 3; -- this will not give me error >> in the update and delete statements
dbms_output.put_line('program continue');
end;
---------------------------------------------------------------------------------------------------------------------------------------
-- 4.
-- procedure : stored plsql in the db >> like the view in the sql [stored select statement] >> stored and we call it to
execution multiple times without needing to write it again >>> DMLs
-- function : stord function that we can call multiple times >> only a function without DDMLs
-- Example: program to update employee salary by a bonus [ procedure >> DMLs >> anonymous block
begin
update employees
set salary = salary + v_bonus
where employee_id = v_emp_id;
end;
---------------------------------------------------------------------------------------------------------------------------------
-- 5. Procedure update_salary
-- procedure name: update salary [ take 2 parameters number] : update salary of employee with a bonus
create or replace procedure update_salary(v_emp_id number, v_bonus number) -- 2 parameters >> -- every time
we must get 2 values from the user -- don`t declare the size
is
begin
update employees
set salary = salary + v_bonus
where employee_id = v_emp_id;
end;
-----------------------------------------------------------------------------------------------------------------------------------------
begin
update_salary(105, 2000); -- calling the procedure
update_salary(107, 4000);
update_salary(114, 5000);
end;
select employee_id, salary from employees;
end;
--
=======================================================================
=
--7. Anonymous for functions
-- 8. Functions
-- 8. call for functions
declare
v_emp_id number(4) :=107;
v_tax_perc number(4) := 10;
v_salary number(8,2);
v_tax_value number(8, 2);
begin
select salary
into v_salary
from employees
where employee_id = v_emp_id;
begin
select salary
into v_salary
from employees
where employee_id = v_emp_id;
declare
v_tax_value := calc_tax(107, 10); -- the value of the function must must must be stored in a variable
dbms_output.put_line('tax value = '||v_result);
end;
-- One of the main advantages of functions is that it could be called from sql [ almost used in reports] >> by select
statement
--
=======================================================================
====================