Oracle - Update with join - oracle

Using Oracle 11g. I need to do an update with a self join. Oracle doesn't support updates with joins and using MERGE isn't working as I'm trying to do an update on columns used in the on clause
What I've tried:
update
(
select a.ID, a.FROM_STAGE_ID, a.TO_STAGE_ID, b.TO_STAGE_ID
from STATES a,
STATES b
where a.ID = b.ID and
a.TO_STAGE_ID = b.FROM_STAGE_ID and
a.TO_STAGE_ID = 'FIZZBUZZ' and
a.FROM_STAGE_ID <> b.TO_STAGE_ID and
a.CODE = b.CODE
)
set a.TO_STAGE_ID=b.TO_STAGE_ID;
This resulted in : "SQL Error: ORA-00904: "B"."TO_STAGE_ID": invalid identifier"
MERGE
INTO STATES a
USING STATES b
ON (
a.ID = b.ID and
a.TO_STAGE_ID = b.FROM_STAGE_ID and
a.TO_STAGE_ID = 'FIZZBUZZ' and
a.FROM_STAGE_ID <> b.TO_STAGE_ID and
a.CODE = b.CODE
)
WHEN MATCHED THEN
UPDATE
set a.TO_STAGE_ID = b.TO_STAGE_ID;
This resulted in: "SQL Error: ORA-38104: Columns referenced in the ON Clause cannot be updated: "A"."TO_STAGE_ID"
38104. 00000 - "Columns referenced in the ON Clause cannot be updated: %s"
*Cause: LHS of UPDATE SET contains the columns referenced in the ON Clause
I can try deleting the rows that require updating and populating them from a staging/temp table, but am interested to see if there is another way.

The error in the first case is because you are trying to reference the columns using table aliases that are only valid within the scope of the subquery. You should be able to get around that by aliasing the columns:
update
(
select a.ID, a.FROM_STAGE_ID, a.TO_STAGE_ID a_to_stage_id, b.TO_STAGE_ID b_to_stage_id
from STATES a,
STATES b
where a.ID = b.ID and
a.TO_STAGE_ID = b.FROM_STAGE_ID and
a.TO_STAGE_ID = 'FIZZBUZZ' and
a.FROM_STAGE_ID <> b.TO_STAGE_ID and
a.CODE = b.CODE
)
set a_to_stage_id = b_to_stage_id
This still may not work - it depends on whether the join preserves the key of the original table.

Related

JPQL query with having oracle db

I am using jpql jpa eclipselink Following query wont work :
SELECT c FROM TableA c WHERE c.forumId = :forumId AND c.isDefault = true HAVING MAX (c.validFrom)
The error im getting "The expression is not a valid conditional expression"
The HAVING clause only works with a GROUP BY expression.
The HAVING clause allows for the results of a GROUP BY to be filtered.
Your question is:
i want o get max validFrom how can i make expression ot of this
But you can make a query without GROUP BY and HAVING to do what you want:
select c from TableA c WHERE c.validFrom = (
SELECT MAX(c2.validFrom)
FROM TableA c2
WHERE c2.Id = c.Id AND c.forumId = :forumId AND c.isDefault = true
)
If you would like to use GROUP BY and HAVING, you can do:
SELECT c FROM TableA c WHERE c.validFROM = (
SELECT MAX(validFROM)
FROM TableA
WHERE forumId = :forumId AND isDefault = true
GROUP BY validFROM
HAVING validFROM=c.validFROM
)

How to update and set values based on multiple joins in select statment?

I want to update a column prtnum and revlvl in table invdtl based on value from select statment, here is the code
update invdtl set invdtl.prtnum = usr_prtmst_xref.prtnum,invdtl.revlvl =
usr_prtmst_xref.colnam ([select
invdtl.prtnum,usr_prtmst_xref.prtnum AS
crossref,invdtl.revlvl,aremst.arecod,aremst.fwiflg from invdtl
join usr_prtmst_xref
on usr_prtmst_xref.prtnum = usr_prtmst_xref.prtnum
join invsub
join invlod
join locmst
join aremst
on aremst.arecod = locmst.arecod
and aremst.wh_id = locmst.wh_id
on locmst.stoloc = invlod.stoloc
and locmst.wh_id = invlod.wh_id
on invlod.lodnum = invsub.lodnum
on invsub.subnum = invdtl.subnum where aremst.arecod = 'EXPR' or
aremst.fwiflg = '1' and rownum <2])
I want to copy two values prtnum and revlvl that are returned by select statement but there is some syntax issue.
There are a bunch of errors here:
The syntax for a multi-column update is basically
update blah
set ( col1, col2 ) = ( select x, y
from
...
)
The syntax for multiple joins is basically
from table1 t1
join table2 t2
on t1.col = t2.col
join table3 t2 on
t2.col = ...
Get ride of "[" and "]"
The predicate rownum<2 is probably to get around the message you received, something like "single row sub-query returns more than 1
row" Which this predicate "fixes" that problem, you are just getting
the first random row; probably not what you want. You probably need to
correlate the sub-query with the update
I would fix these basic syntax errors and try again.

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!

