Trigger to copy the same row into another table - sql

How do I get values in Table 1 to Table2; that would duplicate the row based on Table1's column (Orders)
Table1:
ID TICKETID USERNAME FIRSTNAME LASTNAME ORDERS STATUS
SEL00007 Hema1 Hema Sri 3 New
SEL00008 Romi1 Romi T 2 New
Table2:
ID TICKETID USERNAME FIRSTNAME LASTNAME ORDERS STATUS
SEL00007 Hema1 Hema Sri 3 New
SEL00007 Hema1 Hema Sri 3 New
SEL00007 Hema1 Hema Sri 3 New
SEL00008 Romi1 Romi T 2 New
SEL00008 Romi1 Romi T 2 New
This is what I was able to come up with after referring to lot of other posts
CREATE OR REPLACE TRIGGER Duplicate_Rows
AFTER INSERT OR UPDATE ON Table1
REFERENCING NEW AS New OLD AS Old
FOR EACH ROW
DECLARE N_Ord NUMBER;
BEGIN
N_Ord := (SELECT (Orders) from Table2);
INSERT INTO UserTable2 (TICKETID,username,firstName,lastName,Status)
SELECT :New.TICKETID,:New.username,:New.firstName,:New.lastName,:New.Status
FROM dual
CONNECT BY LEVEL <= N_Ord;
END Duplicate_Rows;
/
Please help!!

Close; no need to separately select orders into a variable; it'll fail anyway because table is mutating so trigger can't see it.
Trigger:
SQL> CREATE OR REPLACE TRIGGER trg_ai_t1 AFTER
2 INSERT ON table1
3 FOR EACH ROW
4 BEGIN
5 INSERT INTO table2(
6 id,
7 ticketid,
8 username,
9 firstname,
10 lastname,
11 orders,
12 status
13 )
14 SELECT :new.id,
15 :new.ticketid,
16 :new.username,
17 :new.firstname,
18 :new.lastname,
19 :new.orders,
20 :new.status
21 FROM dual CONNECT BY
22 level <= :new.orders;
23
24 END;
25 /
Trigger created.
Insert into table1:
SQL> INSERT INTO table1(
2 id,
3 ticketid,
4 username,
5 firstname,
6 lastname,
7 orders,
8 status
9 )VALUES(
10 'SEL00007',
11 NULL,
12 'Hema1',
13 'Hema',
14 'Sri',
15 3,
16 'New'
17 );
1 row created.
Result:
SQL> SELECT *
2 FROM table1;
ID TICKETID USERNAME FIRST LASTN ORDERS STATU
---------- ---------- ---------- ----- ----- ---------- -----
SEL00007 Hema1 Hema Sri 3 New
SQL> SELECT *
2 FROM table2;
ID TICKETID USERNAME FIRST LASTN ORDERS STATU
---------- ---------- ---------- ----- ----- ---------- -----
SEL00007 Hema1 Hema Sri 3 New
SEL00007 Hema1 Hema Sri 3 New
SEL00007 Hema1 Hema Sri 3 New
SQL>

Related

how to write a trigger that checks if a value is already in the table?

I'd like to write trigger which checks if the product already exists in the given pallet and if it does, instead of adding a new row, just add the value to the old row
I have table:
ID(pk)
product_ID(fk)
number of product
1
15
14
And for exaple if i want add new row something like that (id: 2, product_id: 15, number of product: 13) I would like to get something like this:
ID(pk)
product_ID(fk)
number of product
1
15
27
Not like this:
ID(pk)
product_ID(fk)
number of product
1
15
14
2
15
13
I use orlace
Add row to table means insert. If you add unique index on both columns Id and product_id, after then while try to insert existing values the exception dup_val_on_index should happened. And if you insert and on insert gets dup_val_on_index exception you can overwrite it by update statement, no need to do trigger , all can be done on insert statement in exception statement
The way you put it, I agree with what Alex commented - a merge instead of separate insert and/or update. I'd further suggest you to create a procedure which will be used to insert rows into the table. Why? It is simpler to call the procedure than to write the same (long?) merge all over again.
Here's an example:
SQL> create table test
2 (id number constraint pk_test primary key,
3 product_id number,
4 number_prod number
5 );
Table created.
SQL> create or replace procedure p_ins_test
2 (par_id in test.id%type,
3 par_product_id in test.product_id%type,
4 par_number_prod in test.number_prod%type
5 )
6 is
7 begin
8 merge into test t
9 using (select par_id as id,
10 par_product_id as product_id,
11 par_number_prod as number_prod
12 from dual
13 ) x
14 on (x.product_id = t.product_id)
15 when matched then update set
16 t.number_prod = t.number_prod + x.number_prod
17 when not matched then insert (id, product_id, number_prod)
18 values (x.id, x.product_id, x.number_prod);
19 end;
20 /
Procedure created.
Testing:
SQL> exec p_ins_test(1, 15, 14);
PL/SQL procedure successfully completed.
SQL> select * from test;
ID PRODUCT_ID NUMBER_PROD
---------- ---------- -----------
1 15 14
SQL> exec p_ins_test(2, 15, 13);
PL/SQL procedure successfully completed.
SQL> select * from test;
ID PRODUCT_ID NUMBER_PROD
---------- ---------- -----------
1 15 27
SQL> exec p_ins_test(3, 99, 10);
PL/SQL procedure successfully completed.
SQL> select * from test;
ID PRODUCT_ID NUMBER_PROD
---------- ---------- -----------
1 15 27
3 99 10
SQL>

