UPDATE to multiple tables with one WHERE clause - sql

I need to update two tables with the same WHERE clause. The WHERE clause has hundreds of IDs so I want to avoid writing it twice like this...
UPDATE TABLE1
SET (values...)
WHERE ID in (list of IDs)
UPDATE TABLE2
SET (values...)
WHERE ID in (list of IDs) -- this is the same statement as above
Is there a way to merge these with one WHERE statement?

SQL Server does not support multi-table updates.
You can, however, put these ids in a table, that you can then use in your queries.
create table id_table (id int); -- or whathever datatype you need
insert into id_table (id) values (1), (2), ...; -- list of ids
Then:
update t
set ...
from table1 t
where exists (select 1 from id_table i where i.id = t.id)

You can't really do this in SQL Server. Your best bet is to create a temporary table:
select *
into toupdate
from values ( . . . ) v(id)
Then you can use this in the delete statements:
update table1
set . . .
where id in (select id from toupdate);

Related

Equivalent for Merge with output clause in SQL Server to Postgresql

I want to insert values based on below code to a temporary table in postgresql
declare #output table (AuditScratchID bigint, AuditID bigint);
merge table atb
using (select
s.ID
....
....
....
from #temporaryTableVariable s
inner join ....
...............
..............
) as s
on 1 = 2 -- Impossible Condition so they never match
when not matched then
insert (.....)
values (.....)
output s.ID, inserted.ID
into #output;
Just to mention, how can I correlate values into temporary table
I don't understand the use of MERGE to begin with.
This seems like a straightforward insert ... select. To see the inserted rows, use the returning clause
insert into atb (...)
select ... columns ...
from some_table
join other_table on ...
returning *

Using SELECT from RETURNING while UPDATE in PostgreSQL

I have two tables T1,T2 I have to add the column id of T1 in T2 and update a value in T1.
So I am able to get the values from T2 using RETURNING,but when using values in UPDATE WHERE then not able to UPDATE the column
Example:
WITH "T1S" AS (INSERT INTO "T1" VALUES()RETURNING id AS "T1id" ),
"T2S" AS (INSERT INTO "T2"(t1_id) VALUES(
(SELECT "T1id" FROM "T1S"))
)RETURNING t1_id AS "T1id",t2_id AS "T2id"
)
UPDATE "T1" set value=t2_id WHERE id IN (SELECT t1_id FROM "T2S")
Image of query
If I understand correctly, this is the logic that you want:
WITH T1S AS (
INSERT INTO "T1"
VALUES ()
RETURNING id AS T1id
),
T2S AS (
INSERT INTO "T2" (t1_id)
SELECT T1ID
FROM T1S
RETURNING *
)
UPDATE "T1" t1
SET value = T2S.t2_id
FROM T2S
WHERE t1.id = T2S.t1_id;
Notes:
Using double quotes for table and column names is a bad practice. Using them for CTEs and column aliases is an absurdity. They just make references harder.
The solution is that you want the join the table to the CTE in the final UPDATE.

Dynamically storing values in SQL table

