Oracle - Tree - PL/SQL - Copying data with mapping - oracle

I have following table structure
ID Name Parent_ID
1 abc 0
2 efg 1
3 hij 1
4 klm 2
5 nop 3
and so on....id is generated in a sequence
I want a PL/SQL to coy this same data in same table but id should be generated by seq and Parent_ID should be mapped accordingly...that means..after PL/SQL it should look like
ID Name Parent_ID
1 abc 0
2 efg 1
3 hij 1
4 klm 2
5 nop 3
6 abc 0
7 efg 6
8 hij 6
9 klm 7
10 nop 8
can any1 help me in this...thnx

So, here is your original data:
SQL> select * from t23
2 /
ID NAM PARENT_ID
---------- --- ----------
1 abc 0
2 efg 1
3 hij 1
4 klm 2
5 nop 3
SQL>
This procedure populates a PL/SQL collection with the extant rows. It loops through those rows, populating an associative array with a new ID which is indexed by the original ID. (Note the assignment uses the 11g syntax for getting a sequence value, rather than the traditional selecting from DUAL). The ID is then chnaged to the new value, and the PARENT_ID is updated with the value stored in the associative array. Lastly the new rows are inserted into the table using the bulk FORALL syntax,
SQL> declare
2 type num_lookup is table of pls_integer
3 index by pls_integer;
4 id_translate num_lookup;
5
6 type t23_nt is table of t23%rowtype;
7 new_rows t23_nt;
8 begin
9 select *
10 bulk collect into new_rows
11 from t23
12 order by id asc;
13
14 for i in new_rows.first()..new_rows.last()
15 loop
16 id_translate(new_rows(i).id) := s23.nextval;
17 new_rows(i).id := s23.currval;
18 if new_rows(i).parent_id != 0
19 then
20 new_rows(i).parent_id := id_translate(new_rows(i).parent_id);
21 end if;
22 end loop;
23
24 forall j in new_rows.first()..new_rows.last()
25 insert into t23 values new_rows(j);
26
27 end;
28 /
PL/SQL procedure successfully completed.
SQL>
And, lo!
SQL> select * from t23;
ID NAM PARENT_ID
---------- --- ----------
1 abc 0
2 efg 1
3 hij 1
4 klm 2
5 nop 3
6 abc 0
7 efg 6
8 hij 6
9 klm 7
10 nop 8
10 rows selected.
SQL>

Related

how to convert column value to multiple insert rown oracle cursor

I am trying to copy value from our old db to new db where there is a change in the table structure.
Below is the structure of the table
Table1
Table1ID, WheelCount, BlindCount, OtherCount
For eg values of table 1 is like below
Table1ID, 1,2,5
Table1 is now changed to TableNew with the below
TableNewID, DisableID , Quantity.
So the value should be
TableNewID1, 1,1 here 1= WheelCount from table1
TableNewID2, 2,2 here 2= BlindCount
TableNewID3, 3,5 here 5= OtherCount
how to write a cursor to transform table1 value to the new table tableNew structure.
Table1
Table1ID WheelCount BlindCount OtherCount
1 1 2 5
2 8 10 15
A master table defined to map disableid
DisableID Type
1 wheelCount
2 blindcount
3 otherCount
Expected structure
ID **Table1ID** **DISABLEID** QUANTITY
1 1 1 1
2 1 2 2
3 1 3 5
4 2 1 8
5 2 2 10
6 2 3 15
The simplest is a UNION ALL for each column you want to turn into a row.
insert into tablenew
select table1id,1,wheelcount from table1
union all
select table1id,2,blindcount from table1
union all
select table1id,3,othercount from table1
There are other, sleeker methods for avoiding multiple passes on the first table, in case it's huge.
This is how I understood it.
Current table contents:
SQL> SELECT * FROM table1;
TABLE1ID WHEELCOUNT BLINDCOUNT OTHERCOUNT
---------- ---------- ---------- ----------
1 1 2 5
2 8 10 15
Prepare new table:
SQL> CREATE TABLE tablenew
2 (
3 id NUMBER,
4 table1id NUMBER,
5 disableid NUMBER,
6 quantity NUMBER
7 );
Table created.
Sequence (will be used to populate tablenew.id column):
SQL> CREATE SEQUENCE seq_dis;
Sequence created.
Trigger (which actually populates tablenew.id):
SQL> CREATE OR REPLACE TRIGGER trg_bi_tn
2 BEFORE INSERT
3 ON tablenew
4 FOR EACH ROW
5 BEGIN
6 :new.id := seq_dis.NEXTVAL;
7 END;
8 /
Trigger created.
Copy data:
SQL> INSERT INTO tablenew (table1id, disableid, quantity)
2 SELECT table1id, 1 disableid, wheelcount AS quantity FROM table1
3 UNION ALL
4 SELECT table1id, 2 disableid, blindcount AS quantity FROM table1
5 UNION ALL
6 SELECT table1id, 3 disableid, othercount AS quantity FROM table1;
6 rows created.
Result:
SQL> SELECT *
2 FROM tablenew
3 ORDER BY table1id, disableid;
ID TABLE1ID DISABLEID QUANTITY
---------- ---------- ---------- ----------
1 1 1 1
3 1 2 2
5 1 3 5
2 2 1 8
4 2 2 10
6 2 3 15
6 rows selected.

