How to insert into multiple tables from one table through procedures? - oracle11g

There are 4 tables
Table1(Column11, Column12, Column13)
Table2(Column21, Column22)
Table3(Column31, Column32,column33)
Table4(Column21, Column22)
And the following Mapping Table:
Table5(Sourcetable,Source column ,Destination table ,Destination column)
How to insert data from Table1 as source table and destination table as Table2,table3,table,4, Through Procedures?
I am using oracle 11g. Please help to achieve this!

If I understand your question, this is what you are looking for:
CREATE OR REPLACE PROCEDURE cpy_table
AS
CURSOR targ_dest_relation IS
SELECT sourcetable, sourcecolumn, destinationtable, destinationcolumn FROM table5;
BEGIN
FOR rec IN targ_dest_relation loop
execute immediate 'insert into ' || rec.destinationtable || '(' || rec.destinationcolumn || ') select ' || rec.sourcecolumn || ' from ' || rec.sourcetable;
END loop;
END;
/
SQL Fiddle

Related

I'm having trouble writing a cursor/loop. I'm not sure why it's not working

My code is here. I keep getting errors for the select statement. I've already created a waitlist table and a sequence. I inserted values into waitlist, however; I had to get the sname from the students table since waitlist does not have sname in the table. I'm trying to display RankingSid, Snum, sname, time(such as 1 pm or 2 pm).
create or replace procedure getWaiting(
p_callnum waitlist.callnum%type) as
cursor cwaiting is
select RankingSid, waitlist.snum, students.sname, to_char(time, 'hh AM')time
from waitlist, students
where p_callnum=callnum
and waitlist.snum=students.snum;
begin
For EachStudent in cwaiting loop
insert into TestTable values (EachStudent.RankingSid, Eachstudent.snum, EachStudent.sname, EachStudent.time);
dbms_output.put_line(eachstudent.rankingsid || eachstudent.snum || eachstudent.sname, eachstudent.time);
end loop;
end;
/
There are a number of syntax errors in your code, the biggest being your insert statement you need to reference your cursor variable for the insert in the same way that you did for the dbms_output. I do not have your table definitions to test the code but the below should be pretty close to what you need.
create or replace procedure getWaiting(
p_callnum waitlist.callnum%type) as
cursor cwaiting is
select RankingSid, waitlist.snum, students.sname, to_char(time, 'hh AM')time
from waitlist, students
where p_callnum=callnum
and waitlist.snum=students.snum;
begin
For EachStudent in cwaiting loop
insert into TestTable values (EachStudent.RankingSid, Eachstudent.snum, EachStudent.sname, EachStudent.time);
dbms_output.put_line(eachstudent.rankingsid || eachstudent.snum || eachstudent.sname || eachstudent.time);
end loop;
end;
/
I did it another way and would like to know how to change it..insert table wasn't working the other way. I was wondering if i'd have to create instead of inserting
create or replace procedure getWaiting(
p_callnum waitlist.callnum%type) as
begin
For eachRec in (select waitlist.rankingsid, students.snum, students.sname, to_char(time, 'hh:mi:ss AM') RequestedTime
from students, waitlist
where p_callnum=callnum
and students.snum=waitlist.snum
order by rankingsid)
Loop
dbms_output.put_line('Rank Number '|| eachRec.rankingsid ||' Student Name ' ||eachRec.sname ||' Student Number ' || eachRec.snum ||' Wait List Date ' || eachRec.RequestedTime);
end Loop;
end;
/

How to delete duplicate rows from all of my oracle database tables, using PL/SQL?

A generic way to remove perfectly duplicated rows from all tables owned by a certain user.
Here's the stored procedure for it. Don't forget to replace 'YOUR_USERNAME_HERE' with your username.
CREATE OR REPLACE PROCEDURE DELETE_DUPLICATES_FROM_DB
IS
TABLE_COLUMNS VARCHAR2(10000);
DELETE_STATEMENT VARCHAR2(10000);
CURSOR ALL_MY_TABLES IS SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'YOUR_USERNAME_HERE';
BEGIN
FOR MY_TABLE IN ALL_MY_TABLES
LOOP
SELECT LISTAGG(COLUMN_NAME, ',') WITHIN GROUP (ORDER BY 1) INTO TABLE_COLUMNS FROM USER_TAB_COLUMNS WHERE TABLE_NAME = MY_TABLE.TABLE_NAME;
DELETE_STATEMENT := 'DELETE FROM ' || MY_TABLE.TABLE_NAME || ' WHERE ROWID NOT IN (SELECT MIN(ROWID) FROM ' || MY_TABLE.TABLE_NAME || ' GROUP BY ' || TABLE_COLUMNS || ');';
EXECUTE IMMEDIATE DELETE_STATEMENT;
DBMS_OUTPUT.PUT_LINE(DELETE_STATEMENT);--print the statements we run
END LOOP;
END;