I'm trying to dynamically create a variable or table in SQL which will store distinct values as a result for another sql query.
declare sample_table table
( values varchar(100))
insert into #sample_table values (select t1.value from my_tablw as t1 group by t1.value);
Supposing the distinct values in column value can change from table query to another table query, I want to store the result of this query in a user defined variable/table which can be used later in another query.
Depending on your definition of can be used later you can use a local temp table or table variable.... you just need to change the syntax a bit to not use the values since you are inserting from the results of a query. I also used DISTINCT below which is clearer than the GROUP BY without an aggregate function.
declare sample_table table ([values] varchar(100))
insert into #sample_table
select distinct t1.value
from my_tablw as t1
--one way to use it
select *
from newTable
where columnVal in (select * from #sample_table)
--another way to use it
select at.*
from anotherTable at
inner join #sample_table t on
t.column = at.column
--and another way...
select f.*
from finalTable f
where exists (select * from #sample_table t where t.column = f.column)
If you need this to be used outside the scope of your current batch, you'll need to use a persisted table or global temporary table.

Insert a records count into a different table

I need to write the count of all records in one table into another. I am using an INSET INTO statement, it seems pretty straightforward. Access returns that I am making a syntax mistake. Here is my query:
INSERT INTO tblA (Field1)
VALUES (SELECT COUNT(tblB.ID) FROM tblB);
What is the problem here? Access documentation says you are allowed to give a query as argument for VALUES. Is it the aggregation that Access doesn't like?
I would do it with insert . . . select as Tim recommends. But, I want to explain what is wrong with your syntax.
The syntax for insert . . . values is:
insert into tblA(field1)
values ( . . . );
Notice the parentheses. In addition, a subquery always needs to have its own parentheses. So, to make your version work, you need an extra set of parentheses:
INSERT INTO tblA (Field1)
VALUES ( (SELECT COUNT(tblB.ID) FROM tblB) );
Use INSERT INTO...SELECT:
INSERT INTO tblA (Field1)
SELECT COUNT(tblB.ID) FROM tblB
this the easy way we can use COALESCE, i hope it's usefull
SELECT
table1.id,
COALESCE(table2_count, 0) AS table2_count,
COALESCE(table3_count, 0) AS table3_count
FROM users
LEFT JOIN (
SELECT id, COUNT(*) AS table2_count
FROM table2
GROUP BY id
) table2_counts ON table2_counts.id = table1.id
LEFT JOIN (
SELECT id, COUNT(*) AS table3_count
FROM table3
GROUP BY id
) table3_counts ON table3_counts.id = table1.id

SQL update statement with different table in from clause

Out of accident I noticed that the following query is actually valid:
UPDATE bikes
SET price = NULL
FROM inserted
WHERE inserted.owner_id = 123456
This is part of a trigger where someone forgot to join the original table to the inserted table. The result is that when the trigger is executed, all prices are set to NULL.
The correct SQL statement is this:
UPDATE bikes
SET price = NULL
FROM inserted
INNER JOIN bikes ON bikes.id=inserted.id
WHERE inserted.owner_id = 123456
How/why is this first statement valid?
Why wouldn't it be valid? SQL Server doesn't know what you're trying to do. It thinks you want to update all of the fields where some condition exists on another table. See the last update below.
SETUP
declare #table table
(
id int,
name varchar(10)
)
declare #itable table
(
id int,
name varchar(10)
)
insert into #table (id, name)
select 1,'abc' union
select 2,'def' union
select 3,'ghi' union
select 4,'jkl' union
select 5,'mno' union
select 6,'pqr'
insert into #itable (id, name)
select 1,'abc' union
select 2,'def' union
select 3,'ghi' union
select 4,'jkl' union
select 5,'mno' union
select 6,'pqr'
All names on #table will change to zzz
update #table
set name = 'zzz'
from #itable i
where i.id = 1
select * from #itable
select * from #table
All names where id = 1 on #table becomes yyy
update #table
set name = 'yyy'
from #itable i
inner join #table t on i.id = t.id
where i.id = 1
select * from #itable
select * from #table
This will NOT update anything
update #table
set name = 'aaa'
from #itable i
where i.id = 133
select * from #itable
select * from #table
The first statement does not work as expected because it is missing the entire INNER JOIN line with the bikes and inserted table. Without that SQL Server will update all rows as all rows will qualify for an update when the inserted.owner_id = 123456.
You can reproduce this outside of the trigger in TSQL like :
update bikes set price =null
from SomeOtherTable
where SomeOtherTable.SomeColumn = 'some_value_that_exists'
This is syntactically valid statement in SQL Server. If the Intention is to update bikes table based on existance of a row in some unrelated table that cant be joined because the 2 tables arent related then this is how you would do it. But that is not your requirement. Hence why it updates all records instead of only those that match the bikes.id In programming terms this is called as a logical bug.
The inner join makes it more restrictive and forces to to update only those rows that match the join condition between the 2 tables (bikes.id=inserted.id comparison )
In Simple terms the from clause is optional..Consider below query..
update table
set id=10
This has one table right after update clause ,sql just updates it..
now consider below query..
update table1
set id=40
from table2..
What do you think SQL does,it updates all the rows same as first query..
unless you refer to another table in from clause and join like below
update t1
set t1.id=40
from
table1 t1
join
table2 t2
on t1.id=t2.id
below is the from clause explanation in update syntax stripped down to show only to relevant parts..
If the object being updated is the same as the object in the FROM clause and there is only one reference to the object in the FROM clause, an object alias may or may not be specified. If the object being updated appears more than one time in the FROM clause, one, and only one, reference to the object must not specify a table alias. All other references to the object in the FROM clause must include an object alias
As long as above rules are valid (as in your case),SQL will happily update table found immediately after update clause