Home » SQL & PL/SQL » SQL & PL/SQL » PL/SQL for 3 different tables (Oracle 11.2.0.4)
PL/SQL for 3 different tables [message #597080] Mon, 30 September 2013 14:57 Go to next message
Ricky_1362002
Messages: 111
Registered: February 2009
Senior Member
I am a DBA but for some reason, I have been requested to write a PL/SQL procedure to get the following:

Below are the tables:


Table - CONFI				Table - DEPT				Table - PER_DEPT	
											
ID 	Name	Dept_ID			Dept_ID	Desc				Dept_ID	Level
1	Tom	100			100	abc				100	3
2	Rick	100			101	def				100	4
3	Mary	101			102	acd				100	5
4	Cathy	101								101	1
5	Sarah	102								101	2
										102	6
										102	7


Table CONFI has the records entered wrongly by someone, it should have different Dept_ID for different Names.
Table DEPT has some description
Table PER_DEPT has some levels assigned to each dept, multiple levels are assigned to the same dept, that is how it is.

All the IDs are sequentially generated, using confi_seq.nextval(for ID) and dept_seq.nextval(for dept_id)

Confi table is to be updated in such a way that it should have different dept_id for different names
For example, here dept_id 100 is repeated 2 more times, so the dept table must be added with 2 more new dept_id values
starting with the nextval i.e. 103 and 104
And in the Per-Dept table, these new values must be inserted, with the same levels as with 100

The new tables should look like this:

Table - CONFI				Table - DEPT				Table - PER_DEPT	
											
ID 	Name	Dept_ID			Dept_ID	Desc				Dept_ID	Level
1	Tom	100			100	abc				100	3
2	Rick	103			101	def				100	4
3	Mary	101			102	acd				100	5
4	Cathy	104			103	abc				101	1
5	Sarah	102			104	def				101	2
										102	6
										102	7
										103	3
										103	4
										103	5
										104	1
										104	2



I am trying to work on this but not really getting any good ideas as am a DBA and new to these PL/SQL Procedures, need your help please.

Thank you,
Rick
Re: PL/SQL for 3 different tables [message #597081 is a reply to message #597080] Mon, 30 September 2013 15:23 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
I must say that this problem looks more to me like a homework assignment as opposed to any sort of real world application.

>I am a DBA
really?

how can you be a DBA & not know PL/SQL basics?

what have you been doing the last three years?
Re: PL/SQL for 3 different tables [message #597082 is a reply to message #597081] Mon, 30 September 2013 15:29 Go to previous messageGo to next message
Ricky_1362002
Messages: 111
Registered: February 2009
Senior Member
Well, I am a DBA and sorry for saying that I am new to PL/SQL, I do know quite a bit of it, but this one looks complicated to me, coz I think this involves cursors and so on, It has been quite long that I had worked on creating the PL/SQl procedures. For me, it looks much of a developers work here, but as I have been requested, I am trying to help them around, and thought of asking some people over here for suggestions and help.

I understand that this does NOT really looks like a real world application, but it is, the application for the folks here is built in such a way, and I cannot argue with the application team here, instead I thought I would try to help them if I can. And so posted here for the help/suggestions.

[Updated on: Mon, 30 September 2013 15:33]

Report message to a moderator

Re: PL/SQL for 3 different tables [message #597083 is a reply to message #597080] Mon, 30 September 2013 15:33 Go to previous messageGo to next message
Lalit Kumar B
Messages: 3174
Registered: May 2013
Location: World Wide on the Web
Senior Member
Did you have a look at Merge statement. If you want to update one table at a time and also do the inserts, merge would suffice the requirement as plain SQL instead of using pl/sql. Any particular reason for choosing pl/sql over SQL, any bottleneck?

Regards,
Lalit
Re: PL/SQL for 3 different tables [message #597084 is a reply to message #597083] Mon, 30 September 2013 15:41 Go to previous messageGo to next message
Ricky_1362002
Messages: 111
Registered: February 2009
Senior Member
Not really Lalit, no restrictions here, Merge can also be used.

If you/someone could help me out with that Merge statement to get the desired results, it would be great.

Thank you,
Rick

[Updated on: Mon, 30 September 2013 15:48]

Report message to a moderator

Re: PL/SQL for 3 different tables [message #597086 is a reply to message #597084] Mon, 30 September 2013 15:52 Go to previous messageGo to next message
Lalit Kumar B
Messages: 3174
Registered: May 2013
Location: World Wide on the Web
Senior Member
Is the count of duplicate dept_id in confi table restricted to only 2, or could it be more?
Re: PL/SQL for 3 different tables [message #597087 is a reply to message #597086] Mon, 30 September 2013 15:56 Go to previous messageGo to next message
Ricky_1362002
Messages: 111
Registered: February 2009
Senior Member
Nope, some DEPT_IDs are repeated 5 times, 10 times and some even 400 times. We might want to take it as a variable.
To answer your question - NO, it is not restricted, it could be more than 2.

Thank you for the concern Lalit.

[Updated on: Mon, 30 September 2013 15:57]

Report message to a moderator

Re: PL/SQL for 3 different tables [message #597091 is a reply to message #597087] Mon, 30 September 2013 16:33 Go to previous messageGo to next message
Lalit Kumar B
Messages: 3174
Registered: May 2013
Location: World Wide on the Web
Senior Member
Alright then, it is much complex in plain SQL to do multiple updates. I call it to be multiple updates in your case since you want to update the duplicates with incremental sequence. A single update will set all the dept_id with a single value.

A hint for you to build a logic is -

1. Fetch the dept_ids from confi table which are duplicates.
2. Use it as a subquery to return only the records having duplicate dept_ids. Use analytic function, row_number to give rank to the duplicate dept_ids over partition by dept_id order by dept_id.
3. In a loop, update these dept_ids row by row and assign the next sequence value. It has to be row by row...hence slow.
4. Write and insert statement just after this update and insert the curr val (since value already incremented while it updated confi table) into the dept table.
5. Repeat the loop till there are no dupliactes.

This is what came across my mind right now. We can definitely improve it but only if you come up with your logic and code.

Regards,
Lalit
Re: PL/SQL for 3 different tables [message #597093 is a reply to message #597091] Mon, 30 September 2013 17:11 Go to previous messageGo to next message
Ricky_1362002
Messages: 111
Registered: February 2009
Senior Member
Thank you for your inputs Lalit. Let me give it a try now, will update here.

Thank You,
Rick.
Re: PL/SQL for 3 different tables [message #597098 is a reply to message #597093] Mon, 30 September 2013 18:06 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
1) What is being done to prevent similar bad data from getting into these tables in the future?
2) What PK/FK relationship exists on DEPT_ID between these 3 tables?
3) From where does DEPT.DESC value originate when new rows are INSERTed into DEPT table?
4) what is the criteria used to decide which row values remain unchanged & which rows get new values?
5) I saw many words explaining changes to PER_DEPT that I did not understand; especially the value for the LEVEL column
Re: PL/SQL for 3 different tables [message #597193 is a reply to message #597080] Tue, 01 October 2013 08:58 Go to previous messageGo to next message
Ricky_1362002
Messages: 111
Registered: February 2009
Senior Member
Quote:
1) What is being done to prevent similar bad data from getting into these tables in the future?

They are doing some changes at the application level, to make sure that the data inserted would be correct from now on.

Quote:
2) What PK/FK relationship exists on DEPT_ID between these 3 tables?

Dept_Id is the has an FK relation with both the other tables, and PK for the DEPT table.

Quote:
3) From where does DEPT.DESC value originate when new rows are INSERTed into DEPT table?

Well, they are the pre-defined values and they don't change.

Quote:
4) what is the criteria used to decide which row values remain unchanged & which rows get new values?

Sorry but I do not understand this question.


Quote:
5) I saw many words explaining changes to PER_DEPT that I did not understand; especially the value for the LEVEL column

Oh, let me try explaining that again.
For one Dept_id there are many levels assigned, in this case-for dept_id=100 levels 3,4,5 are assigned, and since 100 has been repeated in CONFI table I would like to replace the second time 100 with the next dept_id (from the nextval), which is 103.
Now, 103 is the new dept_id, so it should have some levels (same as 100), and levels 3,4,5 should be assigned.

Please let me know if I was able to answer your questions or if you have any other questions.
Thank you BlackSwan.

Lalit, according to your logic does it also take care of the PER_DEPT table? I think we should add a few more steps. Well, I am still trying to get the desired results but being unsuccessful. Let me know if you can help me further.

Thanks
Rick
Re: PL/SQL for 3 different tables [message #597218 is a reply to message #597193] Tue, 01 October 2013 12:16 Go to previous messageGo to next message
Ricky_1362002
Messages: 111
Registered: February 2009
Senior Member
Ofcourse I am glad of BlackSwans suggestions and your inputs.

I am still trying but not able to get the desired results, coz I am poor in PL/SQL.

Here is the Logic I am trying - I am just giving you the pseudo code for understanding:


create table dept_id_repeats(dept_id number(5), counts number(5))
as 
(select dept_id, count(*) as Counts
from CONFI
group by dept_id having count(*) > 1
order by dept_id)


The above will give us this table - dept_id_repeats:
Dept_id	Counts
100	2
101	2
102	1


create or replace procedure UPDATE_CONF
is
cursor c1 is select counts from dept_id_repeats;
begin
n number:=100
if n=100
if c1.counts>1

insert into dept (dept_id,desc)
values (dept_seq.nextval, (select desc from dept where dept_id=n));

insert into per_dept(dept_id,level)
values(dept_seq.currval, (select level from per_dept where dept_id=n) -- > these will be multiple values and I dont really know how I can insert them)

end if;
n=n+1;
end;  

end;  ----end procedure


I know there are LOT of mistakes, but please bare with me. I need your help.

Thank you,
Rick
Re: PL/SQL for 3 different tables [message #597224 is a reply to message #597218] Tue, 01 October 2013 13:57 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
Ricky_1362002 wrote on Tue, 01 October 2013 10:16
Ofcourse I am glad of BlackSwans suggestions and your inputs.

I am still trying but not able to get the desired results, coz I am poor in PL/SQL.

Here is the Logic I am trying - I am just giving you the pseudo code for understanding:


create table dept_id_repeats(dept_id number(5), counts number(5))
as 
(select dept_id, count(*) as Counts
from CONFI
group by dept_id having count(*) > 1
order by dept_id)


The above will give us this table - dept_id_repeats:
Dept_id	Counts
100	2
101	2
102	1





>having count(*) > 1
You need to file a bug report to get Oracle fixed so it stops producing incorrect results like below
>102 1
Re: PL/SQL for 3 different tables [message #597226 is a reply to message #597224] Tue, 01 October 2013 14:10 Go to previous messageGo to next message
Ricky_1362002
Messages: 111
Registered: February 2009
Senior Member
Sorry, my bad. It should be this:
Dept_id	Counts
100	2
101	2


Re: PL/SQL for 3 different tables [message #597232 is a reply to message #597226] Tue, 01 October 2013 17:23 Go to previous message
Ricky_1362002
Messages: 111
Registered: February 2009
Senior Member
Well, here is what I tried. Please correct me if I am wrong.

create or replace procedure UPDATE_CONFI_TABLE
IS
cursor c1 is
SELECT name,dept_id,
ROW_NUMBER( ) OVER (PARTITION BY
dept_id ORDER BY dept_id
NULLS LAST) SRLNO
FROM confi;
dept1_rec confi%rowtype;
cursor c2 is 
select * from dept;
dept2_rec dept%rowtype;
a number:=100
begin
open c1,c2;
loop
fetch c1 into dept1_rec;
fetch c2 into dept2_rec;
    loop
    if dept1_rec.dept_id=a and tid1_rec.srlno=2
    then
    
    insert into dept
    select dept_seq.nextval,dept2_rec.desc
    from dept where dept_id=&&a;

    update confi set dept_id=dept_seq.currval 
    where dept_id=&&a and dept1_rec.srlno=2;

    Insert INTO per_dept
    select dept_seq.currval,level
    from per_dept where dept_id=&&a;

    end if;
    end loop;
a=a+1;
end loop;
close c1,c2;
end;
/
Previous Topic: Regexp_SUBSTR on an array returning no value
Next Topic: Clob_Agg Order by
Goto Forum:
  


Current Time: Wed Apr 24 08:24:54 CDT 2024