Aliasing in Bulk Collect giving error of unimplemented feature

The problem statement: The user would specify a name based on which I have to pull names of two tables from a table and then extract values from those tables.I have created a pl/sql procedure for that and since the select query can return n number of rows I'm using Bulk Collect. I have created and object based on the fields I want to extract. Now the problem is that the columns are common in both the tables, so if I don't use alias I get ambiguous column error and if I use that I get the error of unimplemented feature.
here's my code:
create or replace type recon_obj_vib
is object (RECON_TABLE_KEY NUMBER(19)
,RECON_CHGLOGATTR_IDXLST VARCHAR2(1000 CHAR));
create or replace type recon_tab_vib
is table of recon_obj_vib;
create or replace PROCEDURE noMatchReport_proc(tableDesc IN VARCHAR2)
IS
l_recon_tab_vib recon_tab_vib := recon_tab_vib();
n Integer :=0;
out varchar2(2000);
tableName1 varchar2(25);
tableName2 varchar2(25);
tableDesc_without_space varchar2(25);
tableDesc_ra varchar2(25);
BEGIN
tableDesc_without_space:=Regexp_Replace(tableDesc,'\s');
tableDesc_ra:=UPPER('RA_' || tableDesc_without_space || ' %');
out:= 'Select recon_table_name from recon_tables where recon_table_desc = (:value) and rownum=1 and RECON_TABLE_name like (:userName)';
execute immediate out into tableName1 USING tableDesc,tableDesc_ra;
out:= 'Select recon_table_name from recon_tables where recon_table_desc = (:value) and rownum=1 and RECON_TABLE_name not like (:userName)';
execute immediate out into tableName2 USING tableDesc,tableDesc_ra;
out:='Select a.RECON_TABLE_KEY,a.RECON_CHGLOGATTR_IDXLST BULK COLLECT INTO l_recon_tab_vib from ' || tableName1 || ' a , ' || tableName2 || ' b where a.RE_KEY = b.RE_KEY and rownum=1';
execute immediate out into l_recon_tab_vib;
FOR i IN 1..l_recon_tab_vib.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE('RECON_TABLE_KEY '|| l_recon_tab_vib(i).RECON_TABLE_KEY ||' RECON_CHGLOGATTR_IDXLST ' || l_recon_tab_vib(i).RECON_CHGLOGATTR_IDXLST );
END LOOP;
END;
This part:
out:='Select a.RECON_TABLE_KEY,a.RECON_CHGLOGATTR_IDXLST BULK COLLECT INTO l_recon_tab_vib from ' || tableName1 || ' a , ' || tableName2 || ' b where a.RE_KEY = b.RE_KEY and rownum=1';
execute immediate out into l_recon_tab_vib;
Should be:
out:='Select a.RECON_TABLE_KEY,a.RECON_CHGLOGATTR_IDXLST from '
|| tableName1 || ' a , ' || tableName2
|| ' b where a.RE_KEY = b.RE_KEY and rownum=1';
execute immediate bulk collect into l_recon_tab_vib;
i.e. the BULK COLLECT INTO clause is part of the calling PL/SQL not part of the dynamic SQL.

Duplicate INSERT record procedure

