SQL Update values from multiple tables - sql

I have the following sql. I just want to update 2 fields from the table t1 and 1 field from t2. I tried to join the t2 but it doesnt work. Is it possible to update two tables?
And i want to update the t2.field with a const variable.
so that i get something like this
UPDATE test1_00 t1
SET (t1.field,
t1.field,
t2.field = 5)
UPDATE test1_00 t1
SET (t1.field,
t1.field,
t2.field) =
(SELECT test,
test,
test
FROM table(test_function(
02172,
'TEST',
date('2021-07-26'),
'TEST',
5455612)
)
join test1 t1 on t1.id = t2.id
where t2.test = test
and t2.test = test
);

No.
An update can only update one table at a time.

Related

SQL UPDATE table1 row-by-row based on values in table2

I have two tables and I want to UPDATE one table based on the values of another table.
With the help of the following SO-post I write a query:
query = f""" UPDATE table1
SET goal =
(SELECT table2.goal FROM table2
WHERE player = table2.player
AND opponent = table2.opponent
AND date = table2.date
AND competition = table2.competition
AND score = table2.score """
When I execute the query every row of table1 is affected with the same value for goal. However, the desired process is that the query checks row-by-row if there are matching rows and, if so, update the column goal. What am I doing wrong?
You must correlate the subquery with the table that you want to update:
UPDATE table1 AS t1
SET goal = (
SELECT t2.goal
FROM table2 AS t2
WHERE t2.player = t1.player
AND t2.opponent = t1.opponent
AND t2.date = t1.date
AND t2.competition = t1.competition
AND t2.score = t1.score
);
Or:
UPDATE table1 AS t1
SET goal = (
SELECT t2.goal
FROM table2 AS t2
WHERE (t2.player, t2.opponent, t2.date, t2.competition, t2.score) =
(t1.player, t1.opponent, t1.date, t1.competition, t1.score)
);
Note that if a row in table1 does not match any row in table2, the column will be updated to null.
If in this case you don't want the column to be updated use also COALESCE():
UPDATE table1 AS t1
SET goal = COALESCE((
SELECT t2.goal
FROM table2 AS t2
WHERE (t2.player, t2.opponent, t2.date, t2.competition, t2.score) =
(t1.player, t1.opponent, t1.date, t1.competition, t1.score)
), goal);
If your version of SQLite is 3.33.0+, you could use the UPDATE..FROM syntax:
UPDATE table1 AS t1
SET goal = t2.goal
FROM table2 AS t2
WHERE (t2.player, t2.opponent, t2.date, t2.competition, t2.score) =
(t1.player, t1.opponent, t1.date, t1.competition, t1.score);
From what I understand, this query will only affect the table1 if the table2 have the same values. Do you want to check if any row is the same then update the goal value?
Instead of using AND, you could use OR. This modification will make sure the query will go through if any of the values are similar.
query = f""" UPDATE table1
SET goal =
(SELECT table2.goal FROM table2
WHERE player = table2.player
OR opponent = table2.opponent
OR date = table2.date
OR competition = table2.competition
OR score = table2.score )"""

Updating to another Database with a lengthy IN clause

I'm trying to update certain columns from one DB to another in tables whose Id columns align.
I have the query below, but I fear it will update all rows because the IN clause values aren't being matched.
How do I match all those values within the IN clause to the relevant column from Table1? Or is this correct as is?
UPDATE Table1
SET NAME = T2.Name
FROM OTHERDB.[Table2] as T2
WHERE T2.Id in
(
'12345678'
--...
}
Your suspicions are correct: your query will update every row.
You need a join:
UPDATE T1
SET NAME = T2.Name
FROM Table1 T1
JOIN OTHERDB.Table2 as T2 ON T2.Id = T1.Id
WHERE T1.Id in (
'12345678',
...
}
This assumes that Id columns match up between databases. If that’s not the case, the join/where clauses would need adjustment.
Using an inner join means if there’s no corresponding data in the other database, there won’t be an update to null.
The where clause now looks up on the local table’s Id for efficiency.
You can try the following:
UPDATE Table1
SET Table1.Name = T2.Name
FROM OtherDB.Table2 T2
WHERE T2.Id IN
(
SELECT Id FROM Table1 (NOLOCK) WHERE ...
)

