asm*_*mgx 1 sql t-sql sql-server
我有 2 个表:Tags 和 TagsTemp。
标签有数百万行,而标签临时有数千行。
它们都是物理表。
两个表中的主键是 ID,它是自动 ID(因此 ID 的编号不同,它们不匹配)。
我必须将所有数据从 TagsTemp 移动到标签。
那很简单。我这样做了:
BEGIN TRANS
INSERT INTO Tags (C1, C2, C3)
SELECT C1, C2, C3 FROM TagsTemp
DELETE FROM TagsTemp
COMMIT
Run Code Online (Sandbox Code Playgroud)
问题在于,TagsTemp 可能在此事务期间(在插入和删除语句之间的时间内)有新记录。
我不想删除包含未插入记录的表。
我在想这样的事情:
BEGIN TRANS
INSERT INTO @T (ID, C1, C2, C3)
SELECT ID, C1, C2, C3 FROM TagsTemp
INSERT INTO Tags (C1, C2, C3)
SELECT C1, C2, C3 FROM @T
DELETE FROM TagsTemp
WHERE ID IN (SELECT ID FROM @T)
COMMIT
Run Code Online (Sandbox Code Playgroud)
但这似乎不是最好的方法和糟糕的表现。
有没有更好的解决方案来做到这一点?
注意:我无法更改表结构。
对于几千行,我认为您的解决方案非常好,但只是为了让您知道另一种方法,您可以MAX(ID)从表中获取然后使用它,假设您的自动 ID 正在递增整数:
BEGIN TRAN;
DECLARE @MaxId INT;
SELECT @MaxId = MAX(ID) from TagsTemp;
INSERT INTO Tags (C1, C2, C3)
SELECT C1, C2, C3
FROM TagsTemp
WHERE ID <= @MaxId;
DELETE
FROM TagsTemp
WHERE ID <= @MaxId;
COMMIT;
Run Code Online (Sandbox Code Playgroud)
PS:不确定你的END TRANS- 我想你的意思是COMMIT?
受Bart Hofland的启发,您实际上可以捕获插入期间正在传输的记录的 ID,只要您使用语句MERGE作为插入,如下所示:
DECLARE @IDs TABLE (ID INT PRIMARY KEY);
BEGIN TRAN;
MERGE Tags target
USING TagsTemp source
ON 0 = 1
WHEN NOT MATCHED THEN
INSERT (C1, C2, C3) VALUES (source.C1, source.C2, source.C3)
OUTPUT source.id INTO @IDs;
DELETE
FROM TagsTemp
WHERE ID IN (SELECT ID FROM @IDs);
COMMIT;
Run Code Online (Sandbox Code Playgroud)
当您的标准不基于自动递增标识列时,这可以提供更灵活的方法。
| 归档时间: |
|
| 查看次数: |
138 次 |
| 最近记录: |