update one table with data from another using the common key
create table table1 (
id varchar2(4),
name varchar2(10),
desc_ varchar2(10)
)
create table table2 (
id varchar2(4),
id_new varchar2(4)
)
insert into table1 values('1111', 'a', 'abc')
insert into table1 values('2222', 'b', 'def')
insert into table1 values('3333', 'c', 'ghi')
insert into table1 values('4444', 'd', 'jkl')
insert into table2 values('1111', '8080')
insert into table2 values('2222', '9090')
merge into table1 t1
using (select * from table2) t2
on (t1.id = t2.id)
when matched then update set t1.id = t2.id_new
error: ORA-27432: step does not exist for chain .
This should work:
update table1 t1
set id = coalesce((
select id_new
from table2 t2
where t1.id = t2.id), id);
SQL Fiddle Demo
Here's an alternative approach with merge:
merge into table1 t1
using (select * from table2) t2
on (1 = 1)
when matched then update set t1.id = t2.id_new where t1.id = t2.id
More Fiddle
Probably best speed you'll obtain using:
merge into table1 t1
using (select t1.rowid rw, t2.id_new
from table2 t2
join table1 on (table1.id = t2.id)
) s
on t1.rowid = s.rowid
when matched then update set t1.id = s.id_new;
However it depends on optimizer(previous answers may have a good behavior if CBO intuits your desire)
Related
I have test table(1) with following values
Yet I have an update of this table called table(2) :
As you can see table(2) is similar table(1) but it has new values with new dates for each ID.
How should I use update command to update table1 based on new values of table2
In sql the fastest way to do so via a merge function, it will add the new rows to the table1 that are existing in table2 and not in table1.
merge into table1 t1
using table2 t2
on t1.id = t2.id
and t1.date = t2.date
when not matched then
insert (t1.id, t1.date, t1.value1, t1.value2 , t1.value3, t1.value4)
values (t2.id, t2.date, t2.value1, t2.value2 , t2.value3, t2.value4)
What I understood from your question is that you have multiple records for each id in table2 and you want the values against the latest row based on the data to be updated to table1. in such a case, you can try with a ROW_NUMBER or RANK function, just like this
;WITH CTE
AS
(
SELECT
RN = ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Date DESC),
id,
date,
val1,
val2,
val3
FROM Table2
)
UPDATE T1
SET
Val1 = T2.Val1
Val2 = T2.Val2
FROM Table1 T1
INNER JOIN CTE T2
ON T1.id = T2.id
WHERE T2.RN = 1
I tried this query and i get this msg SQL Error: ORA-00933: SQL command not properly ended ,but i can't see where the problem realy is ?
update T1 set T1.name=T2.name from Table1 T1
inner join Table2 T2
on T1.id=T2.id where T2.id in (select id from Table2 group by id having count(entity)=1);
Your statement is not valid Oracle syntax.
You have two common options.
Option #1: use a correlated subquery in your UPDATE...
update table t1
set t1.name = ( SELECT t2.name
FROM table2 t2
WHERE t2.id = t1.id
AND t2.id IN ( SELECT t2a.id
FROM table2 t2a
GROUP BY t2a.id
HAVING COUNT(t2a.entity) = 1 )
)
where exists ( SELECT 'x'
FROM table2 t2
WHERE t2.id = t1.id
AND t2.id IN ( SELECT t2a.id
FROM table2 t2a
GROUP BY t2a.id
HAVING COUNT(t2a.entity) = 1 )
;
Option #2: (my preference) use a MERGE statement:
merge into table1 t
using ( SELECT t2.id,
t2.name,
COUNT(t2.entity) OVER ( PARTITION BY t2.id ) entity_count
FROM table2 t2
) u
ON ( t.id = u.id AND u.entity_count = 1 )
WHEN MATCHED THEN UPDATE SET t.name = u.name;
I usually test SQL before I post it, but no time today. So, there might be syntax errors in the above.
I would phrase the update as:
update table t1
set t1.name = (select t2.name
from table2 t2
where t2.id = t1.id and rownum = 1
)
where (select count(t2.entity)
from table2 t2
where t2.id = t1.id
) = 1;
I'm not sure if I understood the data context. I created an example where ID's aren't UNIQUE
create table T1 ( name varchar2(55), id number(4,0), entity number(2,0));
create table T2 ( name varchar2(55), id number(4,0), entity number(2,0));
insert into T1 (name, id, entity) values ('T1name1', 1, 1);
insert into T1 (name, id, entity) values ('T1name2', 2, 1);
insert into T1 (name, id, entity) values ('T1name3', 3, 3);
insert into T1 (name, id, entity) values ('T1name4', 4, 4);
insert into T2 (name, id, entity) values ('T2name1', 1, 1);
insert into T2 (name, id, entity) values ('T2name2', 2, 1);
insert into T2 (name, id, entity) values ('T2name3', 3, 3);
insert into T2 (name, id, entity) values ('T2name4', 3, 1);
update T1 set name =
nvl(
( select name
from T2
where T2.id = T1.id
and exists
( select 'x'
from T2 table2
where table2.id = T2.id
group by id
having count(entity) = 1)
)
,T1.name)
In this context, just T1.id = 1 and T1.id = 2 will be updated (T2.id = 3 has count(entity) = 2)
I have table1 and table2. They have the same columns and the column ID is the one that i can use to connect the tables.
How can i run foreach statment that will update row Name in table1 with the value for column Name in table2?
I need this so i can fix the column Name in Table1 because it is incorect , and the good values for it are in table2
I tried using a single update statement but it takes forever to execute because both tables are with over 600 000 rows
update
table1 t1
set
(
t1.name
) = (
select
t2.name
from
table2 t2
where
t2.id = t1.id
and
rownum = 1
)
where exists (
select
null
from
table2 t2
where
t2.id = t1.id
);
For this query:
update table1 t1
set t1.name = (select t2.name from table2 t2 where t2.id = t1.id and rownum = 1)
where exists (select 1
from table2 t2
where t2.id = t1.id
);
You want an index on table2(id, name).
A simple inner join should work this.
UPDATE T1
SET T1.NAME = T2.NAME
FROM MyTable T1
INNER JOIN MyOtherTable T2
ON T1.ID = T2.ID
I want to insert an id that i created into an update of each row:
UPDATE TABLE1
SET NAME=(INSERT INTO TABLE2(EVT01,EVT02) values(0,0)
SELECT #id=SCOPE_IDENTITY() )
FROM TABLE1
INNER JOIN TABLE2 ON ......
How can i make that in SQL Server?
Thanks.
You can create an Insert Trigger on Table2 to Update Table1 using Inserted table:
CREATE TRIGGER [dbo].[YourTriggerName]
ON [dbo].[Table2]
AFTER INSERT
AS
BEGIN
UPDATE t1
SET NAME= t2.IdColName
FROM Table1 t1
INNER JOIN Inserted t2 ON ......
END
Declare #NewId Int
INSERT INTO TABLE2(EVT01,EVT02) values(0,0)
Select #NewId = ##Identity
UPDATE t1
SET t1.NAME = t2.Name
FROM TABLE1 As t1
Join TABLE2 As t2 On t1.somecolumn = t2.Id
Where t2.Id = #NewId
Edit:-
----- Table SourceTable
Insert Into TABLE2(EVT01,EVT02)
Select Col1
,Col2
From SrouceTable
Update t1
Set t1.Name = t2.Id
From TABLE1 As t1
Join TABLE2 As t2 On t1.Somecolumn = t2.Id
Join SourceTable As st On t2.EVT01 = Col1 ----Assumed there would be unique matching column
How can I prevent inner SELECT from returning NULL (when matches no rows) and force query to fail.
INSERT INTO tt (t1_id, t2_id) VALUES (
(SELECT id FROM t1 WHERE ...),
(SELECT id FROM t2 WHERE ...)
);
Side question: is there better way form this query (t1_id, t2_id are foreign keys, but might be NULL) ?
How about something like:
INSERT INTO tt (t1_id, t2_id)
SELECT t1.id, t2.id FROM t1, t2 WHERE ...
Just make sure the SELECT returns exactly what you want to INSERT - so if it's possible for t1.id and t2.id to be NULL then include the relevant clause in your WHERE condition (... AND t1.id IS NOT NULL AND t2.id IS NOT NULL ...).
You may also prefer to use SELECT DISTINCT if there's a chance of duplicate rows appearing.
Edit: If you need 2 IDs from different rows of the same table:
SELECT t1.id, t2.id FROM some_table AS t1, some_table AS t2
WHERE ...
INSERT INTO tt (t1_id, t2_id) VALUES (
(SELECT id FROM t1 WHERE ...),
(SELECT id FROM t2 WHERE ...)
)
WHERE EXISTS (SELECT id FROM t1 WHERE ...)
AND (SELECT id FROM t2 WHERE ...)
It may seem awkward and redundant but any SQL executor worth its salt won't execute each part twice.
Alternatively if t1 and t2 are related somehow:
INSERT INTO tt (t1_id, t2_id)
SELECT t1.id, t2.id
FROM t1
JOIN t2 ON ...
WHERE ...
This can be enhanced and used as given below
INSERT INTO tt (t1_id, t2_id)
select distinct t1.id,t2.id
from t1,t2
where t1.id=t2.id
and t1.id is not null
and t2 id is not null
);