Oracle - how to insert if not exists?

Example dB : https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=49af209811bce88aa67b42387f1bb5f6
I'd like to add insert this line
1002 9 1 UNKNOWN
Because of the line exists
1002 5 1 JIM
I was thinking about something like
select codeclient from STATS_CLIENT_TEST where CODEAXESTAT=5
and insert codeclient, 9,1,UNKNOWN.
but not sure how to do it? And simple query or a PL/SQL?
What's the best way to get it?
Thanks
Use an INSERT .. SELECT statement with a PARTITIONed outer join:
INSERT INTO stats_client_test (
codeclient, codeaxestat, codeelementstat, valeuraxestatistiqueclient
)
SELECT cc.codeclient,
s.codeaxestat,
s.codeelementstat,
'UNKNOWN'
FROM (SELECT DISTINCT codeclient FROM stats_client_test) cc
LEFT OUTER JOIN stats_client_test s
PARTITION BY (s.codeaxestat, s.codeelementstat)
ON (s.codeclient = cc.codeclient)
WHERE s.rowid IS NULL;
or a MERGE statement:
MERGE INTO stats_client_test dst
USING (
SELECT cc.codeclient,
s.codeaxestat,
s.codeelementstat,
s.ROWID AS rid
FROM (SELECT DISTINCT codeclient FROM stats_client_test) cc
LEFT OUTER JOIN stats_client_test s
PARTITION BY (s.codeaxestat, s.codeelementstat)
ON (s.codeclient = cc.codeclient)
) src
ON (dst.ROWID = src.rid)
WHEN NOT MATCHED THEN
INSERT (codeclient, codeaxestat, codeelementstat, valeuraxestatistiqueclient)
VALUES (src.codeclient, src.codeaxestat, src.codeelementstat, 'UNKNOWN');
db<>fiddle here
Here's one option: using the MINUS set operator, find missing codeclient values and then insert appropriate row(s).
Before:
SQL> select * From stats_client_Test order by codeaxestat, codeclient;
CODECLIENT CODEAXESTAT CODEELEMENTSTAT VALEURAXESTATISTIQUECLIENT
-------------------- ----------- --------------- ----------------------------------------
1000 5 1 JOHN
1001 5 1 ALICE
1002 5 1 JIM
1003 5 1 BOB
1000 9 1 MAN
1001 9 1 WOMAN
1002 9 1 unknown
1003 9 1 MAN
8 rows selected.
Query:
SQL> insert into stats_client_test
2 (codeclient, codeaxestat, codeelementstat, VALEURAXESTATISTIQUECLIENT)
3 select x.codeclient, 9, 1, 'unknown'
4 from (select codeclient from stats_client_Test
5 where codeaxestat = 5
6 minus
7 select codeclient from stats_client_Test
8 where codeaxestat = 9
9 ) x;
0 rows created.
After:
SQL> select * From stats_client_Test order by codeaxestat, codeclient;
CODECLIENT CODEAXESTAT CODEELEMENTSTAT VALEURAXESTATISTIQUECLIENT
-------------------- ----------- --------------- ----------------------------------------
1000 5 1 JOHN
1001 5 1 ALICE
1002 5 1 JIM
1003 5 1 BOB
1000 9 1 MAN
1001 9 1 WOMAN
1002 9 1 unknown --> here it is
1003 9 1 MAN
8 rows selected.
SQL>

