I expect the SQL-Statement to update a limited amounts of rows, instead of every row:
UPDATE Join_Test_1
SET ANumber = 3
FROM Join_Test_1 AS ST1
INNER JOIN Join_Test_2 AS ST2
ON ST1.PKID = ST2.PKID;
I expect the statement to behave the same as the statements:
UPDATE Join_Test_1
SET ANumber = 3
FROM Join_Test_2
WHERE Join_Test_1.PKID = Join_Test_2.PKID;
UPDATE Join_Test_1
SET ANumber = 3
WHERE EXISTS (SELECT * FROM Join_Test_2 WHERE Join_Test_2.PKID = Join_Test_1.PKID);
SELECT * FROM Join_Test_1 ORDER BY PKID;
The statements using the WHERE-Clause only update the "ANumber" field where the PKID matches.
The statement using the INNER JOIN updates all fieds in the table.
Why does the INNER JOIN not limit the number of rows updated?
Can the statement with the INNER JOIN be rewritten to use the JOIN to limit the number of rows updated?
/* Expansive Example */
CREATE TABLE Join_Test_1 (PKID SERIAL,ANumber INTEGER);
CREATE TABLE Join_Test_2 (PKID SERIAL,ANumber INTEGER);
INSERT INTO Join_Test_1 (ANumber) VALUES (1),(1);
INSERT INTO Join_Test_2 (ANumber) VALUES (2);
UPDATE Join_Test_1
SET ANumber = 3
FROM Join_Test_1 AS ST1
INNER JOIN Join_Test_2 AS ST2
ON ST1.PKID = ST2.PKID; -- Updates 2
SELECT * FROM Join_Test_1 ORDER BY PKID;
-- 1, 3
-- 2, 3
UPDATE Join_Test_1 SET ANumber = 1; -- Update 2
UPDATE Join_Test_1
SET ANumber = 3
FROM Join_Test_2
WHERE Join_Test_1.PKID = Join_Test_2.PKID;
SELECT * FROM Join_Test_1 ORDER BY PKID;
-- 1, 1
-- 2, 3
UPDATE Join_Test_1 SET ANumber = 1; -- Update 2
UPDATE Join_Test_1
SET ANumber = 3
WHERE EXISTS (SELECT * FROM Join_Test_2 WHERE Join_Test_2.PKID = Join_Test_1.PKID);
SELECT * FROM Join_Test_1 ORDER BY PKID;
-- 1, 1
-- 2, 3
DROP TABLE IF EXISTS Join_Test_1;
DROP TABLE IF EXISTS Join_Test_2;
3
Answers
In
plpgSQL
there is an way to update a single table during joing as follows:Process-01: db<>fiddle – Update During joining
Process-02: db<>fiddle – Update During joining
Process-03: db<>fiddle – Normal way
You alias the table
Join_Test_1
, but you don’t call the alias in the update. That means theFROM
statement is ignored. You statement is the same asUPDATE Join_Test_1 SET ANumber = 3
.Arguably, when dealing with updates that involve multiple or complex joins and/or conditions – the most readable and maintainable way to do it is using the MERGE INTO sintax.
R e s u l t :
fiddle
Just make sure that your USING query fetches unique rows to be matched…