SQL:更新并获取旧值和新值
SQL: Upsert and get the old and the new values
我有以下 table 项:
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?
第 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.
其实你只需要插入一个。当 ExpiryYear
和 Hash
匹配时你不想做任何事情。您只想从源插入那些列不匹配的目标。您可以使用 Merge
或 Insert
.
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 则按以下步骤操作
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
您可以如下:
-- MOCK DATA
DECLARE @Tbl TABLE
(
Id INT IDENTITY NOT NULL PRIMARY KEY,
MemberId INT,
MemberGuid CHAR(5),
ExpiryYear CHAR(4),
Hash CHAR(5)
)
INSERT INTO @Tbl
VALUES
(1, 'Guid1', '2017', 'Hash1'),
(1, 'Guid2', '2018', 'Hash1'),
(2, 'Guid3', '2020', 'Hash3'),
(2, 'Guid4', '2017', 'Hash1')
-- MOCK DATA
-- Parameters
DECLARE @FromParam INT = 1
DECLARE @ToParam INT = 2
DECLARE @TmpTable TABLE (NewDataId INT, OldDataId INT)
MERGE @Tbl AS T
USING
(
SELECT * FROM @Tbl
WHERE MemberId = @FromParam
) AS F
ON T.Hash = F.Hash AND
T.ExpiryYear = F.ExpiryYear AND
T.MemberId = @ToParam
WHEN NOT MATCHED THEN
INSERT ( MemberId, MemberGuid, ExpiryYear, Hash)
VALUES ( @ToParam, F.MemberGuid, F.ExpiryYear, F.Hash)
OUTPUT inserted.Id, F.Id INTO @TmpTable;
SELECT * FROM @TmpTable
我有以下 table 项:
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?
第 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.
其实你只需要插入一个。当 ExpiryYear
和 Hash
匹配时你不想做任何事情。您只想从源插入那些列不匹配的目标。您可以使用 Merge
或 Insert
.
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 则按以下步骤操作
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
您可以如下:
-- MOCK DATA
DECLARE @Tbl TABLE
(
Id INT IDENTITY NOT NULL PRIMARY KEY,
MemberId INT,
MemberGuid CHAR(5),
ExpiryYear CHAR(4),
Hash CHAR(5)
)
INSERT INTO @Tbl
VALUES
(1, 'Guid1', '2017', 'Hash1'),
(1, 'Guid2', '2018', 'Hash1'),
(2, 'Guid3', '2020', 'Hash3'),
(2, 'Guid4', '2017', 'Hash1')
-- MOCK DATA
-- Parameters
DECLARE @FromParam INT = 1
DECLARE @ToParam INT = 2
DECLARE @TmpTable TABLE (NewDataId INT, OldDataId INT)
MERGE @Tbl AS T
USING
(
SELECT * FROM @Tbl
WHERE MemberId = @FromParam
) AS F
ON T.Hash = F.Hash AND
T.ExpiryYear = F.ExpiryYear AND
T.MemberId = @ToParam
WHEN NOT MATCHED THEN
INSERT ( MemberId, MemberGuid, ExpiryYear, Hash)
VALUES ( @ToParam, F.MemberGuid, F.ExpiryYear, F.Hash)
OUTPUT inserted.Id, F.Id INTO @TmpTable;
SELECT * FROM @TmpTable