How can I improve this update script? - oracle

I want to update a table in oracle which has 155.750 rows.
I write this:
UPDATE Table1 R
SET R.TOTAL =
(SELECT SUM(T.TOTALS_TO_DATE)
FROM Table2 T
WHERE T.ID= R.ID
AND T.TYPE = 'type5');
Table1 has index at ID
Table2 has indexes at ID and TYPE.
This is not responding. How can edit this to run fastly?
If I write this select it runs fastly.
SELECT SUM(T.TOTALS_TO_DATE),R.ID
FROM Table2 T,Table1 R
WHERE T.ID= R.ID
AND T.TYPE = 'type5'
group by R.ID ;
This runs but I do not understand why the update script takes 3000seconds.
Thanks.

try to use MERGE statement
MERGE INTO table1 R using
( SELECT SUM(T.TOTALS_TO_DATE) S, T.ID
FROM Table2 T
WHERE T.TYPE = 'type5'
group by T.ID
) T
ON ( R.ID = T.ID)
WHEN MATCHED THEN UPDATE SET R.TOTAL = T.S
;

You forgot to put the where condition in the Update script. Hence it is updating the whole table1 and hence it is taking time.
For the select query you have mentioned the where clause which is running faster.
Edit:-
Check our this link
Here are some of the steps which you can do to improve your update command run faster.
Removing index on the column to be updated.
Executing the update in smaller batches.
Disabling Delete triggers.
Replacing Update statement with a Bulk-Insert operation.

Related

INSERT ALL statement incredibly slow, even when no records to insert

This is on 11g. I have an INSERT ALL statement which uses a SELECT to build up the values to insert. The select has some subqueries that check that the record doesn't already exist. The problem is that the insert is taking over 30 minutes, even when there are zero rows to insert. The select statement on its own runs instantly, so the problem seems to be when it is used in conjunction with the INSERT ALL. I rewrote the statement to use MERGE but it was just as bad.
The table has no triggers. There is a primary key index, and a unique constraint on two of the columns, but nothing else that looks like it might be causing an issue. It currently has about 15000 rows, so definitely not big.
Has anyone a suggestion for what might be causing this, or how to go about debugging it?
Here's the INSERT ALL statement.
insert all
into template_letter_merge_fields (merge_field_id, letter_type_id,table_name,field_name,pretty_name, tcl_proc)
values (template_let_mrg_fld_sequence.nextval,letter_type_id,table_name,field_name, pretty_name, tcl_proc)
select lt.letter_type_id,
i.object_type as table_name,
i.interface_key as field_name,
i.pretty_name as pretty_name,
case
when w.widget = 'dynamic_select' then
'dbi::'||i.interface_key||'::get_name'
when w.widget = 'category_tree' and
i.interface_key not like '%_name' and
i.interface_key not like '%_desc' then
'dbi::'||i.interface_key||'::get_name'
else
'dbi::'||i.interface_key||'::get_value'
end as tcl_proc
from template_letter_types lt,
dbi_interfaces i
left outer join acs_attributes aa on (aa.object_type||'_'||aa.attribute_name = i.interface_key
and decode(aa.object_type,'person','party','aims_organisation','party',aa.object_type) = i.object_type)
left outer join flexbase_attributes fa on fa.acs_attribute_id = aa.attribute_id
left outer join flexbase_widgets w on w.widget_name = fa.widget_name
where i.object_type IN (select linked_object_type
from template_letter_object_map lom
where lom.interface_object_type = lt.interface_object_type
union select lt.interface_object_type from dual
union select 'template_letter' from dual)
and lt.interface_object_type = lt.interface_object_type
and not exists (select 1
from template_letter_merge_fields m
where m.sql_code is null
and m.field_name = i.interface_key
and m.letter_type_id = lt.letter_type_id)
and not exists (select 1
from template_letter_merge_fields m2
where m2.pretty_name = i.pretty_name
and m2.letter_type_id = lt.letter_type_id)

ORACLE - Update Multiple Columns with Values from Nested Join

