SQL:Upsert并获取旧值和新值

时间:2016-11-03 09:15:01

标签: sql sql-server tsql upsert sql-merge

我有下表项目:

Id          MemberId          MemberGuid        ExpiryYear         Hash    
--------------------------------------------------------------------------- 
1           1                 Guid1             2017               Hash1
2           1                 Guid2             2018               Hash2
3           2                 Guid3             2020               Hash3
4           2                 Guid4             2017               Hash1

我需要将项目从成员复制到另一个成员(不仅仅是更新MemberId,还要插入新记录)。规则是:如果我想将所有项目从一个成员迁移到另一个成员,我将不得不检查新成员中该项目是否存在。

例如,如果我想将项目从成员1移动到成员2,我将仅移动ID为2的项目,因为我已经在成员2处有一个具有相同哈希值和相同到期年份的项目(这个是插入新项目之前需要检查的列。

如何编写一个查询,只将不存在的项目从一个成员迁移到另一个成员,并获取旧ID和记录的新ID?不知何故有一个upsert?

3 个答案:

答案 0 :(得分:0)

第1步:

Get in cursor all the data of member 1

第2步:

 While moving through cursor.
        Begin
        select hash, expirydate from items where memberid=2 and hash=member1.hash and expirydate=member1.expirydate

第3步

If above brings any result, do not insert.

       else insert.        

希望这有帮助

注意:这不是实际代码。我正在为您提供基于您可以编写sql的步骤。

答案 1 :(得分:0)

其实你只需要一个插页。当ExpiryYearHash匹配时,您不想做任何事情。您只想从源到目标插入那些列不匹配的目标。您可以使用MergeInsert

执行此操作
CREATE TABLE YourTable
(
    Oldid INT,
    OldMemberId INT,
    Id INT,
    MemberId INT,
    MemberGuid CHAR(5),
    ExpiryYear CHAR(4),
    Hash CHAR(5)
)   

INSERT INTO YourTable VALUES

(null, null, 1, 1, 'Guid1', '2017', 'Hash1'),
(null, null, 2, 1, 'Guid2', '2018', 'Hash2'),
(null, null, 3, 2, 'Guid3', '2020', 'Hash3'),
(null, null, 4, 2, 'Guid4', '2017', 'Hash1')

DECLARE @SourceMemberID AS INT = 1
DECLARE @TargetMemberID AS INT = 2

MERGE [YourTable] AS t
USING
(
    SELECT * FROM [YourTable]
    WHERE MemberId = @SourceMemberID
) AS s
ON t.Hash = s.Hash AND t.ExpiryYear = s.ExpiryYear AND t.MemberId = @TargetMemberID
WHEN NOT MATCHED THEN
    INSERT(Oldid, OldMemberId, Id, MemberId, MemberGuid, ExpiryYear, Hash) VALUES (s.Id, s.MemberId, (SELECT MAX(Id) + 1 FROM [YourTable]), @TargetMemberID, s.MemberGuid, s.ExpiryYear, s.Hash);

SELECT * FROM YourTable

DROP TABLE YourTable

/* Output:
Oldid   OldMemberId Id  MemberId    MemberGuid  ExpiryYear  Hash
-----------------------------------------------------------------
NULL    NULL        1   1           Guid1       2017        Hash1
NULL    NULL        2   1           Guid2       2018        Hash2
NULL    NULL        3   2           Guid3       2020        Hash3
NULL    NULL        4   2           Guid4       2017        Hash1
2       1           5   2           Guid2       2018        Hash2

如果您只想选择,请执行以下操作

SELECT null AS OldID, null AS OldMemberID, Id, MemberId, MemberGuid, ExpiryYear, Hash FROM YourTable
UNION ALL
SELECT A.Id AS OldID, A.MemberId AS OldMemberID, (SELECT MAX(Id) + 1 FROM YourTable) AS Id, @TargetMemberID AS MemberId, A.MemberGuid, A.ExpiryYear, A.Hash
FROM YourTable A
LEFT JOIN
(
    SELECT * FROM YourTable WHERE MemberId = @TargetMemberID
) B ON A.ExpiryYear = B.ExpiryYear AND A.Hash = B.Hash
WHERE A.MemberId = @SourceMemberID AND B.Id IS NULL

答案 2 :(得分:0)

您可以如下所示:

{{1}}