How to fetch the deleted records? - sql

How to fetch the deleted records. I am using Oracle 10g.

Do you have a backup before the deletion? ...or you could try using flashback (SELECT AS OF)
http://docs.oracle.com/cd/E11882_01/appdev.112/e41502/adfns_flashback.htm#ADFNS01003
Hope I've understood your question correctly.

Do some research into the RETURNING clause: https://docs.oracle.com/cd/B19306_01/appdev.102/b14261/returninginto_clause.htm
https://docs.oracle.com/cd/B19306_01/appdev.102/b14261/collections.htm#BABHDGIG
The link has a fully-functional example with an UPDATE statement. I'm sure if you spent some time on it you can figure out how to make it work with a DELETE statement as well.
DECLARE
TYPE EmpRec IS RECORD (last_name employees.last_name%TYPE,
salary employees.salary%TYPE);
emp_info EmpRec;
emp_id NUMBER := 100;
BEGIN
UPDATE employees SET salary = salary * 1.1 WHERE employee_id = emp_id
RETURNING last_name, salary INTO emp_info;
DBMS_OUTPUT.PUT_LINE('Just gave a raise to ' || emp_info.last_name ||
', who now makes ' || emp_info.salary);
ROLLBACK;
END;
/

Related

Oracle Block Statement DBMS output syntax