Why sub SQL in FROM area can't be null?

select col_1,
col_2
from tbl_a A,
tbl_b B,
( select col_1,col_2 from tbl_c where clo_c_1 <> '1' ) C
where A.col_1 = B.col_1
and A.col_2 = B.col_2
and (A.col_2 = B.col_2
or C.col_2 = A.col_2);
My environment is Oracle,when I run this SQL,if the sub SQL C hasn't got a result,then the entire SQL returns NULL.Whereas if C has a result(not null) which fits other condions,there could be a result.Would somebody explain why sub SQL at the from area need to be not NULL?Thanks very much.
You need to bring yourself into the 90s and start using standard joins:
select col_1,
col_2
from tbl_a A
inner join
tbl_b B
on A.col_1 = B.col_1
and A.col_2 = B.col_2
left join
( select col_1,col_2 from tbl_c where clo_c_1 <> '1' ) C
on
C.col_2 = A.col_2
As a guess. I'm not entirely sure what your join conditions should be but that's my first attempt.
This is expected behaviour. When you join two result sets, you only want to get results where the join criteria is satisfied. If the criteria are not satisfied, you should get no results.
If I run the query "get me all the employees older than 65, and get their departments", if there are no employees older than 65, you would not expect to get any results, even if there are some departments in the database.
SELECT emp.name, dept.dept_name
FROM emp
JOIN dept
ON (emp.dept_no = dept.dept_no)
WHERE emp.age > 65;
As the others said, if you actually want to get rows regardless of whether the subquery has any results, you need to use an outer join.

Oracle: column ambiguously defined

I know there are lots of questions like these, but my question is not how to get rid of this error but to know how this worked earlier in 9-th version of Oracle.
I've got an old sources written in Ruby and Oracle DB which recently was upgraded to version=11.
I cannot edit data in Oracle DB, only read. so there are two tables lets say: table A(id, name, type, customer) and table B(id,a_id,type,person)
so. there is a query in the source code:
select a.id,b.id from a join b on a.id = b.a_id where type = 'A'
so in Oracle 9 this worked perfectly but now i've got "column ambiguously defined" error.
What i'd like to know is:
where type = 'A'
is the same as
where a.type = 'A' AND b.type = 'A'
or
where a.type = 'A' OR b.type = 'A'
?
I think this was a bug with the ANSI style join. Use DBMS_XPLAN to find which table was being filtered in the old database.
Or better still, work out from the business logic what they query SHOULD have been.
No, and that's the problem: It could mean
where a.type = 'A'
or it could mean
where b.type = 'A'
with potentially different results; hence the error saying it is ambiguously defined.
I think you should test in Oracle 9 (where you say it works) and compare the output of the ambiguous query:
--- Base
select a.id,b.id from a join b on a.id = b.a_id where type = 'A'
with both the non-ambiguous ones:
--- QueryA
select a.id,b.id from a join b on a.id = b.a_id where a.type = 'A'
and:
--- QueryB
select a.id,b.id from a join b on a.id = b.a_id where b.type = 'A'
Something like this would do:
select a.id,b.id from a join b on a.id = b.a_id where type = 'A'
MINUS
select a.id,b.id from a join b on a.id = b.a_id where a.type = 'A'
(in short):
(Base)
MINUS
(QueryA)
and then:
(QueryA)
MINUS
(Base)
If both of the above MINUS queries return 0 rows, then BASE query is interpreted as QueryA.
Check similarly and compare Base with QueryB.
Another plausible reason for this error is that during (or about the same period with ) the migration, a type column was added in the 2nd table. Do you have old versions of the database tables' definitions to check that?
All - keep in mind there was a major change to the optimization engine for 11g. If you set your query optimizer level to 10.2.x on your 11g instance I bet the query would start working again.
That being said you should provide the alias for it so it's not ambiguous to the database server or the DBA / Developer coming behind you. :)

Resources