Bulk update a column in Oracle 11G - merge

I have two tables say Table1 and Table2 that contains the following column with which I should join and perform an update a column of Table1 with the value of the same column present in Table2.
Columns for Join condition:
Table1.mem_ssn and Table2.ins_ssn
Table1.sys_id and Table2.sys_id
Table1.grp_id and Table2.grp_id
Column to update:
Table1.dtofhire=Table2.dtofhire
I need a way to bulk update (using single update query without looping) the above mentioned column in Oracle 11G.
Table1 does not contain any key constraint specified since it will be used as a staging table for Data upload.
Please help me out to update the same.

You can use the MERGE statement.
It should look something like this:
MERGE INTO table1 D
USING (SELECT * FROM table2 ) S
ON (D.mem_ssn = S.ins_ssn and D.sys_id = S.sys_id and D.grp_id=S.grp_id)
WHEN MATCHED THEN
UPDATE SET D.dtofhire=S.dtofhire;
UPDATE:
Since you have more than one row in table2 with the same (ins_ssn,sys_id,grp_id) and you want the max dtofhire, you should change the query in the using clause:
MERGE INTO table1 D
USING (SELECT ins_ssn, sys_id, grp_id, max(dtofhire) m_dtofhire
FROM table2
GROUP BY ins_ssn,sys_id,grp_id) S
ON (D.mem_ssn = S.ins_ssn and D.sys_id = S.sys_id and D.grp_id=S.grp_id)
WHEN MATCHED THEN
UPDATE SET D.dtofhire=S.m_dtofhire;

The query that I used to arrive the functionality is seen below
UPDATE table1 T2
SET dtofhire = (SELECT Max(dtofhire) AS dtofhire
FROM table2 T1
WHERE T2.mem_ssn = T1.ins_ssn
AND T2.sys_id = T1.sys_id
AND T2.grp_id = T1.grp_id
GROUP BY ins_ssn,
sys_id,
grp_id)
WHERE ( mem_ssn, sys_id, grp_id ) IN (SELECT ins_ssn,
sys_id,
grp_id
FROM table2 );

Related

Updating a column by counting data from another table

I have two tables let’s say A & B and would like to count the results of column2 in table B by comparing them to table A column2 and update them in table A column1.
I am using the script shown here, but it's taking a really long time so I'd appreciate it if somebody could provide an alternative / better and faster option/script
UPDATE tableA
SET tableA.column1 = (SELECT COUNT(*)
FROM tableB
WHERE tableA.column2 = tableB.column2)
Use the proprietary UPDATE ... FROM to perform a join that can be something else than a nested loop:
UPDATE tableA SET tableA.column1 = tbc.count
FROM (SELECT column2,
count(*) AS count
FROM tableB
GROUP BY column2) AS tbc
WHERE tableA.column2 = tbc.column2;

multiple sequence update postgres

I have a table, on which I have added a new column nxvl.
I need to do something like this
UPDATE table1
SET nxvl = nexval('my_sequence_1')
from table2
where table1.col_id = table2.id and table2.val_col=1
order by table1.date
UPDATE table1
SET nxvl = nexval('my_sequence_2')
from table2
where table1.col_id = table2.id and table2.val_col=2
order by table1.date
Postgres doesn't allow order by on update
It has around 100,000 rows.
Can it be done with Update command. Right now there are only 2 values in val_col ie 1 & 2
Since it's a one time thing, I don't mind doing it with functions and looping through each row and update.
For knowledge wondering if there's a better way of achieving it.
Using Postgres 12.2
You can set the order and fetch the associated sequence value in a subquery, then update table (without even considering the update order)
UPDATE table1
SET nxvl = a.seq
FROM
( select table1.id, nexval('my_sequence_1') seq
from table1
join table2
on table1.col_id = table2.id
and table2.val_col=1
order by table1.date
) a
WHERE table1.id = a.id;

How to update a table column based on the condition of two other table columns using st_contains()

