我已将问题抽象为以下情况:
我有一个表(A
),其中包含我要更新的项目编号(Quantity
)。
接下来我有一个表(SL
),其中包含我需要从中选择的表(A
)的引用。
最后需要更新的表(B
)
CREATE TABLE A
(
Id int,
Quantity int
)
CREATE TABLE SL
(
Id int,
A_Id int,
S_Id int
)
CREATE TABLE B
(
Id int,
StatusValue int,
A_Id int,
S_Id int NULL,
)
所以让我们插入一些数据用于测试目的:
INSERT INTO A Values (1, 4), (2, 2), (3, 3), (4, 4), (5, 2)
delete from B
declare @i int = 1;
declare @j int = 0;
declare @maxA int = 5;
declare @rows_to_insert int = 10;
while @i < @maxA
begin
while @j < @rows_to_insert * @i
begin
INSERT INTO B VALUES (10+@j, 0, @i, null)
set @j = @j + 1
end
set @i = @i + 1
end
select * from B
INSERT INTO SL Values (1, 1, 1), (2, 2, 1), (3 ,2, 1)
现在问题了。我想更新B
中与SL
中的记录相关的 TOP(数量)记录。基本上这就是我想要做的,但它在SQL中不受支持:
DECLARE @Sale_Id int = 1;
WITH AB (AId, AQuantity, SaleId)
AS
(
SELECT A.Id, A.Quantity, SL.S_Id FROM A
INNER JOIN SL on A.Id = SL.A_Id
WHERE SL.S_Id = @Sale_Id
)
UPDATE TOP(AB.Quantity) B
SET StatusValue = 1,
S_Id = AB.SaleId
FROM AB
WHERE StatusValue = 0 -- Edited
AND B.A_Id = AB.AId
错误消息是
Msg 4104,Level 16,State 1,Line 55 无法绑定多部分标识符“AB.Quantity”。
我有什么办法来完成这项工作?
(总是Cursor
,但这是一个不错的选择吗?)
注意:数据有一个有趣的一面,在SL中有两次记录引用A_Id = 2.这意味着结果需要有4条B记录且A_Id = 2已更新
答案 0 :(得分:1)
这应该有效
DECLARE @Sale_Id int = 1;
with tmp as (
SELECT A.Id, A.Quantity, SL.S_Id SaleID, B.S_ID, b.id b_id, B.StatusValue,
rn=dense_rank() over (partition by a.id order by b.id)
FROM A
JOIN SL on A.Id = SL.A_Id
JOIN B ON B.A_Id = A.Id
WHERE SL.S_Id = @Sale_Id
)
update tmp
set S_ID = SaleID,
StatusValue = 1
where rn <= quantity;
然而,你的数据看起来很有趣,因为A.id = 2在同一个SL.id = 1上出售两次。
答案 1 :(得分:0)
所以似乎Cursor
是我需要去的方式:
DECLARE @A_Id int, @Quantity int;
DECLARE ABCursor CURSOR LOCAL READ_ONLY FOR
SELECT A.Id, A.Quantity FROM A
INNER JOIN SL on A.Id = SL.A_Id
WHERE SL.S_Id = @Sale_Id
OPEN ABCursor
FETCH NEXT FROM ABCursor
INTO @A_Id, @Quantity
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE TOP(@Quantity) B
SET StatusValue = 1,
S_Id = @Sale_Id
WHERE StatusValue = 0
AND B.A_Id = @A_Id
AND S_Id is null
FETCH NEXT FROM ABCursor
INTO @A_Id, @Quantity
END
CLOSE ABCursor;
DEALLOCATE ABCursor;
现在必须阅读光标的最佳定义,即:LOCAL READ_ONLY