How to store and retrieve data from temp table - oracle

I am new to PL-SQL. Please can someone help me on wrapping the below.
I need to:
Copy contents of table A and store in global temp table
Do an update on Table A & other tasks
Revert contents of Table A from global temp table
Delete temp table
ANy help is much appreciated.

Here you are:
Sample tables:
SQL> create table test as select * from dept;
Table created.
SQL> create global temporary table gtt_test as
2 select * from test where 1 = 2;
Table created.
SQL> select * from test;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
1 Dept 1 NY
2 Dept 2 London
6 rows selected.
SQL> select * from gtt_test;
no rows selected
Anonymous PL/SQL block which does what you asked:
SQL> begin
2 -- copy contents ...
3 insert into gtt_test select * from test;
4
5 -- update A
6 update test set loc = 'blabla';
7 delete from test where deptno = 20;
8
9 -- revert
10 delete from test;
11 insert into test select * from gtt_test;
12
13 -- delete temp
14 delete from gtt_test;
15 end;
16 /
PL/SQL procedure successfully completed.
At the end, no changes whatsoever:
SQL> select * from test;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
1 Dept 1 NY
2 Dept 2 London
6 rows selected.
SQL> select * from gtt_test;
no rows selected
SQL>
[EDIT]
Query you posted as a comment isn't correct; dynamic SQL must be enclosed into single quotes, it must not be terminated by a semi-colon while all other statements must. Fixed, it should be
BEGIN
EXECUTE IMMEDIATE 'create table camel_route_temp as '
|| ' select * from acquire.CAMEL_ROUTE_PROCESS';
DBMS_OUTPUT.put_line ('Temp table created');
--update A
UPDATE acquire.camel_route_process
SET acquire = 'DISABLED',
assure = 'DISABLED',
validation = 'DISABLED',
report = 'DISABLED',
notification = 'DISABLED';
COMMIT;
DBMS_OUTPUT.put_line ('Aquire components disabled');
END;
/

Related

Create a PL/SQL block to insert a new record into the Department table. Fetch the maximum department id from the Department table and add 10 to it;

Create a PL/SQL block to insert a new record into the Department table. Fetch the maximum department id from the Department table and add 10 to it
I can't see images, but - here's how I understood your homework:
Current table contents:
SQL> select * from dept;
DEPTNO DNAME LOC
---------- -------------------- --------------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
Procedure:
SQL> create or replace procedure p_ins_dept (par_dname in varchar2, par_loc in varchar2) is
2 l_deptno number;
3 begin
4 select max(deptno)
5 into l_deptno
6 from dept;
7
8 insert into dept (deptno, dname, loc)
9 values (nvl(l_deptno, 0) + 10, par_dname, par_loc);
10 end;
11 /
Procedure created.
Testing:
SQL> exec p_ins_dept ('Test', 'Zagreb');
PL/SQL procedure successfully completed.
SQL> select * from dept;
DEPTNO DNAME LOC
---------- -------------------- --------------------
50 Test Zagreb --> here it is
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL>
Note that such an approach is likely to fail in a multi-user environment where
two (or more) users simultaneously call the procedure,
fetch MAX department number value
add 10 to it
insert a row
which fails for the 2nd (and other) user because primary key is violated because of the 1st user - who successfully inserted the row
But OK; for a simple homework question, I guess you don't care much about such things.

How to execute trigger on delete or update on specific column happen in oracle?

