2

the below FOR loop doesn't work. I have two columns PID, PAYMENT in table t1 and table t2. I want to update PAYMENT in table t1 from table t2 where t1.PID=t2.PID

FOR X  IN(select paymentterm,pid from temp_project)  
LOOP
  update project p
set p.paymentterm=temp_project.PID
where p.PID=X.PID;
END LOOP;
commit;
2
  • Why have you added a mysql tag to this? The interfaces you are using do not matter for this question. Commented Jan 28, 2014 at 17:51
  • actually out of all these examples your way is the only one that worked for me to update multiple rows based on a select. Commented Dec 28, 2016 at 22:47

2 Answers 2

4

You can achieve this behavior without looping:

UPDATE project
SET    paymentterm = (SELECT peymentterm
                      FROM   temp_project
                      WHERE  project.pid = temp_project.pid)
WHERE  pid IN (SELECT pid FROM temp_project)
Sign up to request clarification or add additional context in comments.

6 Comments

-1, because if there are pid's in project that are not in temp_project, you just set all of their paymentterm's to null
@DavidAldridge good point, added a WHERE clause. I wish Oracle had a sensible UPDATE JOIN syntax...
@Murenik -- you can perform both updates and deletes against key-preserved views (see my answer). Not ideal, but cleaner than making the join twice.
@DavidAldridge yup, I'm aware of that. Clunky as heck, IMHO (not your answer, which I upvoted - Oracle's solution for this problem)
Well, it does have the benefit of being very "relational". In theory a query or a view or a table should all be equally updateable, so this join between project and temp_project could be defined as a view, and the update run against it.
|
3

Try:

update project p
set    paymentterm = (select t.paymentterm
                        from temp_project tp
                       where tp.pid = p.pid)
where  pid in (select pid from temp_project)

... or, if temp_project.pid is constrained to be unique:

update (select p.pid,
               p.paymentterm,
               t.paymentterm new_paymentterm
          from project p join temp_project t on p.pid = t.pid)
set    paymentterm = new_paymentterm;

You might make sure that you're not making changes where none are required with:

update (select p.pid,
               p.paymentterm,
               t.paymentterm new_paymentterm
          from project p join temp_project t on p.pid = t.pid
         where coalesce(p.paymentterm,-1000) != coalesce(t.paymentterm,-1000))
set    paymentterm = new_paymentterm;

(Guessing at -1000 being an impossible value for paymentterm there). This could also be written as a MERGE statement.

4 Comments

David, when trying to use 2nd query, it gives error:"cannot modify a column which maps to a non key-preserved table" *Cause: An attempt was made to insert or update columns of a join view which map to a non-key-preserved table. *Action: Modify the underlying base tables directly. 1st query gives the error: single-row subquery returns more than one row 01427. 00000 - "single-row subquery returns more than one row"
In the temp_project table, the pid is not unique. Therefore the system does not know which value to use to apply to the project table. You ought to fix this, although there would be workarounds.
tried the second method but: ORA-01779: cannot modify a column which maps to a non key-preserved table in my case i can't have a key on there since it's not unique.
merge also won't work because it doesn't allow for multiple rows. get the unstable rows message when i try that

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.