UPDATE语句未执行导致主键错误

时间:2016-05-26 16:04:35

标签: sql sql-server tsql

我有以下声明,我正在运行;

 declare @prod varchar(25)
    set @prod = (select top 1 prodref
            from dba.proditem
            where prodcateg = '84' 
            AND obsolete = 0
            AND defaultsupersededby is null
            AND charindex('/B/',proddesc) > 0
            AND salesanalysis is null 
            order by prodref asc)
    declare @cnt INT
    set @cnt = 1
    while @cnt <= (select count(prodref)
            from dba.proditem
            where prodcateg = '84' 
            AND obsolete = 0
            AND defaultsupersededby is null
            AND charindex('/B/',proddesc) > 0)
    BEGIN
      INSERT INTO dba.proditemlinks(opco_code, prodref, linked_prodref,
                                    defaultquantity,ratioquantity,linktype)
      VALUES ('C',@prod,'601110GST',100,1,3)
      INSERT INTO dba.proditemlinks(opco_code, prodref, linked_prodref,
                                    defaultquantity,ratioquantity,linktype)
      VALUES ('C',@prod,'601115GST',100,1,3)
      INSERT INTO dba.proditemlinks(opco_code, prodref, linked_prodref,
                                    defaultquantity,ratioquantity,linktype)
      VALUES ('C',@prod,'601120GST',100,1,3)
      INSERT INTO dba.proditemlinks(opco_code, prodref, linked_prodref,
                                    defaultquantity,ratioquantity,linktype)
      VALUES ('C',@prod,'601130GST',100,1,3)
      INSERT INTO dba.proditemlinks(opco_code, prodref, linked_prodref,
                                    defaultquantity,ratioquantity,linktype)
      VALUES ('C',@prod,'601140GST',100,1,3)
      INSERT INTO dba.proditemlinks(opco_code, prodref, linked_prodref,
                                    defaultquantity,ratioquantity,linktype)
      VALUES ('C',@prod,'601150GST',100,1,3)
      INSERT INTO dba.proditemlinks(opco_code, prodref, linked_prodref,
                                    defaultquantity,ratioquantity,linktype)
      VALUES ('C',@prod,'601160GST',100,1,3)
      INSERT INTO dba.proditemlinks(opco_code, prodref, linked_prodref,
                                    defaultquantity, ratioquantity,linktype)
      VALUES ('C',@prod,'601170GST',100,1,3)
      INSERT INTO dba.proditemlinks(opco_code, prodref, linked_prodref,
                                    defaultquantity,ratioquantity,linktype)
      VALUES ('C',@prod,'601179GST',100,1,3)
      INSERT INTO dba.proditemlinks(opco_code, prodref, linked_prodref,
                                    defaultquantity,ratioquantity,linktype)
      VALUES ('C',@prod,'601180GST',100,1,3)
      INSERT INTO dba.proditemlinks(opco_code, prodref, linked_prodref,
                                    defaultquantity,ratioquantity,linktype)
      VALUES ('C',@prod,'600965GST',100,1,3)
      UPDATE dba.proditem
         SET salesanalysis = 'B'
       WHERE prodref = @prod
      set @cnt = @cnt+1
    END

该声明似乎一次正常,然后第二次错误告诉我proditemlinks中的“主键”不是唯一的。 proditemlinks的主键是'opco_code','prodref','linked_prodref'。

它在第一次运行时工作正常,在第二次运行时插入行,但最后的update语句没有执行,因此它尝试再次插入最后一项,因为它没有在select语句中过滤掉

我想要实现的目标

dba.proditem创建某些新产品时,我需要在dba.proditemlinks中创建一些相关项目。我的select过滤掉了包含相关项目的产品。

由于我不能保证每次只创建一个项目,我使用select top 1并循环遍历所有行并插入所需的项目。

启用以确保我没有重复项目,我在update之后添加了insert语句,以确保在起始select语句中过滤掉该项目。