Postgres incorrect update on join

I am trying to run some update queries on Postgres where tables are joined on common field. This is run with SQL Server and the update count is 1 which is expected whereas postgres the update count is 3. It seems that postgres does not perform implicit join when the destination table is the same name as the source table involved in the join. The script could be more descript than what is being said and here it is:
drop table test;
drop table test2;
create table test(col1 int, col2 varchar(10));
insert into test values(1, 'aaa');
insert into test values(2, 'bbb');
insert into test values(3, 'ccc');
create table test2(col1 int);
insert into test2 values(2);
select * from test;
select * from test2;
// Select join = rowcount 1
select count(*) from test t2, test2 t3
where t2.col1 = t3.col1;
// SQL Server update = 1; postgres =3
update test set col2 = 'changed'
from test t2, test2 t3
where t2.col1 = t3.col1;
The above query can be simplified with:
update test set col2 = 'changed'
from test2 where test.col1 = test2.col1;
but that is not my intention as the join clause might involve some more join statements.
The desired intention was to run a query like this:
UPDATE IDMAP_CHILD_JOBID SET RESTORESUCCESS = IDMAP_TABLE_JOBID.RESTORESUCCESS, RESTOREERRMSG = IDMAP_TABLE_JOBID.RESTOREERRMSG
FROM CHILD, IDMAP_TABLE_JOBID
WHERE CHILD.ID = IDMAP_CHILD_JOBID.OLDID AND CHILD.FK1 = IDMAP_TABLE_JOBID.OLDID
AND IDMAP_TABLE_JOBID.RESTORESUCCESS = $FALSE
Postgres complains with table specified more than once if IDMAP_CHILD_JOBID is the same as IDMAP_TABLE_JOBID. How can this be rewritten?
My application is supposed to generate an update statement where this is unified query is supposed to be run whereas the behaviour is different. It is obvious that join is performed on select while it is not under update.
If you need to refer to the same table twice (or more), you need to give them different aliases, so that you can refer to each of them:
update test t1
set col2 = 'changed'
from test t2 -- <<-- same table !!
JOIN test2 t3 ON t2.col1 = t3.col1;
where t1.something =t3.something --<<-- link the target to the source
;
UPDATE idmap_child_jobid dst -- <<-- alias=dst
SET restoresuccess = src.restoresuccess
, restoreerrmsg = i.restoreerrmsg
FROM idmap_table_jobid src -- <<-- same table, different alias=src
JOIN child c ON c.fk1 = src.oldid
WHERE c.id = dst.oldid
AND dst.restoresuccess = false
;
[untested,since I don't know the table definitions,or the intentions of the query]
This is run with SQL Server
SQL-server has a slightly different syntax (and semantics) for updates, in:
UPDATE test
SET field= 'OMG'
FROM test t1
JOIN othertable t2 ON t1.field = t2.field
;
... there are ONLY TWO tables in the range-table; even though testis mentioned twice, it is the same entity) This is a Microsoft/Sybase feature.
For this SQL query:
update test
set col2 = 'changed'
from test t2, test2 t3
where t2.col1 = t3.col1;
The equivalent Postgres syntax is:
update test
set col2 = 'changed'
from test2 t3
where test.col1 = t3.col1;
The update/join syntax is different in the two databases (although I think the above will also work in SQL Server).
I am a little confused as there seems to be a difference between the Simplified Query (SQry)
2 tables: test,test2 and
Final Query (FQry)
3 tables: IDMAP_CHILD_JOBID, CHILD, IDMAP_TABLE_JOBID
To update the single row in SQry: (Note the t1 alias to hopefully prevent table specified more than once error)
update test t1
set col2 = 'changed'
from test t2, test2 t3
where t2.col1 = t3.col1
and t1.col1 = t3.col1;
So the FQry will update the rows returned from this query and if there are multiple rows in IDMAP_CHILD_JOBID which match CHILD.ID, they will all get updated.
select IDMAP_CHILD_JOBID.RESTORESUCCESS,
IDMAP_TABLE_JOBID.RESTORESUCCESS, RESTOREERRMSG,
IDMAP_TABLE_JOBID.RESTOREERRMSG
FROM IDMAP_CHILD_JOBID, CHILD, IDMAP_TABLE_JOBID
WHERE CHILD.ID = IDMAP_CHILD_JOBID.OLDID
AND CHILD.FK1 = IDMAP_TABLE_JOBID.OLDID
AND IDMAP_TABLE_JOBID.RESTORESUCCESS = $FALSE

