How do I add Update statement to selected rows I am about to insert into a table with MS SQL query? - sql

I have been busting my head for some time already and without any result.
Honestly I think that I need fresh eyes on this query.
I have written a query that deletes data from one table and puts it into another table. What I can't really figure out, is how to update one column for those rows I am moving, within the same query.
Here is how the query looks:
INSERT table1_archive
SELECT * FROM (
DELETE table
OUTPUT
DELETED.*
WHERE <condition1>
) AS RowsToMove;
What I want is to add also
UPDATE table1 SET <my_column> = "" WHERE <condition1>
Since it is the same condition and table for delete and update, I was thinking that it makes no sense to call two different queries to do some actions for exactly the same rows.
What I want is to clear data out of the <my_column> either before moving rows to table1_archive, or after doing so.
I guess my question is: How would I apply this update statement to the selected rows I am about to insert into the table1_archive?
ANSWER
This question becomes a little redundant as the UPDATE statement was not necessary to achieve what I wanted. I could just list all my columns in the SELECT statement and replace the <my_column> with NULL, or '''.

You can simply manipulate the column to be updated in the select statement.
INSERT INTO table1_archive
SELECT Col1,Col2...,"" AS <my_column> FROM (
DELETE table
OUTPUT
DELETED.*
WHERE <condition1>
) AS RowsToMove;

You can do this in a single statement - but it requires that you enumerate the columns.
Assuming that your tables have columns (col1, col2, col3, mycol), where mycol should be set to null when copied to the archive, you would write this as:
with del as (
delete ...
output deleted.*
where ...
)
insert into table1_archive (col1, col2, col3, mycol)
select col1, col2, col3, null
from del

and also you can try this solution
UPDATE example_table1 table1 ,
(SELECT
my_column1, my_column2
FROM example_table2
WHERE
table1.my_column3=<condition1>
) table2
SET
table1.my_column1 = table2.my_column1,
table1.my_column2 = table2.my_column2
where table1.ID = table2.ID

UPDATE table1 SET
table1.my_column1= table2.my_column1
FROM
example_table1 AS table1
INNER JOIN example_table2 AS table2
ON table1.ID = table2.ID
WHERE
table1.my_column2 = <condition1>

Related

MERGE statement to update or insert rows into a table

My task is to insert or update rows in a table2. Table1 contains id's of all employees. That id matches the ID in the table2. Some of the employees in table2 already have the rows I need but some don't. Table2 doesn't contain the ID's of the employees that don't have those rows.
My task is to update the rows for the existing ID's and insert for the ones that don't have those rows.
I have tried the following statement:
MERGE INTO dbo.table2 AS TGT
USING (SELECT table1ID FROM dbo.table1) AS SRC
ON SRC.table1ID = TGT.table2ID
WHEN MATCHED
AND table2Code = 'ValueToInsertOrUpdateCode'
THEN
UPDATE
SET table2Value= 'ValueToInsertOrUpdateValue'
WHEN NOT MATCHED BY TARGET
THEN
INSERT (table2Code, table2ID, table2Value)
VALUES ('ValueToInsertOrUpdateCode', src.table1ID, 'ValueToInsertOrUpdateValue');
This currently only updates the rows that exist, but doesn't insert the rows for ID's that don't have existing rows.
Based on your comments is sounds like you want this so that the WHEN NOT MATCHED BY TARGET is executed:
MERGE INTO dbo.table2 AS TGT
USING (SELECT table1ID FROM dbo.table1) AS SRC
ON (SRC.table1ID = TGT.table2ID AND table2Code = 'ValueToInsertOrUpdateCode') -- This is the difference
WHEN MATCHED
AND table2Code = 'ValueToInsertOrUpdateCode'
THEN
UPDATE
SET table2Value= 'ValueToInsertOrUpdateValue'
WHEN NOT MATCHED BY TARGET
THEN
INSERT (table2Code, table2ID, table2Value)
VALUES ('ValueToInsertOrUpdateCode', src.table1ID, 'ValueToInsertOrUpdateValue');
WHEN NOT MATCHED BY TARGET would not execute when SRC.table1ID = TGT.table2ID (i.e. they match).
Updating the ON clause to ON (SRC.table1ID = TGT.table2ID AND table2Code = 'ValueToInsertOrUpdateCode') will give you the inserts you are expecting.
However you should probably not do this:
ON <merge_search_condition> Caution
It's important to specify only the columns from the target table to use for matching purposes. That is, specify columns from the target table that are compared to the corresponding column of the source table. Don't attempt to improve query performance by filtering out rows in the target table in the ON clause; for example, such as specifying AND NOT target_table.column_x = value. Doing so may return unexpected and incorrect results.
For this reason and what others have suggested it would be safer to do separate update and insert statements.
I would, honestly, suggest avoiding the MERGE operator and doing an Upsert here instead. For your scenario, what you need is most likely the following:
SET XACT_ABORT ON;
BEGIN TRANSACTION;
UPDATE T2 WITH (UPDLOCK, SERIALIZABLE)
SET table2Value = 'ValueToInsertOrUpdateValue'
FROM dbo.Table2 T2
JOIN dbo.Table1 T1 ON T1.table1ID = T2.table2ID;
-- You could honestly use an EXISTS here, considering that you're updating the table
-- with a literal, rather than a value from the table Table1.
INSERT INTO dbo.Table2 (table2Code , table2ID, table2Value)
SELECT 'ValueToInsertOrUpdateCode',
T1.table1ID,
'ValueToInsertOrUpdateValue'
FROM dbo.Table1 T1
WHERE NOT EXISTS (SELECT 1
FROM dbo.Table2 T2
WHERE T2.table2ID = T1.table1ID);
COMMIT;
db<>fiddle

TSQL: Creating a duplicate table and modifying values in the column properly?

I have a master table that I wish to keep as it is. I want to duplicate this table then find a specific record with a where clause and set a column value to null. I then want to reinsert it into the duplicated table without anything getting modified in the master table.
Right now these are the steps that I have taken, however, for some reason the changes propagate all the way to the master table:
select * into Table_Duplicate from Table_Master
create view vw_Filtered as
select Col1, null as Col2 from Table_Master where Col1 = 'Condition'
update
set Table_Duplicate.Col2 = vw_Filtered.Col2
inner join vw_Filtered
on Table_Duplicate.Col1 = vw_Filtered.Col1
Once Statement 3) has been executed, when I do:
select * from Table_Master where Col1 = 'Condition'
I get the modified value in Col2 but I want to get the value before updating it.
Please do let me know if there are any other way to achieve this.
I think you're over-complicating this.
I wont pretend I know why you need to do this in the first place, but if I had to do such a thing I would probably do it like this:
SELECT Col1,
IIF(Col1 = 'Condition', null, Col2) As Col2
[,Coln]
INTO Table_Duplicate
FROM Table_Master
Then you get all the process in a single select into statement.

updating sql query value with select statement

I am trying to execute a query which is something like:
update table set column=(select column1 from table1);
I just want to store the value from other table to my column
but when i try my sql query it says
ERROR 1242 (21000): Subquery returns more than 1 row
definitely this means my table1 contains more than 1 row so i want to know that is there any way to store data into column from other table with multiple row.
or basically saving content of other table as a text something like
update table set column='Data in text from other table';
You probably need a correlation clause:
update table
set column = (select column1 from table1 where table.col = table1.col);
You need to decide what column(s) are used for the correlation.
it will work as i am getting your requirement.Please let me know if your requirement is other i ll make changes in query
update table_name t1
inner join table1 t2 on t1.id =t2.id
set column =column1
Your nested query returns multiple rows so you encountered this error.
Try in this way
UPDATE FirstTable
SET FirstTable.ColumnName =tbl2.ColumnName
FROM SecondTable tbl2 WHERE tbl2.Id = FirstTable.Id
There should be a common id or something that will help to find exact row.

How to define destination for an append query Microsoft Access

I'm trying to append two tables in MS Access at the moment. This is my SQL View of my Query at the moment:
INSERT INTO MainTable
SELECT
FROM Table1 INNER JOIN Table2 ON Table1.University = Table2.University;
Where "University" is the only field name that would have similarities between the two tables. When I try and run the query, I get this error:
Query must have at least one destination field.
I assumed that the INSERT INTO MainTable portion of my SQL was defining the destination, but apparently I am wrong. How can I specify my destination?
You must select something from your select statement.
INSERT INTO MainTable
SELECT col1, col2
FROM Table1 INNER JOIN Table2 ON Table1.University = Table2.University;
Besides Luke Ford's answer (which is correct), there's another gotcha to consider:
MS Access (at least Access 2000, where I just tested it) seems to match the columns by name.
In other words, when you execute the query from Luke's answer:
INSERT INTO MainTable
SELECT col1, col2
FROM ...
...MS Access assumes that MainTable has two columns named col1 and col2, and tries to insert col1 from your query into col1 in MainTable, and so on.
If the column names in MainTable are different, you need to specify them in the INSERT clause.
Let's say the columns in MainTable are named foo and bar, then the query needs to look like this:
INSERT INTO MainTable (foo, bar)
SELECT col1, col2
FROM ...
As other users have mentioned, your SELECT statement is empty. If you'd like to select more that just col1, col2, however, that is possible. If you want to select all columns in your two tables that are to be appended, you can use SELECT *, which will select everything in the tables.

How to append distinct records from one table to another

How do I append only distinct records from a master table to another table, when the master may have duplicates. Example - I only want the distinct records in the smaller table but I need to insert/append records to what I already have in the smaller table.
Ignoring any concurency issues:
insert into smaller (field, ... )
select distinct field, ... from bigger
except
select field, ... from smaller;
You can also rephrase it as a join:
insert into smaller (field, ... )
select distinct b.field, ...
from bigger b
left join smaller s on s.key = b.key
where s.key is NULL
If you don't like NOT EXISTS and EXCEPT/MINUS (cute, Remus!), you have also LEFT JOIN solution:
INSERT INTO smaller(a,b)
SELECT DISTINCT master.a, master.b FROM master
LEFT JOIN smaller ON smaller.a=master.a AND smaller.b=master.b
WHERE smaller.pkey IS NULL
You don't say the scale of the problem so I'll mention something I recently helped a friend with.
He works for an insurance company that provides supplemental Dental and Vision benefits management for other insurance companies. When they get a new client they also get a new database that can have 10's of millions of records. They wanted to identify all possible dupes with the data they already had in a master database of 100's of millions of records.
The solution we came up with was to identify two distinct combinations of field values (normalized in various ways) that would indicate a high probability of a dupe. We then created a new table containing MD5 hashes of the combos plus the id of the master record they applied to. The MD5 columns were indexed. All new records would have their combo hashes computed and if either of them had a collision with the master the new record would be kicked out to an exceptions file for some human to deal with it.
The speed of this surprised the hell out of us (in a nice way) and it has had a very acceptable false-positive rate.
You could use the distinct keyword to filter out duplicates:
insert into AnotherTable
(col1, col2, col3)
select distinct col1, col2, col3
from MasterTable
Based on Microsoft SQL Server and its Transact-SQL. Untested as always and the target_table has the same amount of rows as the source table (otherwise use columnnames between INSERT INTO and SELECT
INSERT INTO target_table
SELECT DISTINCT row1, row2
FROM source_table
WHERE NOT EXISTS(
SELECT row1, row2
FROM target_table)
Something like this would work for SQL Server (you don't mention what RDBMS you're using):
INSERT INTO table (col1, col2, col3)
SELECT DISTINCT t2.a, t2.b, t2.c
FROM table2 AS t2
WHERE NOT EXISTS (
SELECT 1
FROM table
WHERE table.col1 = t2.a AND table.col2 = t2.b AND table.col3 = t2.c
)
Tune where appropriate, depending on exactly what defines "distinctness" for your table.