I have an MS_ACCESS Query to convert to Oracle SQL.
Access Query
UPDATE target_table T
INNER JOIN source_table S
ON T.linkcolumn = S.linkColumn
SET
T.field1 = S.field1,
T.field2 = S.field2,
T.field3 = S.field3;
Note: This query updates records even though there is a 1-to-many relationship between the Source (1) and the target (many)
----------------------------------------------------
Oracle SQL
This code produces an "unable to get stable set of rows" error because
the target table has instances of many records in the target table matching one record in the source table
MERGE INTO target_table T
USING (
SELECT *
FROM source_table
) S
ON
(
T.manyRecsLinkColumn = S.oneRecLinkColumn
)
WHEN MATCHED THEN
UPDATE SET
T.columnToUpdate1 = S.Value1,
T.columnToUpdate2 = S.Value2,
T.columnToUpdate3 = S.Value3
-------------------------------------------------------
Alternate Approach In Access using VBA script (Pseudo Code)
Dim strFieldValue as String
Dim myDB as database
Dim rsSource, rsTarget as Recordset
Set rsSource = myDB.openRecordset(source_table)
Set rsTarget = myDB.openRecordset(target_table, dbOpenDynaset)
rsSource.moveFIRST ' Start at 1st record
Do while not rsSource.EOF ' Begin Row by Row Scan
strFieldValue = rs!Source!MyValue
rsTarget.findFIRST " rsTarget.FieldName = 'strFieldValue' "
if NOT rsTarget.noMatch ' it is a match
Update rsTarget!Column1 = rsSource!Column1
Update rsTarget!Column2 = rsSource!Column2
Update rsTarget!Column3 = rsSource!Column3
else ' it is not a match
Goto NextRecord
endif
LookForMore:
rsTarget.findNEXT " rsTarget.FieldName = 'strFieldValue' "
if NOT rsTarget.noMATCH ' it is a match
Update rsTarget!Column1 = rsSource!Column1
Update rsTarget!Column2 = rsSource!Column2
Update rsTarget!Column3 = rsSource!Column3
Goto LookForMore
endif
NextRecord: ' no more matches
rsSource.moveNEXT ' Move to next Source record
Loop ' Repeat until End-of-Table
------------------------------------------------------------
Questions:
1. Is there an Oracle SQL statement, perhaps a refinement of the Oracle Code above, which will Update multiple records when there is
1-to-many relationship between the source (1) and target (many)
2. If a Stored Procedure is the only approach, could you provide a general look of that procedure that is probably similar to the ACCESS VBA script above.
So you have one row in your source table that matches with many in the target?
You can "update the join" in Oracle Database.
Provided you have a primary or unique key on the join columns!
create table t1 (
x int,
c1 int,
c2 int,
c3 int
);
create table t2 (
x int ,
c1 int,
c2 int,
c3 int
);
insert into t1 values (1, 1, 1, 1);
insert into t2 values (1, 0, 0, 0);
insert into t2 values (1, 2, 2, 2);
insert into t2 values (1, 4, 4, 4);
commit;
select * from t2;
X C1 C2 C3
1 0 0 0
1 2 2 2
1 4 4 4
update (
select t1.c1 c11, t2.c1 c12 ,
t1.c2 c21, t2.c2 c22 ,
t1.c3 c31, t2.c3 c32
from t1 join t2 on t1.x = t2.x
)
set c12 = c11, c22 = c21, c32 = c31;
SQL Error: ORA-01779: cannot modify a column which maps to a non key-preserved table
select * from t2;
X C1 C2 C3
1 0 0 0
1 2 2 2
1 4 4 4
alter table t1 add primary key (x);
update (
select t1.c1 c11, t2.c1 c12 ,
t1.c2 c21, t2.c2 c22 ,
t1.c3 c31, t2.c3 c32
from t1 join t2 on t1.x = t2.x
)
set c12 = c11, c22 = c21, c32 = c31;
select * from t2;
X C1 C2 C3
1 1 1 1
1 1 1 1
1 1 1 1
Or you could go for a correlated update:
rollback;
update t2
set (c1, c2, c3) = (
select c1, c2, c3 from t1
where t1.x = t2.x
);
select * from t2;
X C1 C2 C3
1 1 1 1
1 1 1 1
1 1 1 1