Update one column of each row in a table [PL/SQL, unix scripting]

i have a table with 12 columns:
table1:
1
2
3
4
5
6
7
8
9
10
11
12
abc
1
000
aaa
zzz
2
234
OOO
00001
01
123
214
def
2
023
bbb
yyy
4
345
PPP
00002
02
133
224
ghi
3
011
ccc
xxx
6
456
QQQ
00003
03
143
234
jkl
4
112
ddd
www
8
567
RRR
00004
04
153
244
i would like to use 3rd column data in a loop and fetch 'best match' data from another table.
table2:
1
2
3
4
0
777
676
america
00
888
878
england
01
999
989
france
02
666
656
germany
3rd column data will be trimmed in the loop until a match in table2 is fetched.
first row:
iter 1: table1 row1 col3=000 -- no match in table
iter 2: table1 row1 col3=00 -- return england, replace table1 row1 col12=214 with 'england'
updated row: abc,1,000,aaa,zzz,2,234,OOO,00001,01,123,england
second row:
iter 1: table1 row2 col3=023 -- no match in table
iter 2: table1 row2 col3=02 -- return germany, replace table1 row1 col12=224 with 'germany'
updated row: def,2,023,bbb,yyy,4,345,PPP,00002,02,133,germany
What you will need to do is create a procedure, then within the procedure declare a cursor as well as a variable_c_row cursor_name%ROWTYPE.
Within the procedure, this will be the contents:
OPEN cursor_name
FETCH cursor_name INTO variable_c_row;
WHILE cursor_name%FOUND LOOP
-- Declare a number variable (i)
i := 0;
-- Declare a varchar variable (match)
match := variable_c_row.col3
WHILE length(match) > 0 LOOP OR l_countryname IS NULL
begin
-- Declare a yourrow%ROWTYPE variable (l_countryname)
SELECT col4 FROM table2 INTO l_countryname WHERE col1 = match;
UPDATE table1 SET col12 = l_countryname;
exception when no_data_found then null;
end;
i := i+1;
match := substr(variable_c_row.cow3, 0, length(match)-i);
END LOOP;
FETCH cursor_name INTO variable_c_row;
END LOOP;
CLOSE cursor_name;
Since the question had no DDL or DML, the most I can provide is a broad answer, which has not been tested.

How to flip values of two rows?

ID TYPE ORDER_INDEX CITY_ID
-----------------------------------
1 CAT 1 1
2 DOG 2 1
3 CAT 4 2
4 DOG 5 2
5 BEE 9 1
For each city I need to swap the order_index of cat and dog.
So city with ID 1 should have cat=2 and dog=1, city with ID 2 would have cat=5 and dog=4.
How can this be done with pure SQL?
Use an update:
UPDATE yourTable t1
SET ORDER_INDEX = (SELECT t2.ORDER_INDEX FROM yourTable t2
WHERE t2.CITY_ID = t1.CITY_ID AND
t2.TYPE IN ('CAT', 'DOG') AND
t2.TYPE <> T1.TYPE)
WHERE TYPE IN ('CAT', 'DOG');
The above update logic assumes that you wish to do the ORDER_INDEX swap between dog/cat pair records having the same CITY_ID.
Well, if you don't care about ID, then there's a simple option which does what you wanted:
Before:
SQL> select * from test order by id;
ID TYP ORDER_INDEX CITY_ID
---------- --- ----------- ----------
1 CAT 1 1
2 DOG 2 1
3 CAT 4 2
4 DOG 5 2
5 BEE 9 1
Update:
SQL> update test set
2 type = decode(type, 'DOG', 'CAT', 'DOG')
3 where type in ('CAT', 'DOG');
4 rows updated.
After; requirement was
city with ID 1 should have cat=2 and dog=1, city with ID 2 would have cat=5 and dog=4.
SQL> select * from test order by id;
ID TYP ORDER_INDEX CITY_ID
---------- --- ----------- ----------
1 DOG 1 1 --> city with ID = 1 has DOG = 1 ...
2 CAT 2 1 --> ... and CAT = 2
3 DOG 4 2 --> city with ID = 2 has DOG = 4 ...
4 CAT 5 2 --> ... and CAT = 5
5 BEE 9 1
SQL>

