【发布时间】:2017-08-17 22:17:15
【问题描述】:
希望一次迁移 20K 行左右。离开 SQL 超过 10 年,一直在苦苦挣扎。
我可能完全错了。需要用Table2.Value1 中的最小值更新Table1.Value2,除非已经有Value2。如果是后者,我需要插入一行,其值为Table1.Value1。
Table1.Value1 是行的每个 ID 的最小值。 Value2 必须是下一个最低值。
当前表1:
ID1, 123, [empty]
ID4, 111, [empty]
当前表2:
ID1, 224
ID1, 331
ID4, 210
ID4, 551
Table1 - 所需状态:
ID1, 123, 224
ID1, 331, [empty]
ID4, 111, 210
ID4, 551, [empty]
Table2 - 所需状态:
[empty]
这是我尝试过的,更新部分可以正常工作。插入永远不起作用。我想我把自己编码到了一个角落。
CREATE PROCEDURE dbo.Broken
AS
--DECLARE VARIABLES
DECLARE @ID INT,
@Value1 INT,
@Value2 INT,
@tmpValue INT
--DECLARE COUNTER
DECLARE @Counter INT
SET @Counter = 1
--DECLARE CURSOR FOR QUERY
DECLARE cTable1 CURSOR READ_ONLY FOR
SELECT ID,Value1, Value2
FROM Table1
OPEN cTable1
--FETCH VARIABLES
FETCH NEXT FROM cTable1 INTO @ID, @Value1, @Value2
--LOOP
WHILE @@FETCH_STATUS = 0
BEGIN
IF (@Value2 = '' OR @Value2 is NULL)
BEGIN
--UPDATE Table1.Value2 with next lowest Table1.Value2 > Table1.Value1
SET @tmpValue = (SELECT MIN(Value1) FROM Table2 WHERE Value1 > @Value1 AND ID = @ID)
UPDATE Table1
SET Value2 = @tmpValue
WHERE ID = @ID
--DELETE AFFECTED ROW FROM Table2
DELETE FROM Table2
WHERE Value1 = @tmpValue AND ID = @ID;
END
ELSE
BEGIN
--INSERT ROW IN Table1 WITH ID, Value1 FROM Table2
SET @ID = (SELECT MIN(ID) FROM Table2)
SET @tmpValue = (SELECT MIN(Value1) FROM Table2 WHERE ID = @ID)
INSERT INTO Table1(ID, Value1, Value2)
VALUES (@ID, @tmpValue, '')
DELETE FROM Table2
WHERE ID = @ID
END
--FETCH NEXT VARIABLES
FETCH NEXT FROM cTable1 INTO @ID, @Value1, @Value2
END
--CLOSE THE CURSOR TABLE
CLOSE cTable1
DEALLOCATE cTable1
大约有 20000 行,所以我希望存储过程能够完成所有工作。这是一次性的,所以我不太担心开销。
【问题讨论】:
-
如果
Table2中有另一行与ID1, 111怎么办?那么ID1, 444呢?在这些情况下,最终结果应该是什么?无论如何,思考集,而不是游标——MIN(Value) GROUP BY ID、UNION、ROW_NUMBER()、CROSS APPLY在这里应该派上用场,以便在一个表中构建结果。然后,您可以在事务中使用INSERT INTO、MERGE或单独的INSERT/UPDATE语句使Table1看起来像那个结果(然后Table2可以简单地删除其所有行)。如果您已经 10 年没有使用 SQL,那么您还记得游标的存在是一种耻辱。 :-P -
存储过程是实现您的目标所必需的吗?这可以通过使用 CASE 语句和 INSERT INTO 将表抓取到临时表来轻松完成
-
@JeroenMostert,我需要审查 MERGE,但我认为这是实现它的另一种方式。
-
@Isaiah3015,不,我绝对不喜欢使用存储过程。最初我尝试在没有的情况下构建它,但不能。
标签: sql sql-server sql-server-2008 procedure