I made this account just for this question because I'm really not sure how to word it properly for google to pick up on it. So here goes...
I was working on a query for a group project that I was assigned in my database II course. I made 2 and was working on a third when I wanted to see if I could do something like the following.
declare
Emp_ID := 03;
Salary_Increment := 2.0 --constants do not change
Salary_ID := 03;
Current_Salary := 47500
Updated_Salary := Current_Salary * 2.0
BEGIN
dbms_output.put_line('The Employee with the ID of' +Emp_ID 'will receive a 2% bonus.');
dbms_output.put_line('This Employees new salary will be: ' +Updated_Salary ');
end;
I attempted to do this previously but with a more simple code snippet. Figured I would see if I could do this just to simplify how much I have to type out.
TL;DR - Can I use a reference like +Emp_ID in a Oracle SQL dbms output?
In oracle, There are two ways of concating the string.
using || operator.
Like this.
dbms_output.put_line('The Employee with the ID of' || Emp_ID || ' will receive a 2% bonus.');
using CONCAT method.
Like this:
dbms_output.put_line(CONCAT(CONCAT('The Employee with the ID of', Emp_ID), ' will receive a 2% bonus.'));
Note that CONCAT uses only two parameter as input. So you need to use it multiple times to concat more than 2 strings.
Cheers!!
The string concatenation operator is || in PL/SQL, so you'd want to write
dbms_output.put_line('The Employee with the ID of' || Emp_ID || ' will receive a 2% bonus.');

Create row level trigger that computes the total salary for each newly inserted employee

I need to Create a row level trigger that computes the total salary for each newly inserted employee - trigger before insert and before update of the salary or bonus fields. I also need to Use the :NEW fields to store the data.
So far I have: I cant really figure out how to display the total salary, I believe I set up the beginning right, just not sure about the rest after FOR EACH ROW WHEN
CREATE OR REPLACE TRIGGER
TRG_Step3_TotSalary
BEFORE UPDATE OF salary, bonus ON Lab12_Employees
FOR EACH ROW WHEN (Salary + Bonus = :NEW.TotalSalary);
BEGIN
INSERT :NEW.Salary + bonus
DBMS_OUTPUT.PUT_LINE('New Salary =' || (:NEW.TotalSalary);
Untested but I belive the below should work
CREATE OR REPLACE TRIGGER
TRG_Step3_TotSalary
BEFORE UPDATE OF salary, bonus ON Lab12_Employees
FOR EACH ROW
BEGIN
:NEW.TotalSalary := :NEW.Salary + bonus
DBMS_OUTPUT.PUT_LINE('New Salary =' || (:NEW.TotalSalary);
END

Using PL/SQL to develop relationship among two tables?

I am new to the PL/SQL language and I am working on a problem and was looking for advice to the right direction to go. Any help would be greatly appreciated!
I have an Employee table and a Building table.
The Employee table consists of Employee_ID, Last_Name, First_Name, and Job(F/P) full or part time.
The Building table consists of Employee_ID and Building_location.(This is the location where the employee works from) either a home or office.
I want the user to type in the last_name from user input. As a result I am looking for the information from the employee: Employee Name, Job (full or part employee) and the building_location. For example, I want my output to look something like this if the user typed in Johnson:
Employee Name Job Position Building Location
====================================================
Andre Johnson Part Time Home Office
Nick Johnson Full Time Downtown Office
If a user types in any string I want to list all Employees who work for the company. But if the name is on the Employee table like 'Johnson' is then it only displays Johnson. Would I need to add in another SELECT clause?
At this point I put together some code that checks if the employee works for the company or not. I am looking to build from this.
ACCEPT p_1 PROMPT 'Please enter the last name of the employee:'
DECLARE
v_name employee.last_name%TYPE := '&p_1';
v_lname employee.last_name%TYPE;
v_fname employee.first_name%TYPE;
v_jobpos employee.job%TYPE;
v_buildtype building.building_type%TYPE;
v_count NUMBER;
BEGIN
SELECT COUNT(*)
INTO v_count
FROM employee
WHERE UPPER(last_name) = UPPER(v_name);
IF v_count = 0 THEN
DBMS_OUTPUT.PUT_LINE('EMPLOYEE NAME Job Position Building Location');
DBMS_OUTPUT.PUT_LINE('----------------------------------------------------' );
for i in (select * from employee order by last_name) loop
DBMS_OUTPUT.PUT_LINE(i.last_name || ', ' || i.first_name)
end loop;
ELSE
for i in (select * from employee order by last_name) loop
DBMS_OUTPUT.PUT_LINE(i.last_name || ', ' || i.first_name);
end loop;
END IF;
END;
You can do this. The simplest way might be like this:
...
IF v_count = 0 THEN
DBMS_OUTPUT.PUT_LINE(v_name || ' Does not work here.');
/* New code starts here! */
DBMS_OUTPUT.PUT_LINE('Employees are:');
for r in (select * from employees) loop
dbms_output.put_line(r.last_name||', '||r.first_name);
end loop;
/* New code ends here! */
ELSE
...
end if;
end;

Validating whether an emp is a manager in oracle

I am trying to build a trigger that would not allow users to give a salary higher than 10,000 to employees but if the employee is a manager, I don't want the user to be able to give less than 15000 of a salary.
What I reached so far is the following
create or replace trigger sal_check
before update or insert on emp
for each row
begin
if :new.sal > 10000
then
update emp set sal = 10000;
end if;
end;
Now can I please take a hint of how to do a check whether the employee is a manager or not?
Note : I am using Oracle, and this is running on Scott schema, the one that actually comes with Oracle by default.
If emp table has mgr column and you set up foreign key constraint, it's enough just to check whether mgr field is not null. Also, update emp set sal = 10000; in your code will cause ORA-04091 (table is mutating), you need to change it to :new.sal := 1000. So you trigger will look like
...
if :new.mgr IS NULL THEN
if :new.sal > 10000
then
:new.sal := 10000;
end if;
ELSE
if :new.sal < 15000
then
:new.sal := 15000;
end if;
END IF;
I think you should create a table (not temporary) with all the managers.
Afterwords, it would be quite easy to detect if a employee is a manager or not and by making a simple select on that table you could see what should be the salary.
To determine what employees should be on the table, it would be the ones in the mgr column.

Updating database records in a loop?

declare
begin
for i in (select * from emp)
loop
if i.sal=1300 then
update emp
set sal=13000;
end if;
end loop;
end;
This code is updating all the records with salary 13000. Instead i want to update records having salary 1300 to the value 13000. Can you tell where I made a mistake?
I am accesing records using implicit cursor..
for every record i am checking the sal value of that record..
if salary value in a particular record is 1500 i want to update it to 15000..
delete that code and just use:
update emp set sal = 13000 where sal = 1300
Whenever you can do the update with one single statement, you should do that instead of using a loop. You'll get a very huge performance gain that way; or, the other way round, updates in a loop cost you a lot of performance.
If you really really have to use a loop, of course you need a where condition to make sure you are only updating the record you really want to update. A possible way that always works (even if there is no unique key available) is to use the rowid pseudocolumn:
begin
for i in (select rowid, emp.* from emp)
loop
if i.sal=1300 then
update emp
set sal=13000
where rowid=i.rowid;
end if;
end loop;
end;
Another possibility would be using an explicit cursor and the "update ... where current of cursorname" syntax.
You need to put a constraint on your update statement.
What you have at the moment will loop through the results rows, and if it finds a row with salary equal to 1300, if then executest he following SQL:
update emp
set sal=13000;
Without the contraint this updates every row.
This code is updating all the records with salary 13000.
Instead i want to update records having salary 1300 to the value 13000.
for every record i am checking the sal value of that record..
if salary value in a particular record is 1500 i want to update it to 15000..
So what exactly do you want?
You want to update only 1,500 salary, you issue:
UPDATE emp
SET sal = 15000
WHERE sal = 1500;
You want to increase all salary ten times, you issue:
UPDATE emp
SET sal = sal * 10;
While some of these solutions are workable its not a one size fits all solution. I ran into a scenario where we had to set an xml/nvarchar(max) field to null on a table that has +50 M records. This is an excerpt of the code
begin
declare #rows int,
#y int = 2020,
#m int = 1;
set #rows = 1;
while (#rows > 0)
begin
update top (500) cr
set [xml] = null
from [dbo].[customer] cr with(index(ix_customer_reportdt))
where year([reportdt]) = #y
and month([reportdt]) = #m
and [xml] is not null;
set #rows = ##rowcount;
end
end
here's a quick solution that helps in removing the spaces (trimming) of a column data based on created date:
UPDATE table_Name SET column_name = LTRIM(RTRIM(column_name))
WHERE EXTEND(dateTime_column, YEAR TO DAY)='2020-01-31' ;