oracle update query [duplicate]

This question already has an answer here:
Closed 12 years ago.
Possible Duplicate:
Oracle Multiple update Query
I have a query
Select item_code,comp_code from item;
which returns
item_code, comp_code
912001 01
912001 04
912002 01
912002 02
912002 03
912003 01
and i have three values for comp_code for each item. suppose comp_1,comp_2,comp_3
now i want to update the table with each item code will have these three values. ie, there will be three entry for each item with comp_code value as comp_1,comp_2,comp_3 like below o/p
item_code, comp_code
912001 comp_1
912001 comp_2
912001 comp_3
912002 comp_1
912002 comp_2
912002 comp_3
912003 comp_1
912003 comp_2
912003 comp_3
How can write a single query which select and update these values
I'm not sure I quite follow what you want.. but to get from figure A to figure B, you could do the following.
Create a holding table with the new values
Drop the old table
Rename the holding table.
This of course does not take into account indexes, permissions, etc...
SQL> #so_test
SQL> DROP
2 TABLE SO_TEST;
Table dropped.
SQL>
SQL> CREATE
2 TABLE SO_TEST
3 (
4 ITEM_CODE NUMBER
5 , COMP_CODE VARCHAR2 (10)
6 );
Table created.
SQL>
SQL> INSERT
2 INTO
3 SO_TEST VALUES
4 (
5 912001
6 ,'01'
7 );
1 row created.
SQL>
SQL> INSERT
2 INTO
3 SO_TEST VALUES
4 (
5 912001
6 ,'04'
7 );
1 row created.
SQL>
SQL> INSERT
2 INTO
3 SO_TEST VALUES
4 (
5 912002
6 ,'01'
7 );
1 row created.
SQL>
SQL> INSERT
2 INTO
3 SO_TEST VALUES
4 (
5 912002
6 ,'02'
7 );
1 row created.
SQL>
SQL> INSERT
2 INTO
3 SO_TEST VALUES
4 (
5 912002
6 ,'03'
7 );
1 row created.
SQL>
SQL> INSERT
2 INTO
3 SO_TEST VALUES
4 (
5 912003
6 ,'01'
7 );
1 row created.
SQL>
SQL> CREATE
2 TABLE SO_TEST_NEW AS
3 SELECT
4 A.ITEM_CODE AS ITEM_CODE
5 , 'comp_'
6 || B.N AS COMP_CODE
7 FROM
8 (
9 SELECT
10 ITEM_CODE
11 FROM
12 SO_TEST
13 GROUP BY
14 ITEM_CODE
15 )
16 A
17 , (
18 SELECT
19 ROWNUM AS N
20 FROM
21 (
22 SELECT
23 1 X
24 FROM
25 DUAL
26 CONNECT BY LEVEL <= 3
27 )
28 )
29 B
30 ORDER BY
31 A.ITEM_CODE;
Table created.
SQL>
SQL> DROP
2 TABLE SO_TEST;
Table dropped.
SQL>
SQL> ALTER TABLE SO_TEST_NEW RENAME TO SO_TEST;
Table altered.
SQL>
SQL> SELECT
2 *
3 FROM
4 SO_TEST;
ITEM_CODE COMP_CODE
---------- ---------------------------------------------
912001 comp_1
912001 comp_2
912001 comp_3
912002 comp_1
912002 comp_3
912002 comp_2
912003 comp_1
912003 comp_3
912003 comp_2
9 rows selected.
SQL>

Resources