Need bulk update when condition doesn't matches - oracle

declare
type employee_t is table of employee%rowtype index by pls_integer;
l_employee_data employee_t;
begin
select *
bulk collect into l_employee_data from employee;
forall indx in 1 .. l_employee_data.count
update roster r
set r.job = l_employee_data(indx).job,
r.position = l_employee_data(indx).position,
r.organisation = l_employee_data(indx).organisation
where r.employee_code = l_employee_data(indx).employee_code;
commit;
end;
In the above example, query updates all the data where it matches employee code with idx value. This is fine. My requirement here is, is it possible to update also, the other rows which doesn't matches employee code with idx value? if yes, then please let me know.

Update with what, if employee code doesn't match? If there's no match, then there's no match. You could update those columns with some value, but the question is which.
Besides, instead of what you used, consider a single MERGE statement:
merge into roster r
using employee e
on (e.employee_code = r.employee_code)
when matched then update set
r.job = e.job,
r.position = e.position,
r.organisation = e.organisation;

Related

I'm trying to update 2 fields in multiple tables in my database using a trigger after inserting a new row

i just created the trigger
here is the code:
CREATE OR REPLACE TRIGGER tr_update_solde_nbreserv
AFTER INSERT ON reservation
FOR EACH ROW
BEGIN
UPDATE CLIENTS
SET CLIENTS.NB_RESERV = NB_RESERV+1 , CLIENTS.SOLDE = SOLDE+1
FROM dbo.clients as c
INNER JOIN dbo.reservation as r
ON c.numc = r.numc
WHERE r.numr = :new.numr;
BEGIN
SELECT fillHist_station FROM DUAL;
END;
end tr_update_solde_nbreserv;
i'm getting these 2 errors:
Error(1,9): PL/SQL: SQL Statement ignored
Error(3,9): PL/SQL: ORA-00933: SQL command not properly ended
how can i fix them
There are several issues with your trigger code.
1) The purpose of this part of the code is unclear :
BEGIN
SELECT fillHist_station FROM DUAL;
END;
fillHist_station is not declared, hence this code would raise an invalid identifier error.
2) The syntax of the UPDATE query is invalid. Also, your intend is to select from the table that the trigger fired on, which is not allowed in Oracle. From looking at your code, it looks like you don't actually need to query RESERVATION to achieve your goal. As a row was just inserted in RESERVATION, you already know the corresponding client number.
3) You miss a / at the end
Here is an updated version of your code, that you can play around with in this db fiddle (you did not provide the structure of your tables so I just created the coulmns that are referenced in the query) :
CREATE OR REPLACE TRIGGER tr_update_solde_nbreserv
AFTER INSERT ON RESERVATION
FOR EACH ROW
BEGIN
UPDATE CLIENTS
SET NB_RESERV = NB_RESERV+1 , SOLDE = SOLDE+1
WHERE numc = :new.numc;
END tr_update_solde_nbreserv;
/
update CLIENTS
SET CLIENTS.NB_RESERV = NB_RESERV+1 , CLIENTS.SOLDE = SOLDE+1
FROM dbo.clients as c
inner join dbo.reservation as r
on c.numc = r.numc
where r.numr = :new.numr;
update with inner join is not supported in Oracle database in this way. furthermore dbo.clients and dbo.reservations look like Sql Server tables rather then oracle.
I believe that you are looking for something like this, but I am not sure about the relations. You may need to fix the query.
UPDATE
(
SELECT clients.nb_reserv, r.nb_reserv as r_nb_reserv, clients.solde, r.solde as r_solde
FROM clients
inner join reservation as r
on c.numc = r.numc
where r.numr = :new.numr
) t
SET CLIENTS.NB_RESERV = r_nb_reserv + 1, clients.solde = r_solde+1;
Simpler approach
UPDATE clients SET NB_RESERV = (SELECT nb_reserv +1
FROM reservations
WHERE c.numc = r.numc and r.numr = :new.numr),
SOLDE = (SELECT SOLDE +1
FROM reservations
WHERE c.numc = r.numc and r.numr = :new.numr)
WHERE EXISTS (SELECT 1 FROM reservations
WHERE c.numc = r.numc and r.numr = :new.numr);