ORACLE SQL : IF EXISTS UPDATE ELSE INSERT

Lets say :
i have data on OracleDb like what i mentioned above.
TRANSFERNUMBER | VALUE1 | VALUE2
2250 | 1000 | 2000
2251 | 1000 | 3000
My main purpose is when add some data on table if data exists it should update the data . if data not exists on the table it should insert new row on table . That is why i want to use if exists on my query .
However i can't handle the query . Also i can't write procedure because of some reasons on the table . Is anyone help me for writing this by using query on Oracle ?
MERGE is what we usually do. Here's an example:
Test table and sample data:
SQL> create table test (tn number, val1 number, val2 number);
Table created.
SQL> insert into test
2 select 2250, 1000, 2000 from dual union all
3 select 2251, 1000, 3000 from dual;
2 rows created.
SQL> select * From test order by tn;
TN VAL1 VAL2
---------- ---------- ----------
2250 1000 2000
2251 1000 3000
How to do it? using represents data you're going to insert or update:
SQL> merge into test t
2 using (select 2250 tn, 1 val1, 2 val2 from dual union all --> for update
3 select 3000 , 8 , 9 from dual --> for insert
4 ) x
5 on (t.tn = x.tn)
6 when matched then update set t.val1 = x.val1,
7 t.val2 = x.val2
8 when not matched then insert values (x.tn, x.val1, x.val2);
2 rows merged.
Result:
SQL> select * From test order by tn;
TN VAL1 VAL2
---------- ---------- ----------
2250 1 2 --> updated
2251 1000 3000
3000 8 9 --> inserted
SQL>

Cannot Set ON COMMIT refresh attribute for Materialized View with PIVOT clause

