This question already has answers here:
Update statement with inner join on Oracle
(15 answers)
Closed 8 years ago.
I am new to Oracle SQL and need some help with the writing the following query. Any guidance would be greatly appreciated. I am not sure I am going down the correct path with this or not.
I have two tables t1 and t2. t1 contains four fields f1...f4. t2 contains the same four fields. I need to update t1.f1 and t1.f4 with the values from t2.f1 and t2.f4, respectively, where t1.f2 = t2.f2 and t1.f3 = t2.f3. If there is a row that does not match these conditions, The row should not be updated.
Am I on the right path or completely lost?
UPDATE t1
SET (t1.f1=t2.f1,
t1.f4=t2.f4)
FROM t1
INNER JOIN (SELECT t2.f1, t2.f4 FROM t2)
ON t1.f2=t2.f2 AND t1.f3=t2.f3
WHERE EXISTS (SELECT t2.f1, t2.f4
FROM t2
WHERE t1.f2=t2.f2 AND t1.f3=t2.f3);
Might be easier if you use a MERGE statement. Something like:
MERGE INTO t1
USING
(SELECT f1,f2,f3,f4 FROM t2) t2
ON
(t1.f2=t2.f2
AND t1.f3 = t2.f3)
WHEN MATCHED THEN
update set t1.f1 = t2.f1,
t1.f4 = t2.f4;
If you are using Oracle version 9i or above 'MERGE' is the best way to do it.
Or you can rewrite your above query like this
UPDATE table1 t1
SET (t1.f1,t1.f2) = (
select t2.f1,t2.f4 from table2 t2
where t1.f2 = t2.f2 and t1.f3 = t2.f3)
WHERE EXISTS (SELECT 1
FROM table2 t2
WHERE t1.f2=t2.f2 AND t1.f3=t2.f3);
Related
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!
This question already has answers here:
Oracle syntax left joins three or more tables
(2 answers)
Closed 7 years ago.
I have some tables in Oracle.
Table_1 contains :
id|name
1|boy
2|roy
Table_2 contains :
id|value
1|90
2|100
Table_3 contains :
id|class
1|A
2|B
I want to join all three tables.
Query_1 :
SELECT A.ID,A.NAME,B.VALUE,C.CLASS
FROM
TABLE_1 A, TABLE_2 B, TABLE_3 C
WHERE
A.ID=B.ID(+) AND
B.ID=C.ID(+)
OR
Query_2 :
SELECT A.ID,A.NAME,B.VALUE,C.CLASS
FROM
TABLE_1 A, TABLE_2 B, TABLE_3 C
WHERE
A.ID=B.ID(+) AND
A.ID=C.ID(+)
Which one is true?
When you need an Outer Join:
Your query will include two or more tables where there may not exist a match for every record. Examples will explain best. If you have two tables: "Parent", and "Work". If you want to ask the question: What contacts do we have within our parent list within local employers an inner join works fine:
select w.employer, w.phone, w.address,p.name, p.phone
from work w, parent p
where w.person_id = p.person_id
If the question is where do our parents work -- well some may be unemployed and have no match in the "work" table -- now you need an outer join. in Oracle SQL:
select p.name, p.phone, w.employer, w.phone, w.address,
from work w, parent p
where p.person_id = w.person_id(+)
The (+) always goes on the side where we need to "synthetically" add a missing id.
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
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.
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