我希望根据包含更新详细信息的表 Y 更新表 X 中的记录。困难在于
假设 X = materials(id, type_id, status, data)
; Y=material_updates(run_id, type_id, quantity, data)
(id
只是一个内部主键字段)
然后我想做的是(相当于)循环一个简单的查询,比如
SELECT *
FROM material_updates
WHERE run_id = :run;
Run Code Online (Sandbox Code Playgroud)
对于每个row
结果集,应用类似的东西
UPDATE TOP(row.quantity) materials
SET data = row.data, status = 1
WHERE status = 0 AND type_id = row.type_id;
Run Code Online (Sandbox Code Playgroud)
status
(在我试图解决的问题中,的变化恰好是恒定的)
样本数据
材料_更新表:
run_id type_id quantity data
1 1 3 42
1 2 2 69
1 2 1 105
Run Code Online (Sandbox Code Playgroud)
更新前的材料表:
type_id status data
1 1 17
1 1 17
1 0 0
1 0 0
1 0 0
1 0 0
2 0 0
2 0 0
2 0 0
2 0 0
Run Code Online (Sandbox Code Playgroud)
更新后的材料表:
type_id status data
1 1 17
1 1 17
1 1 42
1 1 42
1 1 42
1 0 0
2 1 69
2 1 69
2 1 105
2 0 0
Run Code Online (Sandbox Code Playgroud)
我认为可以使用光标来完成,但这是最好的解决方案,还是有更有效的方法?
这对于CURSOR(msdn 链接)来说是完美的,它允许您逐行迭代查询结果并为每个结果执行操作。
这是一个关于它的很好的教程。
这段代码可以解决您的需求:
-- the best fit for this code would be a Stored Procedure with one parameter
-- which is the run_id value you want.
-- error checking omitted for brevity
DECLARE CURSOR theCursor
FOR SELECT type_id, quantity, data FROM material_updates WHERE run_id = @run_id;
DECLARE @type_id int; -- types should match your material_updates fields
DECLARE @quantity int;
DECLARE @data int;
OPEN theCursor;
FETCH NEXT FROM theCursor INTO @type_id, @quantity, @data;
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE TOP(@quantity) materials
SET data = @data, status = 1
WHERE status = 0 AND type_id = @type_id;
END;
CLOSE theCursor;
DEALLOCATE theCursor;
Run Code Online (Sandbox Code Playgroud)
另一个解决方案是使用UPDATE FROM (所以已经有有关它的信息),但我不知道有什么方法可以让它更新特定数量的行。它很可能无法做到这一点。
但请注意,您最终得到的数据没有任何意义,因为没有顺序:您永远不会知道哪些行将被更新/已经被更新。