I'm attempting to update a table column based on the st_contains() results using two other tables. The code I've written below returns too many results. What do I need to change to make this work?
UPDATE "PRIMARY_USE_DESC"."CAD_Primary_Desc" SET "Parcel_Desc" = 'PARK'
WHERE (
SELECT geom_poly
FROM "Buda_Parks" t1
LEFT JOIN (
SELECT geom_point
FROM "HCAD_POINTS"
) t2 ON ST_Contains(t1.geom_poly, t2.geom_point)
) IS NOT NULL
Ok, I figured it out. Posting it here in case someone else has this question.
UPDATE "PRIMARY_USE_DESC"."CAD_Primary_Desc"
Set "Parcel_Desc" = 'PARK'
FROM
(select geom_poly from "Buda_Parks" t1
left join (SELECT geom_point FROM "HCAD_POINTS") t2 on ST_Contains(geom_poly,geom_point)) t3
WHERE ST_Contains(geom_poly, geom_point)

Merge in postgres

Am trying to convert below oracle query to postgres,
MERGE INTO table1 g
USING (SELECT distinct g.CDD , d.SGR
from table2 g, table3 d
where g.IDF = d.IDF) f
ON (g.SGR = f.SGR and g.CDD = f.CDD)
WHEN NOT MATCHED THEN
INSERT (SGR, CDD)
VALUES (f.SGR, f.CDD);
I made changes as below compatible to postgres:
WITH f AS (
SELECT distinct g.CDD , d.SGR
from table2 g, table3 d
where g.IDF = d.IDF
),
upd AS (
update table1 g
set
SGR = f.SGR , CDD = f.CDD
FROM f where g.SGR = f.SGR and g.CDD = f.CDD
returning g.CDD, g.SGR
)
INSERT INTO table1(SGR, CDD ) SELECT f.SGR, f.CDD FROM f;
But am doubtful ,my oracle query is not updating any columns if data matched , but am unable to convert it accordingly . Can anyone help me to correct it ?
Assuming you have a primary (or unique) key on (sgr, cdd) you can convert this to an insert ... on conflict statement:
insert into table1 (SGR, CDD)
select distinct g.CDD, d.SGR
from table2 g
join table3 d ON g.IDF = d.IDF
on conflict (cdd, sgr) do nothing;
If you don't have a unique constraint (which bears the question: why?) then a straight-forward INSERT ... SELECT statement should work (which would have worke in Oracle as well).
WITH f AS (
SELECT distinct g.CDD, d.SGR
from table2 g
join table3 d on g.IDF = d.IDF
)
INSERT INTO table1 (SGR, CDD)
SELECT f.SGR, f.CDD
FROM f
WHERE NOT EXISTS (select *
from table1 t1
join f on (t1.sgr, t1.cdd) = (f.cdd, f.sgrf));
Note that this is NOT safe for concurrent execution (and neither is Oracle's MERGE statement). You can still wind up with duplicate values in table1 (with regards to the combination of (sgr,cdd)).
The only sensible way to prevent duplicates is to create a unique index (or constraint) - which would enable you to use the much more efficient insert on conflict. You should really consider that if your business rules disallow duplicates.
Note that I converted your ancient, implicit join in the WHERE clause to a modern, explicit JOIN operator, but it is not required for this to work.

Inserting values into a column based on the second table

I have two tables table1, table2. Both the tables can be joined based on empID.
I have a new column in table1 called tabseqno. I want to update tabseqno of table1 with tabseqno from table2.
UPDATE TABLE1 SET TABLE1.TABSEQNO =TABLE2.TABSEQNO
WHERE TABLE1.EMPID= TABLE2.EMPID AND TABLE2.GROUPID=99
Either:
update table1 set table1.tabseqno =
( select table2.tabseqno from table2
where table2.empid = table1.empid
and table2.groupid = 99);
or:
update table1 set table1.tabseqno =
( select table2.tabseqno from table2
where table2.empid = table1.empid
and table2.groupid = 99)
where exists
( select table2.tabseqno from table2
where table2.empid = table1.empid
and table2.groupid = 99);
depending on what you want to happen if there is no matching table2 row for a table 1 row (the first statement will set table1.tabseqno to null, the second will not update those rows at all).
Both only work if the table2 subquery can only return a maximum of 1 row for any empid.