T SQL循环插入或更新

时间:2010-11-19 17:38:27

标签: sql sql-server sql-server-2005 tsql stored-procedures

我有两张桌子。

表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)

开始 - 更新 结束 其他 开始 - 插入 端

我想我需要把它放在一个循环中,并且不太确定如何让它运行。

感谢。

3 个答案:

答案 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

中不存在id

INSERT

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条件下,但您可能会明白这一点。