1 个答案:

答案 0 :(得分:1)

试试这个:

DECLARE @prod VARCHAR(25);

DECLARE @cnt INT;

SET @cnt=1;

WHILE @cnt <=
              (
               SELECT COUNT(prodref)
               FROM dba.proditem
               WHERE prodcateg = '84'
                     AND obsolete = 0
                     AND defaultsupersededby IS NULL
                     AND CHARINDEX('/B/', proddesc) > 0
                     AND salesanalysis IS NULL
              )
BEGIN
SET @prod=
          (
           SELECT TOP 1 prodref
           FROM dba.proditem
           WHERE prodcateg = '84'
                 AND obsolete = 0
                 AND defaultsupersededby IS NULL
                 AND CHARINDEX('/B/', proddesc) > 0
                 AND salesanalysis IS NULL
           ORDER BY prodref ASC
          );
INSERT INTO dba.proditemlinks
                             (opco_code, prodref, linked_prodref, defaultquantity, ratioquantity, linktype
                             )
VALUES
       ('C', @prod, '601110GST', 100, 1, 3
       ),
       ('C', @prod, '601115GST', 100, 1, 3
       ),
       ('C', @prod, '601120GST', 100, 1, 3
       ),
       ('C', @prod, '601130GST', 100, 1, 3
       ),
       ('C', @prod, '601140GST', 100, 1, 3
       ),
       ('C', @prod, '601150GST', 100, 1, 3
       ),
       ('C', @prod, '601160GST', 100, 1, 3
       ),
       ('C', @prod, '601170GST', 100, 1, 3
       ),
       ('C', @prod, '601179GST', 100, 1, 3
       ),
       ('C', @prod, '601180GST', 100, 1, 3
       ),
       ('C', @prod, '600965GST', 100, 1, 3
       );
UPDATE dba.proditem
       SET salesanalysis='B'
WHERE prodref = @prod;
SET @cnt=@cnt + 1;
END;

但是,如果您提供更多关于您正在尝试做什么的信息,我们可以为您提供更好的基于集合的方法。

这是我假设你想要在基于集合的方法中做的事情:

    INSERT INTO dba.proditemlinks
                             (opco_code, prodref, linked_prodref, defaultquantity, ratioquantity, linktype
                             )
       SELECT A.opco_code, B.prodref, A.linked_prodref, A.defaultquantity, A.ratioquantity, A.linktype
       FROM
           (
           SELECT 'C' opco_code, NULL prodref, '601110GST' linked_prodref, 100 defaultquantity, 1 ratioquantity, 3 linktype
           UNION ALL
           SELECT 'C', NULL, '601115GST', 100, 1, 3
           UNION ALL
           SELECT 'C', NULL, '601120GST', 100, 1, 3
           UNION ALL
           SELECT 'C', NULL, '601130GST', 100, 1, 3
           UNION ALL
           SELECT 'C', NULL, '601140GST', 100, 1, 3
           UNION ALL
           SELECT 'C', NULL, '601150GST', 100, 1, 3
           UNION ALL
           SELECT 'C', NULL, '601160GST', 100, 1, 3
           UNION ALL
           SELECT 'C', NULL, '601170GST', 100, 1, 3
           UNION ALL
           SELECT 'C', NULL, '601179GST', 100, 1, 3
           UNION ALL
           SELECT 'C', NULL, '601180GST', 100, 1, 3
           UNION ALL
           SELECT 'C', NULL, '600965GST', 100, 1, 3
           ) AS A
       CROSS JOIN
       (
        SELECT prodref
        FROM dba.proditem
        WHERE prodcateg = '84'
              AND obsolete = 0
              AND defaultsupersededby IS NULL
              AND CHARINDEX('/B/', proddesc) > 0
              AND salesanalysis IS NULL
        ORDER BY prodref ASC
       ) AS B;

UPDATE dba.proditem
       SET salesanalysis='B'
WHERE salesanalysis IS NULL;