I have problem with mu procedure which insert duplicate last record in table
example when I put INSERT..... 'AAA' I got to rows in table 'AAA' and 'AAA'
In place when I put DBMS()... in code I got tow records
I use trigger and sequence for column ID in HistoriaDismissDate but they are in good condition. I check if I dropped trigger and sequence and its the same situation
I also use viewDate but this view get mi ONE record not two
my code
CREATE OR REPLACE PROCEDURE ChangeDismissDate
IS
v_id VARCHAR2(11);
v_dateBhd DATE := TO_DATE('20491231','yyyymmdd');
v_dateDismiss DATE := TO_DATE('20491231','yyyymmdd');
v_login VARCHAR2(50);
last_id NUMBER :=0;
CURSOR cur IS
select EMP_NO, LOGIN, ODEJSCIE_BHD, ODEJSCIE_OLD FROM viewDate;
BEGIN
OPEN cur;
LOOP
FETCH cur INTO v_id,v_login,v_dateBhd,v_dateDismiss;
DBMS_OUTPUT.put_line(v_id || ' ' || v_login || ' ' || v_dateBhd || ' ' || v_dateDismiss);
UPDATE employee_tab SET DISMISS_DATE = v_dateBhd WHERE EMP_NO = v_id;
COMMIT;
INSERT INTO HistoriaDismissDate(CUSTOMER_ID,LOGIN, DATE_CHANGE, DATE_BHD, DATE_DISMISS)
VALUES(v_id,v_login, sysdate, v_dateBhd, v_dateDismiss);
COMMIT;
EXIT WHEN cur%NOTFOUND;
END LOOP;
CLOSE cur;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line (DBMS_UTILITY.format_error_stack);
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (DBMS_UTILITY.format_error_stack);
END;
/
2 tips on your original code:
1) cursor is a very old programming technic on PL/SQL. Prefer to use FOR ... LOOP construction. It's cleaner and less error-prone! See how it works:
CREATE OR REPLACE PROCEDURE ChangeDismissDate IS
BEGIN
for cur in (select EMP_NO, LOGIN, ODEJSCIE_BHD, ODEJSCIE_OLD FROM viewDate) loop
DBMS_OUTPUT.put_line(cur.EMP_NO || ' ' || cur.login || ' ' || cur.ODEJSCIE_BHD || ' ' || cur.ODEJSCIE_OLD);
UPDATE employee_tab
SET DISMISS_DATE = cur.ODEJSCIE_BHD
WHERE EMP_NO = cur.EMP_NO;
INSERT INTO HistoriaDismissDate
( CUSTOMER_ID,LOGIN, DATE_CHANGE, DATE_BHD, DATE_DISMISS )
VALUES
( cur.EMP_NO, cur.LOGIN, sysdate, cur.ODEJSCIE_BHD, cur.ODEJSCIE_OLD, );
end loop;
end;
/
2) Never, I mean never put a commit inside your procedure. The commit should be done on the caller block or on your client-side app. When you put a commit inside your procedure, you miss the chance to rollback after running it and other procedures could not call it if they want to control the transaction flow.

PL/SQL Inserting 1 row for each result in a select

I am writing a PL/SQL Procedure that performs a select based on input variables and then inserts a row for each result in the select. I am having trouble debugging what is wrong with my query due my newness to PL/SQL. I know this must be easy, but I am stuck here for some reason. Thanks for your help!
CREATE OR REPLACE PROCEDURE setup_name_map(ranking_id IN NUMBER, class_string IN VARCHAR2)
IS
BEGIN
FOR rec IN (SELECT NAME_ID FROM PRODUCT_NAMES WHERE NAME = class_string)
LOOP
EXECUTE IMMEDIATE 'INSERT INTO NAME_RANKING (NAME_ID, RANKING_ID) VALUES (' || rec.NAME_ID || ', ' || ranking_id || ')';
END LOOP;
END;
According to the Oracle Developer Compiler... 'NAME_ID' is an invalid identifier. I've tried putting it in quotes but no dice. It also complains that loop index variables 'REC' use is invalid. Any help is much appreciated.
There is no need for dynamic SQL here:
BEGIN
FOR rec IN (SELECT NAME_ID FROM PRODUCT_NAMES
WHERE NAME = class_string)
LOOP
INSERT INTO NAME_RANKING (NAME_ID, RANKING_ID)
VALUES (rec.NAME_ID, ranking_id);
END LOOP;
END;
Better still you can avoid a slow row-by-row cursor approach like this:
BEGIN
INSERT INTO NAME_RANKING (NAME_ID, RANKING_ID)
SELECT NAME_ID, ranking_id FROM PRODUCT_NAMES
WHERE NAME = class_string;
END;
If you really did need the dynamic SQL you should not be concatenating values into it, but using bind variables:
BEGIN
FOR rec IN (SELECT NAME_ID FROM PRODUCT_NAMES
WHERE NAME = class_string)
LOOP
EXECUTE IMMEDIATE 'INSERT INTO NAME_RANKING
(NAME_ID, RANKING_ID) VALUES (:b1, :b2)
USING rec.NAME_ID, ranking_id;
END LOOP;
END;

Resources