0

我已将问题抽象为以下情况:

我有一个表 ( 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基本上这是我想要做的,但它在 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

错误信息是

消息 4104,级别 16,状态 1,行 55 无法绑定多部分标识符“AB.Quantity”。

我有什么选择来完成这项工作?(总是有Cursor但这是一个好的选择吗?)

注意:数据有一个有趣的一面,在 SL 中有 2 次引用 A_Id = 2 的记录。这意味着结果需要更新 A_Id = 2 的 4 条 B 记录。

4

2 回答 2

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 上被出售了两次。

SQL小提琴

于 2012-11-29T11:45:13.853 回答
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

于 2012-12-05T10:49:02.403 回答