I want to write the trigger that copies the old data into new table whenever the delete or update is happen.
So I have two tables tableA and tableB
tableA has following attributes: rollno, name, and status
tableB has following attributes: rollno, name
So, first whenever the delete operation is made on tableA I want to copy the old values to the tableB or second Whenever the value of the status attribute on tableA changes to specific value say 'C' then also I have to copy the old values.
I had written trigger that will copy the old values into tableB from tableA whenever delete or update is performed but the trigger is also executing for any update on the tableA.
Here is my trigger code
create or replace trigger my_trigger
before delete or update
on tableA
for each row
begin
insert into tableB values(:OLD.rollno,:OLD.name);
end;
So how to execute trigger if the status attribute is updated?
I can check by using if statement in trigger that if the :NEW value is 'c' then execute the trigger but I also want to execute the trigger for delete statement also how can I do this?
I think I can use two triggers one for delete and one for update and inside update trigger i can check my condition but can I do this in one trigger only in oracle?
Yes, IF can help.
Here's an example based on Scott's schema; have a look.
This is a log table:
SQL> create table deptb as select * From dept where 1 = 2;
Table created.
Trigger:
SQL> create or replace trigger trg_bdu_dept
2 before delete or update on dept
3 for each row
4 begin
5 if deleting then
6 insert into deptb values (:old.deptno, :old.dname, :old.loc);
7 elsif updating and :old.loc = 'NEW YORK' then
8 insert into deptb values (:old.deptno, :old.dname, :old.loc);
9 end if;
10 end;
11 /
Trigger created.
SQL>
Testing:
SQL> select * from dept;
DEPTNO DNAME LOC
---------- -------------------- --------------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL> delete from dept where deptno = 40;
1 row deleted.
SQL> update dept set loc = 'NY' where loc = 'NEW YORK';
1 row updated.
SQL> update dept set loc = 'dallas' where loc = 'DALLAS';
1 row updated.
SQL> select * from deptb;
DEPTNO DNAME LOC
---------- -------------------- --------------------
40 OPERATIONS BOSTON
10 ACCOUNTING NEW YORK
SQL> select * from dept;
DEPTNO DNAME LOC
---------- -------------------- --------------------
10 ACCOUNTING NY
20 RESEARCH dallas
30 SALES CHICAGO
SQL>
You can do this as following:
create or replace trigger my_trigger
before delete or update of status
on tableA
for each row
WHEN (NEW.status= 'C' OR NEW.status IS NULL)
begin
insert into tableB values(:OLD.rollno,:OLD.name);
end;
Only look for updates of column status with update of status. And then only execute the trigger when the new column value matches some condition WHEN (NEW.status= 'C' OR NEW.status IS NULL) checking for your value or null (in the delete case).

Procedure with exceptions

I have try to create procedure for updating row in table 'Departments'. I have to check if department name is unique. If is not unique it has to be stored in new table 'ERROR_DEPART'. I have tried to do that with exception but I fail to execute code.
CREATE PROCEDURE UPD_DEPARTMENT IS
v_depid department.department_id%TYPE;
v_depn department.department_name%TYPE;
v_lid department.location_id%TYPE;
v_phn employees.phone_number%TYPE;
BEGIN
select distinct departments.department_name, locations.location_id, employees.phone_number
into v_depn, v_lid, v_phn
from departments
inner join locations
on departments.location_id = locations.location_id
inner join employees
on departments.manager_id = employees.employee_id
END;
I'd suggest a unique index on department name column. Doing so, Oracle won't let you update any department name so that it would make a duplicate.
Here's an example.
First, test case, based on Scott's DEPT table:
SQL> create table depart as select * From dept;
Table created.
SQL> create unique index ui1_dept on depart (dname);
Index created.
SQL> create table error_depart as select * From depart where 1 = 2;
Table created.
SQL>
The procedure - in the exception handler section - inserts a row into the ERROR_DEPART table if uniqueness is violated.
SQL> create or replace procedure p_upd_dept (par_deptno in number, par_dname in varchar2)
2 is
3 begin
4 update depart d set
5 d.dname = par_dname
6 where d.deptno = par_deptno;
7
8 exception
9 when dup_val_on_index then
10 insert into error_Depart(deptno, dname) values (par_Deptno, par_dname);
11 end;
12 /
Procedure created.
SQL>
Testing: First, what we have now?
SQL> select * From depart;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL> begin
2 p_upd_dept(10, 'SALES'); --> a duplicate
3 p_upd_dept(20, 'new dept'); --> not a duplicate
4 end;
5 /
PL/SQL procedure successfully completed.
SQL> select * from depart;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 new dept DALLAS --> not a duplicate - updated
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL> select * From error_depart;
DEPTNO DNAME LOC
---------- -------------- -------------
10 SALES --> duplicate
SQL>

What is the Oracle equivalent of TG_OP and TG_NAME in Postgres?