I am trying to create the following Materialized View but have gotten this error:
ORA-12054: cannot set the ON COMMIT refresh attribute for the materialized view
I'm using a complete refresh on commit because the table referenced in the view will only have a handful of commits a few times a month and the updates will only be for a few records. Our team has decided complete refresh on commit is the way to go.
Here is the DDL:
CREATE MATERIALIZED VIEW TBLEDW_UANDC_PIVOT
BUILD IMMEDIATE
REFRESH COMPLETE ON COMMIT
ENABLE QUERY REWRITE
AS
SELECT * FROM
(SELECT DISTINCT UC.MAC_CD, UC.GCN_INDEX, UC.GCN_CD, UC.PKG_SZ, UC.U_C_RATE, UC.U_C_AMT FROM
DMT.TBLEDW_UANDC UC)
PIVOT
(SUM(U_C_AMT) FOR (U_C_RATE) IN (10 AS UCA, 30 AS UCB, 50 AS UCC, 70 AS UCD, 90 AS UCE));
I can't figure out why this error is occurring, thank you for any insight!
Here is an example of the PIVOT not working and how to work around it with DECODE.
Full commentary around the example at my blog https://connor-mcdonald.com/2019/10/02/a-refreshing-look-at-pivot/
SQL> create table patient
2 ( region int,
3 office int,
4 patient int,
5 some_date date );
Table created.
SQL>
SQL> alter table patient add primary key ( region, office, patient );
Table altered.
SQL>
SQL> insert into patient values (1,1,1,sysdate);
1 row created.
SQL> insert into patient values (1,1,2,sysdate);
1 row created.
SQL> insert into patient values (1,1,3,sysdate);
1 row created.
SQL>
SQL> create table patient_attrib
2 ( region int,
3 office int,
4 patient int,
5 property varchar2(10),
6 val number);
Table created.
SQL>
SQL>
SQL> alter table patient_attrib add primary key ( region, office, patient, property );
Table altered.
SQL> alter table patient_attrib add constraint patient_attrib_fk
2 foreign key ( region,office,patient) references patient (region,office,patient);
Table altered.
SQL>
SQL> insert into patient_attrib values (1,1,2,'weight',60);
1 row created.
SQL> insert into patient_attrib values (1,1,2,'height',1);
1 row created.
SQL> insert into patient_attrib values (1,1,2,'bp',2);
1 row created.
SQL> insert into patient_attrib values (1,1,2,'heart',3);
1 row created.
SQL> insert into patient_attrib values (1,1,2,'chol',4);
1 row created.
SQL> insert into patient_attrib values (1,1,2,'fatpct',5);
1 row created.
SQL>
SQL> insert into patient_attrib values (1,1,3,'weight',61);
1 row created.
SQL> insert into patient_attrib values (1,1,3,'height',1.1);
1 row created.
SQL> insert into patient_attrib values (1,1,3,'bp',2.1);
1 row created.
SQL> insert into patient_attrib values (1,1,3,'heart',3.1);
1 row created.
SQL> insert into patient_attrib values (1,1,3,'chol',4.1);
1 row created.
SQL> insert into patient_attrib values (1,1,3,'fatpct',5.1);
1 row created.
SQL> select region, office, patient, some_date, weight_val, height_val, bp_val, heart_val, chol_val, fatpct_val
2 from
3 (
4 select h.*, hs.property, hs.val
5 from patient h,
6 patient_attrib hs
7 where h.region = hs.region
8 and h.office = hs.office
9 and h.patient = hs.patient
10 )
11 pivot ( sum(val) as val for ( property ) in ('weight' as weight, 'height' as height,
12 'bp' as bp, 'heart' as heart, 'chol' as chol, 'fatpct' as fatpct));
REGION OFFICE PATIENT SOME_DATE WEIGHT_VAL HEIGHT_VAL BP_VAL HEART_VAL CHOL_VAL FATPCT_VAL
---------- ---------- ---------- --------- ---------- ---------- ---------- ---------- ---------- ----------
1 1 2 02-OCT-19 60 1 2 3 4 5
1 1 3 02-OCT-19 61 1.1 2.1 3.1 4.1 5.1
SQL> create materialized view log on patient
2 with sequence, rowid (region,office,patient,some_date) including new values
3 /
Materialized view log created.
SQL>
SQL> create materialized view log on patient_attrib
2 with sequence, rowid (region,office,patient,property, val) including new values
3 /
Materialized view log created.
SQL> create materialized view MV
2 refresh fast
3 -- on commit
4 as
5 select region, office, patient, some_date, weight_val, height_val, bp_val, heart_val, chol_Val, fatpct_val
6 from
7 (
8 select h.*, hs.property, hs.val
9 from patient h,
10 patient_attrib hs
11 where h.region = hs.region
12 and h.office = hs.office
13 and h.patient = hs.patient
14 )
15 pivot ( sum(val) as val for ( property ) in ('weight' as weight, 'height' as height,
16 'bp' as bp, 'heart' as heart, 'chol' as chol, 'fatpct' as fatpct));
create materialized view MV
*
ERROR at line 1:
ORA-12015: cannot create a fast refresh materialized view from a complex query
SQL> select h.region, h.office, h.patient, h.some_date,
2 sum(decode(hs.property, 'weight', hs.val, 0)) weight_val,
3 sum(decode(hs.property, 'height', hs.val, 0)) height_val,
4 sum(decode(hs.property, 'bp', hs.val, 0)) bp_val,
5 sum(decode(hs.property, 'heart', hs.val, 0)) heart_val,
6 sum(decode(hs.property, 'chol', hs.val, 0)) chol_Val,
7 sum(decode(hs.property, 'fatpct', hs.val, 0)) fatpct_val
8 from patient h,
9 patient_attrib hs
10 where h.region = hs.region
11 and h.office = hs.office
12 and h.patient = hs.patient
13 group by h.region, h.office, h.patient, h.some_date;
REGION OFFICE PATIENT SOME_DATE WEIGHT_VAL HEIGHT_VAL BP_VAL HEART_VAL CHOL_VAL FATPCT_VAL
---------- ---------- ---------- --------- ---------- ---------- ---------- ---------- ---------- ----------
1 1 2 02-OCT-19 60 1 2 3 4 5
1 1 3 02-OCT-19 61 1.1 2.1 3.1 4.1 5.1
2 rows selected.
SQL> create materialized view MV
2 refresh fast
3 on commit
4 as
5 select h.region, h.office, h.patient, h.some_date,
6 count(*) c,
7 count(decode(hs.property, 'weight', hs.val, 0)) weight_cnt,
8 count(decode(hs.property, 'height', hs.val, 0)) height_cnt,
9 count(decode(hs.property, 'bp', hs.val, 0)) bp_cnt,
10 count(decode(hs.property, 'heart', hs.val, 0)) heart_cnt,
11 count(decode(hs.property, 'chol', hs.val, 0)) chol_cnt,
12 count(decode(hs.property, 'fatpct', hs.val, 0)) fatpct_cnt,
13 sum(decode(hs.property, 'weight', hs.val, 0)) weight_val,
14 sum(decode(hs.property, 'height', hs.val, 0)) height_val,
15 sum(decode(hs.property, 'bp', hs.val, 0)) bp_val,
16 sum(decode(hs.property, 'heart', hs.val, 0)) heart_val,
17 sum(decode(hs.property, 'chol', hs.val, 0)) chol_Val,
18 sum(decode(hs.property, 'fatpct', hs.val, 0)) fatpct_val
19 from patient h,
20 patient_attrib hs
21 where h.region = hs.region
22 and h.office = hs.office
23 and h.patient = hs.patient
24 group by h.region, h.office, h.patient, h.some_date;
Materialized view created.
Based on your comment see ON COMMIT Clause
Restrictions on Refreshing ON COMMIT
This clause is not supported for materialized views containing object types or Oracle-supplied types.
This clause is not supported for materialized views with remote tables.
If you specify this clause, then you cannot subsequently execute a distributed transaction on any master table of this materialized view.
For example, you cannot insert into the master by selecting from a
remote table. The ON DEMAND clause does not impose this restriction on
subsequent distributed transactions on master tables.
So, you cannot use it.
The ON COMMIT clause creates a fast refreshable mview. Materialized views with the PIVOT clause, cannot be fast refreshable.
I think you can tell this by yourself by using dbms_mview.explain_mview and checking the columns to see why it is not fast refreshable.

