I have this table named table1
id uniquefield field1 field2
1 11 test test2
2 12 test2 test3
and I have this value in my temp table #temp1
id uniquefield field1 field2
1 11 test test2
2 12 test2 test3
3 13 test4 test5
4 14 test5 test6
Now, what I want to happen is that I want to transfer all data from #temp1 table. It would insert if data does not exist in table1 table and would update if it exist.
Does anybody know how to do this using SQL Server or dynamic SQL?
Hope to find some response from you.
Temp tables are no different in such cases like you mentioned. The difference is they are only available to the current connection for the user; and they are automatically deleted when the user disconnects from instances. So you can handle these tables like any other SQL table and use a MERGE query to achieve this data manupulation.
Assuming the uniquefield column can be treated as link between these tables.
MERGE table1 t
USING #temp1 t1
ON t.uniquefield = t1.uniquefield
WHEN MATCHED THEN
UPDATE
SET t.id = t1.id,
t.field1 = t1.field1,
t.field2 = t1.field2
WHEN NOT MATCHED BY TARGET THEN
INSERT (id, uniquefield, field1, field2)
VALUES (t1.id, t1.uniquefield, t1.field1, t1.field2 );
You can DROP #temp1 after this and do a SELECT * FROM table1 to check the updated/ inserted data.
Assume 2 table row is identical by id, insert with not exists()
-- Append missing row to table1
INSERT table1
SELECT * FROM #temp1 t WHERE NOT EXISTS(SELECT * FROM table1 WHERE id = t.id)
Temp tables are no different in such cases like you mentioned. The difference is they are only available to the current connection for the user; and they are automatically deleted when the user disconnects from instances. So you can handle these tables like any other SQL table.
Assuming the uniquefield column can be treated as link between these tables.
Update statemant:
update table1
set
t.id = t1.id,
t.field1 = t1.field1,
t.field2 = t1.field2
from table1 t
join #temp1 t1
on t.uniquefield = t1.uniquefield
Insert statement:
insert into table1(id, uniquefield, field1, field2)
select t1.id, t1.uniquefield, t1.field1, t1.field2
from table1 t
join #temp1 t1
on t.uniquefield != t1.uniquefield
This is assuming that id is the table primary key. Otherwise replace appropriately.
UPDATE Table1
SET id= T.id,
Uniquefield = T.Uniquefield,
Field1 = T.field1,
Field2 = T.field2
FROM Table1
INNER JOIN #temp1 T ON T.id = Table1.id;
INSERT INTO Table1 (id, uniquefield, field1, field2)
SELECT id, uniquefield, field1, field2
FROM #temp1
WHERE id NOT IN (SELECT id FROM Table1)
I think the elegant way is to use MERGE here:
SET IDENTITY_INSERT table1 ON;
MERGE INTO table1 AS T
USING #temp1 AS S
ON S.id = T.id
WHEN MATCHED THEN
UPDATE SET
T.uniquefield = S.uniquefield,
T.field1 = S.field1,
T.field2 = S.field2
WHEN NOT MATCHED BY TARGET THEN
INSERT (id, uniquefield, field1, field2)
VALUES (S.id, S.uniquefield, S.field1, S.field2);
SET IDENTITY_INSERT table1 OFF;
I have added the IDENTITY_INSERT there just in case ID column in your table1 is an IDENTITY and you might want to keep the one from #temp1 table. If you dont need / have IDENTITY, just remove those lines.
you can simply use this query:-
insert into table1
select * from (
select #temp.workersID,#temp.W_name,#temp.salary,#temp.joining_year,#temp.city,#temp.id
from #temp
full join workers
on #temp.WorkersID = workers.WorkersID
where workers.WorkersID is null
) ds
Related
I have 3 tables. I'm inserting data from t1 into t2 and t3. I would like to only insert the data from t1 that is newer than the newest data already in t2.
This is my current select statement:
from (select *, concat(column1, '|', column2) as id from t1
where column1 = "value1") t
insert into table t2
select
column3,
id
insert into t3
select
column4
id
t1, t2 and t3 also contain a column "ttime", of type timestamp. I would like to modify my insert statement above to only insert data
where t1.ttime > max(t2.ttime)
How can I do this?
with subreq as (select max(time) from t2)
insert into t2 select * from t1 where t1.time>subreq.time
Just make a query with and then you can reference any column inside it for your further operations
I want to use a merge statement in pl/sql and the target table has to be updated on a particular condition. I know we can use multiple when matched condition in sql server with and operator, but i am not sure about Oracle. I am looking for that kind of feature in oracle.
create table table1 (id number, text varchar2(20));
create table table2 (id number, text varchar2(20), text2 varchar2(20));
insert into table1 values (1,'');
insert into table1 values (2,'');
insert into table1 values (3,'');
insert into table2 values (1,'a','b');
insert into table2 values (2,'a','b');
insert into table2 values (3,'a','b');
insert into table2 values (4,'a','b');
I understand you want obtain something like code below with commented line
merge into table1 t1
using table2 t2
on (t1.id = t2.id)
when matched then update set
t1.text = t2.text where t1.id = 1
--t1.text = t2.text2 where t1.id = 2
when not matched then insert values (t2.id, t2.text);
I would do that like:
merge into table1 t1
using (select id, case id when 1 then text when 2 then text2 else null end as tt, text from table2) t2
on (t1.id = t2.id)
when matched then update set
t1.text = t2.tt where t2.tt is not null
--t1.text = t2.text2 where t1.id = 2
when not matched then insert values (t2.id, t2.text);
select * from table1;
I have two tables:
table1: (ID, Code, Name)
table2: (ID, Code, Name)
with same columns
I want to to insert data from table1 to table2 or update columns if that exists in table2 (table1.ID = table2.ID)
What is the simple way to do this?
WITH OUT MERGE
Merge table2 as target
using table1 as source
on
target.id=source.id
When matched
Then
update
set target.id=source.id,
target.name=source.name
When not matched by Target Then
INSERT (id, name) VALUES (id, name);
There are some issues with Merge statement,so it should be used with caution..
Further i recommend ,using merge as two seperate DML statements like below..
insert into table2
select * from table1 t1 where not exists (select 1 from table2 t2 where t2.id=t1.id)
update t2
set
t2.id=t1.id,
t2.name=t1.name
from
table1 t1
join
table2 t2
on t1.id=t2.id
Reasons being stated by Paul White here in his detailed answer..
MERGE table2 t2
USING table1 t1
ON t1.ID = t2.ID
WHEN MATCHED THEN
UPDATE
SET t2.Code = t1.Code, t2.Name = t1.Name
WHEN NOT MATCHED BY TARGET THEN
INSERT (ID, Name, Code)
VALUES (t1.ID, t1.Name, t1.Code);
Assuming the ID column is unique and should not be set, it seems you could do it in two SQL Statements.
/* UPDATE the rows in TABLE2 */
UPDATE TABLE2
SET NAME = (SELECT NAME FROM TABLE1 WHERE TABLE1.CODE = TABLE2.CODE)
WHERE CODE IN (SELECT CODE FROM TABLE1)
/* INSERT the rows that are missing */
INSERT INTO TABLE2
(CODE, NAME)
(
SELECT CODE, NAME
FROM TABLE1
WHERE CODE NOT IN (SELECT CODE FROM TABLE2)
)
get all rows that are in table1 but not in table2
insert into table2(id, code, name)(
SELECT table1.*
FROM table1
LEFT JOIN table2 ON (table1.id = table2.id)
WHERE table2.C IS NULL
)
update table2
update table2 set name = (select name from table1 where table1.code = table2.code and table1.id = table2.id)
It might be worth looking at triggers on update and insert if you'd like to have this done manually
Inserting Date into target table once date is updated in source table
Here there is a working example:
create table Table1(id int,name varchar(100));
create table Table2(id int,name varchar(100));
create trigger Table1Trigger after insert on Table1 for each row begin
insert into Table2(id, name) values (new.id, new.name);
end;
Use the following queries to validate the results
insert into Table1 values(1,'John'),(2,'Smith'),(3,'Carol');
Here I am writing a script that use full when you want to update table2 from table1.
Update table2 set table2.code = table1.code, table2.name=table1.name from table1 where table2.id=table1.id
And if you want to insert then use this script.
Insert into table2 (id,code,name) select id,code,name from table1
If in table2 id is not auto increment.
Otherwise not insert the value of id column in table2.
I have a set of SQL queries that each is an insert statement that gets its values from other tables:
insert into table1 values (
(select tableID from Table1 where Name = 'Name1'),
(select tableID from Table2 where Name = 'Name2'),
(select tableID from Table3 where Name = 'Name3')
)
If the select statements can't find the value in the table (ie, if there is no 'Name1' in Table1), then that field becomes NULL.
Aside from changing the table design to not allow NULL's, is there a way I can modify my SQL to fail rather than insert NULL, if the nested select statements can't find the specified value?
What I would do is store the values in variables initially:
DECLARE #tableID1 INT = (SELECT tableID FROM Table1 WHERE Name = 'Name1')
Then you can do an
IF #tableID1 IS NOT NULL AND #tableID2 IS NOT NULL...
INSERT...
or alternatively an INSERT INTO table1 SELECT #tableID1 WHERE #tableID1 IS NOT NULL.
If for some reason you wanted to do it in a single messy statement you could do:
INSERT INTO table1
(select tableID from Table1 where Name = 'Name1'),
(select tableID from Table2 where Name = 'Name2'),
(select tableID from Table3 where Name = 'Name3')
WHERE EXISTS (select 1 from Table1 where Name = 'Name1'),
AND EXISTS (select 1 from Table2 where Name = 'Name2'),
AND EXISTS (select 1 from Table3 where Name = 'Name3')
A bit long winded, but this work and it should be pretty quick.
IF OBJECT_ID('tempdb..##table1') IS NOT NULL
DROP TABLE ##table1
insert into ##table1 values (
(select tableID from Table1 where Name = 'Name1'),
(select tableID from Table2 where Name = 'Name2'),
(select tableID from Table3 where Name = 'Name3')
)
insert into table1
SELECT * FROM ##table1
where tableID is not null
You could also just insert it and then,
DELETE FROM table1 where tableID is null
Use update statement
try doing
Update Table table_name set id = (select if(Name = NULL, NULL, tableID) from Table1 where Name = 'Name1')
The construct you are looking for is insert . . . select. This allows you to put a where clause on the query. Because your subqueries have to return one row, you can do a cross join, which will return at most one row:
insert into table1(id1, id2, id3)
select t1.tableID, t2.tableId, t3.tableId
from (select tableID from Table1 where Name = 'Name1') t1 cross join
(select tableID from Table2 where Name = 'Name2') t2 cross join
(select tableID from Table3 where Name = 'Name3') t3
where t1.tableID is not null and t2.tableId is not null and t3.tableId is not null;
My guess is that the where clause is unnecessary. NULL in your case is probably not the value of the table id, but represents that no row was found. A cross join on a table with no rows returns no rows, so nothing will be inserted.
Please try with in built sql function to check if inner query is returning null. For example
insert into table1 values (
IFNULL((select tableID from Table1 where Name = 'Name1'),""),
IFNULL((select tableID from Table2 where Name = 'Name2'),"")
)
Table 1:
id name desc
-----------------------
1 a abc
2 b def
3 c adf
Table 2:
id name desc
-----------------------
1 x 123
2 y 345
In oracle SQL, how do I run an sql update query that can update Table 1 with Table 2's name and desc using the same id? So the end result I would get is
Table 1:
id name desc
-----------------------
1 x 123
2 y 345
3 c adf
Question is taken from update one table with data from another, but specifically for oracle SQL.
This is called a correlated update
UPDATE table1 t1
SET (name, desc) = (SELECT t2.name, t2.desc
FROM table2 t2
WHERE t1.id = t2.id)
WHERE EXISTS (
SELECT 1
FROM table2 t2
WHERE t1.id = t2.id )
Assuming the join results in a key-preserved view, you could also
UPDATE (SELECT t1.id,
t1.name name1,
t1.desc desc1,
t2.name name2,
t2.desc desc2
FROM table1 t1,
table2 t2
WHERE t1.id = t2.id)
SET name1 = name2,
desc1 = desc2
Try this:
MERGE INTO table1 t1
USING
(
-- For more complicated queries you can use WITH clause here
SELECT * FROM table2
)t2
ON(t1.id = t2.id)
WHEN MATCHED THEN UPDATE SET
t1.name = t2.name,
t1.desc = t2.desc;
try
UPDATE Table1 T1 SET
T1.name = (SELECT T2.name FROM Table2 T2 WHERE T2.id = T1.id),
T1.desc = (SELECT T2.desc FROM Table2 T2 WHERE T2.id = T1.id)
WHERE T1.id IN (SELECT T2.id FROM Table2 T2 WHERE T2.id = T1.id);
Update table set column = (select...)
never worked for me since set only expects 1 value - SQL Error: ORA-01427: single-row subquery returns more than one row.
here's the solution:
BEGIN
For i in (select id, name, desc from table1)
LOOP
Update table2 set name = i.name, desc = i.desc where id = i.id;
END LOOP;
END;
That's how exactly you run it on SQLDeveloper worksheet. They say it's slow but that's the only solution that worked for me on this case.
Here seems to be an even better answer with 'in' clause that allows for multiple keys for the join:
update fp_active set STATE='E',
LAST_DATE_MAJ = sysdate where (client,code) in (select (client,code) from fp_detail
where valid = 1) ...
The full example is here:
http://forums.devshed.com/oracle-development-96/how-to-update-from-two-tables-195893.html - from web archive since link was dead.
The beef is in having the columns that you want to use as the key in parentheses in the where clause before 'in' and have the select statement with the same column names in parentheses.
where (column1,column2) in ( select (column1,column2) from table where "the set I want" );
BEGIN
For i in (select id, name, desc from table2)
LOOP
Update table1 set name = i.name, desc = i.desc where id = i.id and (name is null or desc is null);
END LOOP;
END;
If your table t1 and it's backup t2 have many columns, here's a compact way to do it.
In addition, my related problem was that only some of the columns were modified and many rows had no edits to these columns, so I wanted to leave those alone - basically restore a subset of columns from a backup of the entire table. If you want to just restore all rows, skip the where clause.
Of course the simpler way would be to delete and insert as select, but in my case I needed a solution with just updates.
The trick is that when you do select * from a pair of tables with duplicate column names, the 2nd one will get named _1. So here's what I came up with:
update (
select * from t1 join t2 on t2.id = t1.id
where id in (
select id from (
select id, col1, col2, ... from t2
minus select id, col1, col2, ... from t1
)
)
) set col1=col1_1, col2=col2_1, ...