Cursor loop update Table by many values

DECLARE
CURSOR contacts
IS
SELECT SUM (budget) AS budget
FROM et_bp_gl_account a, et_bp_fact f
WHERE f.gl_account_id = a.gl_account_id
AND total_flag = 0
GROUP BY month_id, org_unit_id;
BEGIN
FOR r IN contacts
LOOP
UPDATE et_bp_fact
SET budget = r.budget
WHERE gl_account_id IN (SELECT total_element
FROM et_bp_gl_account g, et_bp_fact f
WHERE f.gl_account_id = g.gl_account_id);
END LOOP;
END;
I want to update the table ET_BP_FACT by many values example(25,50,75)
returned from Cursor but when i execute the table updated by (25,25,25)
I think there an issue in the loop
That's because the UPDATE's WHERE clause doesn't "reference" cursor's values. Something like this:
DECLARE
CURSOR contacts
IS
SELECT month_id, org_unit_id, --> include additional columns here ...
SUM (budget) AS budget
FROM et_bp_gl_account a, et_bp_fact f
WHERE f.gl_account_id = a.gl_account_id
AND total_flag = 0
GROUP BY month_id, org_unit_id;
BEGIN
FOR r IN contacts
LOOP
UPDATE et_bp_fact
SET budget = r.budget
WHERE gl_account_id IN
(SELECT total_element
FROM et_bp_gl_account g, et_bp_fact f
WHERE f.gl_account_id = g.gl_account_id
--
AND f.org_unit_id = r.org_unit_id --> ... and reference them here ...
AND g.month_id = r.month_id);
--> ... or, possibly, here
END LOOP;
END;
I'd suggest you to always precede column names with table aliases, because - looking at your code, there's no way to guess which table(s) MONTH_ID and ORG_UNIT_ID belong to, so my code might (or might not) work, but I hope you got the general idea.

Insert the record in one table from another table with some criteria in oracle

I need to insert the record into one table from another table which is exact replica of other table ,condition for putting this as when a same record (for certain condition match) is coming from another table it will update the existing record and when a brand new record come it will insert the record.
I have written the query for this as below please correct me if possible.
INSERT INTO TEMP1 (B,C,D,PROVIDER_ID,NATIONAL_PROVIDER_IDENTIFIER,TAXONIMY_CODE,F,G,H)
SELECT W.B,W.C,W.D,W.PROVIDER_ID,W.NATIONAL_PROVIDER_IDENTIFIER,W.TAXONIMY_CODE,W.F,W.G,W.H
FROM TEMP2 W LEFT JOIN TEMP1 A ON( A.provider_id = W.provider_id
AND A.NATIONAL_PROVIDER_IDENTIFIER = W.NATIONAL_PROVIDER_IDENTIFIER
AND A.TAXONOMY_CODE = W.TAXONOMY_CODE)
WHERE W.SOURCE_ID = 'COSMOS'
It's still a bit unclear to me, but it does sound like you want to be using a MERGE statement.
If so, your statement would look something like this (hoping I understood your data model)
MERGE INTO TEMP1 a
USING (
SELECT B,C,D,PROVIDER_ID,NATIONAL_PROVIDER_IDENTIFIER,TAXONIMY_CODE,F,G,H
FROM TEMP2
WHERE SOURCE_ID = 'COSMOS'
) w
ON (a.provider_id = w.provider_id AND
a.NATIONAL_PROVIDER_IDENTIFIER = w.NATIONAL_PROVIDER_IDENTIFIER AND
a.TAXONOMY_CODE = w.TAXONOMY_CODE
)
WHEN MATCHED THEN
UPDATE SET a.b = w.b,
a.c = w.c,
a.d = w.d,
a.f = w.f,
a.g = w.g,
a.h = w.h
WHEN NOT MATCHED THEN
INSERT (a.B,a.C,a.D,a.PROVIDER_ID,a.NATIONAL_PROVIDER_IDENTIFIER,a.TAXONIMY_CODE,a.F,a.G,a.H)
VALUES (w.B,w.C,w.D,w.PROVIDER_ID,w.NATIONAL_PROVIDER_IDENTIFIER,w.TAXONIMY_CODE,w.F,w.G,w.H);

