使用游标与 2 个表插入行

Use cursor for with 2 tables to insert rows

我有 2 个 table:itemscost

我想根据旧项目代码已经存在的成本,在新项目代码的 table 成本中创建新行。

例如:

我希望在 运行 光标位于 cost table:

后看到这个结果

我尝试 运行 这个,但它一直 运行ning 并且每行重复 100000 次:

DECLARE @item_code_old nvarchar (50)
DECLARE @item_code_new nvarchar (50)

DECLARE CostCURSOR CURSOR FOR
    SELECT item_code_old, item_code_new 
    FROM item 
    WHERE company = 'AEW' AND item_code_new IS NOT NULL

OPEN CostCURSOR 

FETCH NEXT FROM CostCURSOR INTO @item_code_old, @item_code_new

WHILE (@@FETCH_STATUS = 0)
BEGIN
    SELECT @item_code_old = item_code_old 
    FROM cost 
    WHERE company = 'AEW' AND year = 2021

    INSERT INTO cost
        SELECT
            company,
            year,
            month,
            @item_code_new,
            unit_cost
        FROM
            cost
        WHERE
            company = 'AEW' AND year = 2021

    FETCH NEXT FROM CostCURSOR INTO @item_code_old, @item_code_new
END

CLOSE CostCURSOR 
DEALLOCATE CostCURSOR

我错过了什么?

你对变量所做的事情并没有真正意义,你将下一个值提取到 @item_code_old,但随后在每个循环开始时你几乎随机地为其分配一个值:

SELECT  @item_code_old = item_code_old
FROM    cost
WHERE   company = 'AEW'
AND     year = 2021;

那么在插入新成本的时候,根本不用这个变量:

INSERT INTO cost
SELECT  company, year, month, @item_code_new, unit_cost
FROM    cost
WHERE   company = 'AEW'
AND     year = 2021;

我猜你不需要重新分配的第一步 @item_code_old,你确实需要将过滤器应用于插入查询。

话虽如此,这里完全不需要游标(您会发现游标通常是这种情况),您可以通过单个插入来完成此操作,使用如下所示:

INSERT Cost (Company, Year, Month, item_code_old, unit_cost)
SELECT  c.company, c.year, c.month, i.item_code_new, c.unit_cost
FROM    cost AS c
        INNER JOIN Item AS i
            ON c.item_code_old = i.item_code_old
WHERE   c.company = 'AEW'
AND     c.year = 2021
AND     i.item_code_new IS NOT NULL;

为了完整起见,您的光标解决方案如下所示,但我要强调这不是一个好方法。游标应该是最后的手段,它可能甚至不值得练习,因为它不是您会发现非常有用的东西。与其练习游标,不如练习尝试找到基于集合的方法,这将更好地利用您的时间。总之,吐槽一下:

DECLARE @item_code_old NVARCHAR(50);
DECLARE @item_code_new NVARCHAR(50);


DECLARE CostCURSOR CURSOR LOCAL FAST_FORWARD FOR
    SELECT  item_code_old, item_code_new
    FROM    item
    WHERE   company = 'AEW'
    AND     item_code_new IS NOT NULL;

OPEN CostCURSOR;
FETCH NEXT FROM CostCURSOR INTO @item_code_old, @item_code_new;

WHILE(@@FETCH_STATUS = 0)
BEGIN

    INSERT INTO cost (Company, Year, Month, Item_Code_Old, unit_cost)
    SELECT  company, year, month, @item_code_new, unit_cost
    FROM    cost
    WHERE   company = 'AEW'
    AND     year = 2021
    AND     item_code_old = @item_code_old;

    FETCH NEXT FROM CostCURSOR INTO @item_code_old, @item_code_new;

END;
CLOSE CostCURSOR;
DEALLOCATE CostCURSOR;