I'm practically new in using oracle and I bumped into a blocker. Below is the query that I created based on what I have researched online to update multiple columns of a table with values from a nested join statement.
UPDATE
(
SELECT
A.COLUMN1 OLD_COLUMN1,
BC.COLUMN1 NEW_COLUMN1,
A.BALANCE OLD_COLUMN2,
BC.COLUMN2_MIN NEW_COLUMN2,
A.COLUMN3 OLD_COLUMN3,
BC.COLUMN3 NEW_COLUMN3
FROM TABLE_A A
INNER JOIN
(
SELECT B.TWWID,
B.ITEMDATE,
B.COLUMN2_MIN,
C.COLUMN3,
C.COUNTRYID,
C.COLUMN1
FROM TABLE_B B
LEFT OUTER JOIN TABLE_C C
ON TO_CHAR(B.ID) = TO_CHAR(C.ID)
) BC
ON A.ID = BC.ID
AND A.DATE = BC.DATE
)ABCUPDATE
SET ABCUPDATE.OLD_COLUMN1 = ABCUPDATE.NEW_COLUMN1,
ABCUPDATE.OLD_COLUMN2 = ABCUPDATE.NEW_COLUMN2,
ABCUPDATE.OLD_COLUMN3 = ABCUPDATE.NEW_COLUMN3;
Selecting the sub-query returns the expected results but when I run the update script as a whole an error is returned.
ORA-01779: cannot modify a column which maps to a non key-preserved
table
Can anyone please explain why I encounter this error and what adjustments can I do to the script to make it work?
Thanks in advance!

Update SQL Query with Join on 2 tables

I have a requirement to read from 2 tables once read i have to update the falg on both table.
My SQL query
SELECT t1.KUNNR,t1.SETT_KEY,t1.QUART_START,t1.QUART_END,t2.PAY_METH,t2.MAT_NDC,t2.AMOUNT
FROM TSAP_REBATE_MEDI t1
INNER JOIN TSAP_REBATE_LINE t2 ON t1.KUNNR=t2.KUNNR AND t1.SETT_KEY=t2.SETT_KEY
WHERE t1.PROCESSING_STATUS = 'N' AND t2.PROCESSING_STATUS = 'N'
This is working fine now i need an update query for the same where PROCESSING_STATUS is set to 'P' on both tables.
You cannot update two tables at the same time. Run two separate UPDATE statements of the following nature
UPDATE t1
SET COLUMN = VALUE
FROM TSAP_REBATE_MEDI t1
INNER JOIN TSAP_REBATE_LINE t2
ON t1.KUNNR=t2.KUNNR
AND t1.SETT_KEY=t2.SETT_KEY
WHERE t1.PROCESSING_STATUS = 'N'
AND t2.PROCESSING_STATUS = 'N'
/* Add any other conditions */
However, if you want them both to be updated (or neither one), wrap both updates in a BEGIN TRANSACTION - COMMIT

Comparing two tables, if rows are different, run query in Oracle

Think of my two tables have the same columns. One column is the ID, and the other one is the text. Is it possible to implement the following pseudo code in PLSQL?
Compare each row (They will have the same ID)
If anything is different about them
Run a couple of queries: an Update, and an Insert
ElseIf they are the same
Do nothing
Else the row does not exist
So add the row to the table compared on
Is it easy to do this using PLSQL or should I create a standalone application to do do this logic.
As your table have the same columns, by using NATURAL JOIN you can easily check if two corresponding rows are identical -- without need to update your code if a column is added to your table.
In addition, using OUTER JOIN allow you to find the rows present in one table but not in the other.
So, you can use something like that to achieve your purpose:
for rec in (
SELECT T.ID ID1,
U.ID ID2,
V.EQ
FROM T
FULL OUTER JOIN U ON T.ID = U.ID
FULL OUTER JOIN (SELECT ID, 1 EQ FROM T NATURAL JOIN U) V ON U.ID = V.ID)
loop
if rec.id1 is null
then
-- row in U but not in T
elsif rec.id2 is null
then
-- row in T but not in U
elsif rec.eq is null
-- row present in both tables
-- but content mismatch
end if
end loop
Else the row does not exist
So add the row to the table compared on
Is this condition means that rows can be missed in both tables? If only in one, then:
insert into t1 (id, text)
select id, text
from t2
minus
select id, text
from t1;
If missed records can be in both tables, you need the same query that inserts into table t2 rows from t1.
If anything is different about them
If you need one action for any amount of different rows, then use something like this:
select count(*)
into a
from t1, t2
where t1.id = t2.id and t1.text <> t2.text;
if a > 0 then
...
otherwise:
for i in (
select *
from t1, t2
where t1.id = t2.id and t1.text <> t2.text) loop
<do something>
end loop;
A 'merge' statement is what u needed.
Here is the syntax:
MERGE INTO TARGET_TABLE
USING SOURCE_TABLE
ON (CONDITION)
WHEN MATCHED THEN
UPDATE SET (DO YOUR UPDATES)
WHEN NOT MATCHED THEN
(INSERT YOUR NEW ROWS)
Google MERGE syntax for more about the statement.
Just use MINUS.
query_1
MINUS
query_2
In your case, if you really want to use PL/SQL, then select count into a local variable. Write a logic, if count > 0 then do other stuff.

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