我有两张桌子。
表A和表B.列是相同的。
create table TableA (
id int
, name varchar
, last datetime
)
create table TableB (
id int
, name varchar
, last datetime
)
我用大量数据填充表A.我想将表A中的数据插入或更新到表B中。
我想从表A中获取数据,如果id和name doenst匹配则插入到表B中,如果id和name匹配则更新。
我尝试了一些ETL工具但结果非常慢。我有id和name的索引,我想用SQL尝试这个。
我有以下但不正确的工作:
SELECT @id = ID,
@name = name,
@LSDATE = LastSeen_DateTime
FROM DBO.A
IF EXISTS (SELECT ID, name FROM DBO.A
WHERE @ID = ID AND @name = Name)
开始 - 更新 结束 其他 开始 - 插入 端
我想我需要把它放在一个循环中,并且不太确定如何让它运行。
感谢。
答案 0 :(得分:6)
它可能更快做两个语句一个更新和一个插入而不是循环
此语句使用A中的数据更新所有B行,其中ID相同但名称不同
<强>更新强>
Update
tableB
SET
name = a.Name
From
tableB a
INNER JOIN tableA a
on b.ID = a.ID
and A.Name <> b.Name
此语句将所有B行插入A,其中A
中不存在idINSERT
INSERT INTO
tableB
( ID,
Name
)
SELECT
a.ID
a.Name
FROM
tableA b
WHERE
not exists (Select A.ID From tableB a WHERE a.ID = b.ID)
更新了(将其从A转换为B而不是B转换为A)
答案 1 :(得分:6)
如果您使用的是SQL Server 2008(或Oracle或DB2),则可以使用合并语句。
MERGE B
USING A AS source
ON (B.ID = source.ID and B.Name = source.Name)
WHEN MATCHED THEN
UPDATE SET Last = source.Last
WHEN NOT MATCHED BY TARGET THEN
INSERT (ID, Name, Last) VALUES (source.ID, source.Name, source.Last)
-- the following is optional, if you remove it, add a semicolon to the end of the above line.
OUTPUT $action,
inserted.ID AS SourceID, inserted.Name AS SourceName,
inserted.Last AS SourceLast,
deleted.ID AS TargetID, deleted.Name AS TargetName,
deleted.Last AS TargetLast ;
带有“output $ action”的位将显示哪些行正在更新以及哪些行正在更新。
狡猾的话:我认识到这不是完全您正在寻找的内容,但由于其他人可能会搜索此主题,因此将来可能对其他人有所帮助。
答案 2 :(得分:2)
DECLARE @id int
DECLARE @name nvarchar
DECLARE @last datetime
DECLARE TableA_Cursor CURSOR FOR
select id
, name
, last
from TableA;
OPEN TableA_Cursor;
FETCH NEXT from TableA_Cursor
INTO @id, @name, @last;
WHILE @@FETCH_STATUS = 0
BEGIN
IF (EXISTS select 1 from TableB b where b.Id = @id)
update TableB
set Name = @name
, Last = @last
ELSE
insert into TableB (Id, Name, Last)
values (@id, @name, @last)
FETCH NEXT from TableA_Cursor
INTO @id, @name, @last
END
CLOSE TableA_Cursor;
DEALLOCATE TableA_Cursor;
可能存在一些语法错误,尤其是在IF
条件下,但您可能会明白这一点。