Replace SELECT INTO statement with a cursor ORACLE

This is the query. How to replace SELECT INTO statement with a cursor?
I'm newbie in Oracle
Thanks for your help
SELECT CEQ_LISTE_TYPE_QUESTIONS.ID_LISTE_TYPE_QUESTION
INTO vintIdListeTypeQuestion
FROM CEQ_FORMULAIRES
inner join CEQ_LISTE_TYPE_QUESTIONS
on CEQ_LISTE_TYPE_QUESTIONS.ID_LISTE_TYPE_FORMULAIRE=CEQ_FORMULAIRES.ID_TYPE_FORMULAIRE
AND CEQ_LISTE_TYPE_QUESTIONS.WEBCODE='ITEM_BETA_LACTAMASE'
WHERE CEQ_FORMULAIRES.ID_FORMULAIRE=to_number(out_rec.ID_FORMULAIRE)
and ceq_formulaires.date_inactive is null;
The error tells you that the query returns more than 1 row, so you should determine which row you need. Here an example how to fetch the most recent row based on a date field I thought up in ceq_list_type_questions "some_date".
select max(q.id_liste_type_question) keep (dense_rank last order by q.some_date) into vintidlistetypequestion
from ceq_formulaires f
join ceq_liste_type_questions q on q.id_liste_type_formulaire = f.id_type_formulaire
where f.id_formulaire = to_number(out_rec.id_formulaire)
and f.date_inactive is null
and q.webcode = 'ITEM_BETA_LACTAMASE'
Well, if you want to process your multiple rows in a loop, it's as simple as
BEGIN
FOR curs IN (SELECT ceq_liste_type_questions.id_liste_type_question
FROM ceq_formulaires
INNER JOIN ceq_liste_type_questions ON ceq_liste_type_questions.id_liste_type_formulaire=ceq_formulaires.id_type_formulaire
AND ceq_liste_type_questions.webcode = 'ITEM_BETA_LACTAMASE'
WHERE ceq_formulaires.id_formulaire = TO_NUMBER(out_rec.id_formulaire)
AND ceq_formulaires.date_inactive IS NULL)
LOOP
DBMS_OUTPUT.PUT_LINE(curs.id_liste_type_question); -- do what you need to do
END LOOP;
END;
/
But, as BazzPsychoNut mentions, if it's a requirement that your SQL return/operate on a single row, you'll need to modify your query to meet that requirement.

Copy data from a column in some rows to another column in other rows in oracle

quite the same question as here : Copy data from one existing row to another existing row in SQL?
but in Oracle, where update ... from and update t1, t2 are not supported.
I'll repeat it here in my own words ;
I have a table T, which looks like this :
and as the arrow shows it, I want to copy everything from r where c = 1 to e where c = 2, with t matching.
I have the select statement to get what I want to copy :
select
told.t,
told.r
from
T told
inner join
T tnew
on
told.t= tnew.t
where
told.c = 1
and
tnew.c = 2
I just don't know how to put this together in an update. An Oracle update, specifically.
try this:
update T tnew
set tnew.e = (select told.r from T told where told.c = 2 and told.t = tnew.t)
where tnew.c = 1
Sounds like the time for a bulk collects! Not as pretty as AB Cade's solution but more efficient.
declare
c_data is
select t1.rowid as rid, t2.r
from my_table t1
join my_table t2
on t1.t = t2.t
where t1.c = 2
and t2.c = 1
;
type t__data is table of c_data index by binary_integer;
t_data t__data;
begin
open c_data;
loop
fetch c_data bulk collect into t_data limit 25000;
exit when t_data.count = 0;
forall i in t_data.first .. t_data.last loop
update my_table
set e = t_data(i).r
where rowid = t_data(i).rid
;
commit;
end loop;
close c_data;
end;
/

Resources