Insert columns into rows for each ID

I have two tables:
table 1:
ID name
--------- -----------
1 john
2 salma
3 tony
table2:
ID Tasks amount
--------- ----------- ----------
1 write 2
1 memorize 3
1 read 6
1 sing NULL
2 write 1
2 memorize NULL
2 read 5
2 sing NULL
3 write NULL
3 memorize 8
3 read 2
3 sing NULL
I want to insert new columns in table1 for each task mentioned in table2.
Table1:
ID name write memorize read sing
--------- ----------- -------- --------- ------- --------
1 john 2 3 6 NULL
2 salma 1 NULL 5 NULL
3 tony NULL 8 2 NULL
I can do the insert in Table1 for one ID at a time, but not for all of them. Thanks in advance!
First, I inserted the row values in a temporary table as columns using pivot:
select * into #Results
from
(
select ID,Tasks,amount
from #Table2
) tb2
pivot
(
max(amount)
for ID in ([1], [2], [3])
) as piv
Then, I did an inner join with Table1:
select * from Table1 tb1 inner join #Results r on r.ID =tb1.ID
Thanks #JamesL for the seggustion to use pivot!

Update statement using current value of the table

I want to update a row in a table by incrementing by one the integer value of one of the field..
The current doesn't work, why?
Update htmIndex SET numObs = numObs+1 where ...
Simple case, update one row:
SQL> select name
2 , age
3 from t23
4 where id = 2
5 /
NAME AGE
------------ ----------
MR KNOX 47
SQL> update t23
2 set age = age + 6
3 where id = 2
4 /
1 row updated.
SQL> select name
2 , age
3 from t23
4 where id = 2
5 /
NAME AGE
------------ ----------
MR KNOX 53
SQL>
Update a row when the column has a null value:
SQL> select name
2 , age
3 from t23
4 where id = 6
5 /
NAME AGE
------------ ----------
SALLY
SQL> update t23
2 set age=age+5
3 where id = 6
4 /
1 row updated.
SQL> select name
2 , age
3 from t23
4 where id = 6
5 /
NAME AGE
------------ ----------
SALLY
SQL> update t23
2 set age = nvl(age,0) +5
3 where id = 6
4 /
1 row updated.
SQL> select name
2 , age
3 from t23
4 where id = 6
5 /
NAME AGE
------------ ----------
SALLY 5
SQL>
Equally straightforward when updating multiple rows:
SQL> select name
2 , age
3 from t23
4 where age > 20
5 /
NAME AGE
------------ ----------
MR KNOX 53
FOX IN SOCKS 37
CAT 23
LORAX 443
SQL> update t23
2 set age = age + 1
3 where age > 20
4 /
4 rows updated.
SQL> select name
2 , age
3 from t23
4 where age > 20
5 /
NAME AGE
------------ ----------
MR KNOX 54
FOX IN SOCKS 38
CAT 24
LORAX 444
SQL>
It should work. However if the current column value is null then + 1 will return null.
try: Update htmIndex SET numObs = nvl(numObs,0)+1 where ...