I want to create a trigger that just inserts the name of the modified table and the operation performed on it. Kind of like:
BEGIN
INSERT INTO audit_table VALUES(user,tg_name,tg_op);
END;
However I can't find what's the equivalent in Oracle to tg_name and tg_op from Postgres.
Huh, there's nothing that simple in Oracle, as far as I can tell (but I admit - I may be very wrong and someone might know better). Anyway, until that better answer comes, here's a little bit of coding; see if it helps.
I'm creating a test table and a log table (though, I'm not sure how good your log table actually is; you don't know when something was done etc. so - I took some freedom to add at least the DATE column).
SQL> create table test as select * From dept;
Table created.
SQL> create table test_log
2 (username varchar2(30),
3 c_date date,
4 table_name varchar2(30),
5 action varchar2(1));
Table created.
A trigger: unfortunately, I don't know whether there's a built-in function which returns name of an object (a table, in our case) you're doing something with, so I'm querying USER_OBJECTS.
SQL> create or replace trigger trg_test_log
2 after insert or update or delete on test
3 for each row
4 declare
5 l_table_name varchar2(30);
6 l_action varchar2(1);
7 begin
8 select object_name
9 into l_table_name
10 from user_objects
11 where object_id = dbms_rowid.rowid_object(nvl(:new.rowid, :old.rowid));
12
13 if inserting then
14 l_action := 'I';
15 elsif updating then
16 l_action := 'U';
17 elsif deleting then
18 l_action := 'D';
19 end if;
20
21 insert into test_log (username, c_date, table_name, action)
22 values (user, sysdate, l_table_name, l_action);
23 end;
24 /
Trigger created.
And ... action!
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
SQL> select * From test;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL> delete from test where deptno = 40;
1 row deleted.
SQL> update test set loc = 'CROATIA' where deptno = 10;
1 row updated.
SQL> insert into test (deptno, dname, loc) values (99, 'STACK', 'OVERFLOW');
1 row created.
SQL> select * From test;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING CROATIA
20 RESEARCH DALLAS
30 SALES CHICAGO
99 STACK OVERFLOW
SQL> select * From test_log;
USERNAME C_DATE TABLE_NAME A
------------------------------ ------------------- ------------------------------ -
SCOTT 23.09.2018 08:44:17 TEST D
SCOTT 23.09.2018 08:44:17 TEST U
SCOTT 23.09.2018 08:44:17 TEST I
SQL>
There is no point in having special attribute for table_name and operation in DML trigger.
DML trigger can be created only on ONE table so you can hardcode its name in trigger itself.
Conditional predicates INSERTING, DELETING, and UPDATING can be used to derive operation name.
If, howevere, you want to create schema level trigger then you can use predefined attributes ora_*.
create table audit_table
(
user_name varchar2(30),
table_name varchar2(30),
action varchar2(30)
);
create or replace trigger schema_trigger
before create or alter
on schema
begin
insert into audit_table
(user_name, table_name, action)
values
(ora_login_user, ora_dict_obj_name, ora_sysevent);
end schema_trigger;
/
PL/SQL Triggers

Change detection capture in Oracle DB tables

I wanted to if it is possible to detect changes in Oracle DB table for each column and its value and capture the change is a separate temporary table ?
Yes; people usually do that using triggers.
Here's a simple example:
SQL> create table dept_log
2 (deptno number,
3 dname varchar2(20),
4 loc varchar2(20),
5 when date
6 );
Table created.
SQL>
SQL> create or replace trigger trg_bu_dept
2 before update on dept
3 for each row
4 begin
5 if :new.dname <> :old.dname or
6 :new.loc <> :old.loc
7 then
8 insert into dept_log (deptno, dname, loc, when)
9 values (:new.deptno, :old.dname, :old.loc, sysdate);
10 end if;
11 end;
12 /
Trigger created.
SQL> select * from dept;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL> update dept set loc = 'LONDON' where deptno = 40;
1 row updated.
SQL> select * From dept_log;
DEPTNO DNAME LOC WHEN
---------- -------------------- -------------------- -------------------
40 OPERATIONS BOSTON 11.04.2018 22:00:23
SQL>

Resources