Table update based on match/nomatch

I have two tables t1 and t2.
t1 has this structure:
yearmonth
account
company
RCV_amount_t1
t2 has this structure:
yearmonth
account
company
billing amount
billing amount CM_1
billing amount CM_2
RCV_amount_t2
I want to join t2 to t1 using yearmonth, account, and company. If they match, I want to update RCV_amount_t2 with the value in RCG_amount_t1. Otherwise, I want to set RCV_amount_t2 to spaces.
In the same manner, I want to join t1 with t2 using yearmonth, account, and company and set values accordingly.
Is it possible to achieve? If so, how do I go about it?
I want to join t2 to t1 using yearmonth, account, and company. If they
match, I want to update RCV_amount_t2 with the value in RCG_amount_t1.
Otherwise, I want to set RCV_amount_t2 to spaces.
This will update the matching rows with the appropriate value, and update the rows with no match to NULL. If the field is numeric, you can't update it to "spaces"; NULL would be the appropriate indicator of no value. If the field is not numeric, then you could do a second update to replace NULL values with whatever you like, but NULL would still seem to me to be the most appropriate indicator of no value.
UPDATE t2 SET rcv_amount_t2 = (
SELECT rcv_amount_t1
FROM t1
WHERE t1.yearmonth = t2.yearmonth
AND t1.account = t2.account
AND t1.company = t2.company
)
You'll want to use a MERGE.
It allows you to join two tables and specify how to update the values if they match.
The general structure of a MERGE statement looks like:
MERGE INTO driver_table
USING other_table
ON
(
driver_table.column1 = other_table.column1
AND driver_table.column2 = other_table.column2
AND ...
)
WHEN MATCHED THEN UPDATE
SET
driver_table.some_column = other_table.some_value,
driver_table.some_flag = 'Y',
...
;
It seems that we cannot resolve it in a single query, we need a merge and a correlated query, It works fine for me:
This will update t2 with values from t1 when matched:
MERGE INTO t2
USING (SELECT yearmonth, account, company, RCV_amount_t1 FROM t1) S
ON (t1.yearmonth = t2.yearmonth and
t1.account = t2.account and
t1.company = t2.company)
WHEN MATCHED THEN UPDATE SET t2.RCV_amount_t2 = S.RCV_amount_t1;
Then a query containg a corrolated subquery to blank when not matched:
update t2 set RCV_amount_t2 = ' ' where yearmonth||account||company not in(
select yearmonth||account||company from t1
where t1.yearmonth = t2.yearmonth and t1.account=t2.account and t1.company=t2.company);

SQL Server update statement using a join on multiple columns

Having some trouble here.
Table 1:
CID, Name, HID
(001-233, Test1, 12345)
Table 2:
CID, Name, HID, Primary
(001-233, Test1, 12345, '')
Want to update Table2 where a join exists with Table1 with a constant value called 'Y'
So statement is as follows:
UPDATE T2 SET T2.Primary = 'Y'
FROM T2
INNER JOIN T1
ON (T1.CID = T2.CID
AND T1.HID = T2.HID)
This statement just ends up updating all the rows, it's like it only does a join on one id and not the other? I finally gave up and did a WHERE IN subquery with a single "id" by concatenating the two ide fields CID+HID. But I want to understand why this didnt work using the proper join.
Table1 is a CTE..
update t2
set (t2.primary) = (select 'Y' from t1 where T1.CID = T2.CID AND T1.HID = T2.HID)