Oracle Update Statement Using a Join - oracle

I need some help with this query. It works fine in SSMS, but will not work in Oracle. How can I rewrite this so it will work in Oracle? I really appreciate the help.
UPDATE reservation_Daily_elements e
SET e.MARKET_CODE = 'PHEE',
e.ORIGIN_OF_BOOKING = 'DESKTOP'
FROM reservation_Daily_elements e
LEFT JOIN reservation_daily_element_name dn
ON e.resv_daily_el_seq = dn.resv_daily_el_seq
WHERE dn.RESV_NAME_ID IN ('3747957');
Commit;

How about MERGE?
merge into reservation_daily_elements e
using (select dn.resv_daily_el_seq
from reservatioin_daily_element_name dn
where dn.resv_name_id = '3747957'
) x
on (e.resv_daily_el_seq = x.resv_daily_el_seq)
when matched then update set
e.market_code = 'PHEE',
e.origin_of_booking = 'DESKTOP';
If it has to be UPDATE, then
update reservation_daily_elements e set
e.market_code = 'PHEE',
e.origin_of_booking = 'DESKTOP'
where exists (select null
from reservation_daily_element_name dn
where dn.resv_daily_el_seq = e.resv_daily_el_seq
and dn.resv_name = '3747957'
);

Btw, oracle supports updatable inline views, so you can use simple update (Select... From t1 join t2 on...) set... .
Also as I see your 'left join' is really 'inner join' because of the predicates in where clause.

Related

Syntax issues with pervasive SQL if statement used to determine left join on clause

Back Story: I am looking to do a left join based on if a condition is true with an if statement. However if it is false, I want to still join the said table in, but with the same columns or with a new set of columns. This query is being wrote for a Pervasive SQL DB.
This query is fairly large, without this particular issue it executes and returns the data sets as expected. Below is a snapshot of the issue I am currently running into..
SELECT A.ONUM, B.JN, C.SEQ, C.PN
From Z.OH
LEFT JOIN OL A ON Z.ONUM = A.ONUM
LEFT JOIN JH B ON A.ONUM = B.SNUM AND A.OLNUM = B.SLNUM AND B.CLSD <> 'Y'
LEFT JOIN JO C ON IF(A.LC <> 'ZY', B.JN = C.JN, LEFT(B.C_PO, 6) = C.JN OR B.JN = C.JN) AND C.OP_T NOT IN ('Z','C')
WHERE Z.OT <> 'T' AND C.PN NOT IN (SELECT X.PN FROM JH X WHERE B.JN = X.JN)
Again, very summarized version with lots of joins/filters/select statement removed.
I am running into issues on the join with the IF statement. Without the if statement, the query executes as expected.
The original join being: B.JN = C.JN AND C.OP_T NOT IN ('Z', 'C')
When executing the query in PCC it would give the following syntax error at the following point: "B.JN << ??? >> = C.JN"
I tried switching over to an OR statement as shown below, but the run time of the query made it an impossible choice.
LEFT JOIN JO C ON
(B.JN = C.JN) OR (A.LC = 'ZY' AND LEFT(B.C_PO, 6) = C.JN)
AND C.OP_T NOT IN ('Z','C')
Checking the documentation, it looks like the query on the if statement is following the correct syntax...
Most simple solution would be to avoid the IF in the WHERE-clause, and do:
SELECT A.ONUM, B.JN, C.SEQ, C.PN
From Z.OH
LEFT JOIN OL A ON Z.ONUM = A.ONUM
LEFT JOIN JH B ON A.ONUM = B.SNUM AND A.OLNUM = B.SLNUM AND B.CLSD <> 'Y'
LEFT JOIN JO C ON (A.LC <> 'ZY' AND B.JN = C.JN) OR (A.LC = 'ZY' AND (LEFT(B.C_PO, 6) = C.JN OR B.JN = C.JN))
AND C.OP_T NOT IN ('Z','C')
WHERE Z.OT <> 'T' AND C.PN NOT IN (SELECT X.PN FROM JH X WHERE B.JN = X.JN)

Update statement in Oracle with joins

I have the below code in SQL Server:
UPDATE RH SET
--SELECT RH.economic_class ,
economic_class = C.economic_class
FROM dbo.tblRecHist RH
JOIN tblComp C ON RH.company_id = C.company_id
WHERE RH.company_id = #CompID
AND RH.rec_date = #RecDate
Which I have converted in Oracle to:
UPDATE tblRecHist
SET economic_class = (Select C.economic_class from tblComp C join tblRecHist
RH on RH.company_id = C.company_id)
WHERE RH.company_id = v_CompID
AND RH.rec_date = v_RecDate;
As this is a part of a big procedure I am unable to execute this independently.
So, my question is are both the logic correct? If not, what could be the possible change?
That logic won't work becuase your subquery will return more than one record. Instead of joining tblRecHist into your subquery, omit it and correlate the subquery with the current row of tblRecHist from the UPDATE.
UPDATE tblRecHist rh
SET economic_class = (Select C.economic_class
from tblComp C
WHERE C.company_id = RH.company_id )
WHERE RH.company_id = v_CompID
AND RH.rec_date = v_RecDate;
This assumes company_id is a unique key in tblComp.

UPDATE query is slow in combination with RETURNING INTO clause

I have update query which returns updated rows ID. Execution time of query is about 90 seconds. When i remove Returning clause, then execution time is 1ms.
Table update_table has 39000 rows.
Query updates 0 rows in this case. When updates 3 rows- execution time is same.
DECLARE
type intTable IS TABLE OF INTEGER;
idCol intTable;
BEGIN
UPDATE
update_table
SET
prop1 = 3, prop2 = NULL
WHERE EXISTS (
SELECT null FROM update_table f
INNER JOIN rel_table1 u ON f.ID= u.ID
INNER JOIN rel_table2 VP ON f.another_ID = VP.another_ID
WHERE (u.prop1 = 3)
AND VP.prop1 = 1
AND (u.prop2 = 75)
AND f.ID = update_table.ID
)
ReTURNING ID BULK COLLECT INTO idCol;
.
.
.
END;
Why returning clause slows down query?
A good part of using Oracle is knowing what is "supposed" to happen and what isn't.
Adding a RETURNING INTO clause is not "supposed" to make your update run more slowly. When something happens that isn't supposed to happen, check Oracle's support site to see whether it is a known bug.
In your case, it looks like you are encountering:
Bug 27131648 - SUB OPTIMAL PLAN ON UPDATE STATEMENT WITH RETURNING INTO
I am not sure if there is a patch, but there is a simple workaround: use the UNNEST hint. In your case, that would be:
UPDATE
update_table
SET
prop1 = 3, prop2 = NULL
WHERE EXISTS (
SELECT /*+ UNNEST */ null FROM update_table f
INNER JOIN rel_table1 u ON f.ID= u.ID
INNER JOIN rel_table2 VP ON f.another_ID = VP.another_ID
WHERE (u.prop1 = 3)
AND VP.prop1 = 1
AND (u.prop2 = 75)
AND f.ID = update_table.ID
)
ReTURNING ID BULK COLLECT INTO idCol;
I would recommend splitting it into two parts, first BULK COLLECT and next FORALL collected ID's, both extremely fast and you'll keep being able to further reference updated ID's from idCol.
DECLARE
type intTable IS TABLE OF INTEGER;
idCol intTable;
BEGIN
SELECT f.id
BULK COLLECT INTO idCol
FROM update_table f
INNER JOIN rel_table1 u ON f.ID= u.ID
INNER JOIN rel_table2 VP ON f.another_ID = VP.another_ID
WHERE (u.prop1 = 3)
AND VP.prop1 = 1
AND (u.prop2 = 75);
FORALL indx IN 1..idCol.COUNT
UPDATE update_table
SET prop1 = 3, prop2 = NULL
WHERE id = idCol(indx);
.
.
.
END;
I hope I helped!

Using Merge in Oracle for updating a parent table using Joins

I have a SQL statement as below, I couldn't execute the statement in Oracle as it doesn't support Joins in Update. I have tried using updating using a temp table and completed the job, however, I would like to use the Merge statement and failed to write the code.
Let me know if there is a possibility in Oracle use joins in an update which doesn't add any performance overhead.
UPDATE A SET
YearStartPD = B.PERIOD_CODE,
YearEndPD = A.PERIOD_CODE,
PY_YearStartPD = C.PERIOD_CODE,
PY_YearEndPD = A.PY_WeekEndPD
FROM dbo.DIM_TIME A
INNER JOIN
(
select PERIOD_CODE,WEEK_PERIOD_CODE,YEAR_CODE from dbo.DIM_TIME
WHERE WEEK_PERIOD_CODE = '01'
) B ON B.Year_Code = A.Year_Code
LEFT JOIN
(
select PERIOD_CODE,WEEK_PERIOD_CODE,YEAR_CODE from dbo.DIM_TIME
WHERE WEEK_PERIOD_CODE = '01'
) C ON C.Year_Code = A.Year_Code - 1

Oracle Update query with joins

I do know update clause doesn't work with joins in Oracle.
update table1 Pr
set code = (select t2.class_attr_value from table2 t2
where class_attr_name = 'sample' and Pr.epcclass_id = t2.epcclass_id)
I would be thankful if someone can help me modify my query so that I don't get the error of SQL Command not ended properly.
Your Query seems okay to me I just added Table Alias. Your query will update all records in table1. What error you are getting...??
Suggestions,
a) Unless it's the intent that you want to update all records, add a where clause in the query to avoid updating all records...
b) If you are getting (ORA-01427: single-row subquery returns more than one row) then means corelated sub query (within brackets) is missing some condition to make it fetch only 1 row per epcclass_id.
update table1 Pr
set Pr.code = (select t2.class_attr_value
from table2 t2
where t2.class_attr_name = 'sample'
and t2.epclass_id = Pr.epcclass_id
);
Try this:
UPDATE table1 Pr INNER JOIN table2 t2
ON t2.class_attr_name = 'sample' AND Pr.epcclass_id = t2.epcclass_id
SET Pr.code = t2.class_attr_value

Resources