【问题标题】:SQL : Update if exists with stored procedureSQL:如果存在,则使用存储过程更新
【发布时间】:2014-02-20 09:02:11
【问题描述】:

我需要一些有关此 SQL 存储过程的帮助。我正在使用来自不同表的源填充中间表 (COM_EXISTENCIAS) 以用于报告目的。在第一步中,我用 COM_INVENTARIOS 表中符合某些要求的数据填充它,如果有超过一行与 cryteria 匹配,则分组以汇总库存:

BEGIN
    INSERT  INTO COM_EXISTENCIAS
            (
              Mes ,
              Anyo ,
              Centro ,
              Codigo ,
              Stock ,
              Descripcion
            )
            SELECT  I.Mes ,
                    I.Anyo ,
                    I.Centro ,
                    I.Codigo ,
                    SUM(I.Stock) AS STOCK ,
                    I.Descripcion
            FROM    COM_INVENTARIOS I
            WHERE   I.Mes = @Mes
                    AND I.Centro = @Emp
                    AND I.NumInv = @NumInv
                    AND I.Anyo = @Anyo
            GROUP BY I.Codigo ,
                    I.Mes ,
                    I.Anyo ,
                    I.Centro ,
                    I.Descripcion
END

在第二步中,我继续使用另一个表中的数据填充该表(仅限第一个查询未插入的产品,或者表中不存在的产品)

  INSERT    INTO COM_EXISTENCIAS
            (
              Mes ,
              Anyo ,
              Centro ,
              Stock ,
              Codigo
            )
            SELECT  @Mes ,
                    @Anyo ,
                    @Emp ,
                    0 ,
                    Cod_art
            FROM    COM_ENTRADAS
            WHERE   MONTH(Fecha) = @Mes
                    AND Emp = @Emp
                    AND YEAR(Fecha) = @Anyo
            EXCEPT
            SELECT  @Mes ,
                    @Anyo ,
                    @Emp ,
                    0 ,
                    Codigo
            FROM    COM_INVENTARIOS
            WHERE   Mes = @Mes
                    AND Centro = @Emp
                    AND Anyo = @Anyo
            EXCEPT
            SELECT  @Mes ,
                    @Anyo ,
                    @Emp ,
                    0 ,
                    Codigo
            FROM    COM_EXISTENCIAS
            WHERE   Mes = @Mes
                    AND Centro = @Emp
                    AND Anyo = @Anyo

只要我只需要运行一次,它就可以完美运行。我的问题是有时我需要重新运行存储过程,因为一些新产品已添加到 COM_INVENTARIOS。我发现如果在第二步中已经从 COM_ENTRADAS 插入了一行并且现在存在于 COM_INVENTARIOS 中,它不会更新当前行,而是插入一个新行,所以我以两行具有相同数据的行结束。如果表上已经存在 Mes、Centro、NumInv 和 Anyo,我应该如何修改查询的第一部分以进行更新而不是添加?

还有一个额外的问题:在创建线条之后,我会在第三步中使用 COM_ENTRADAS 中的数据进行附加查询来更新它们。它现在可以工作了,但也许有一些更“干净”的方式来查询数据库,或者将两个查询合二为一?

UPDATE  dbo.COM_EXISTENCIAS
SET     TotEntradas = T.TotEnt ,
        ImporteCompras = T.Importe
FROM    ( SELECT    Cod_art ,
                    ISNULL(ROUND(SUM(Cantidad), 3), 0) AS TotEnt ,
                    ISNULL(ROUND(SUM(( P_coste ) * ( Cantidad )), 2), 0) AS Importe
          FROM      COM_ENTRADAS
          WHERE     Emp = @Emp
                    AND MONTH(Fecha) = CAST(@Mes AS INT)
                    AND YEAR(Fecha) = CAST(@Anyo AS INT)
          GROUP BY  Cod_art
        ) AS T
WHERE   T.Cod_art = dbo.COM_EXISTENCIAS.Codigo
        AND Mes = @Mes
        AND Anyo = @Anyo
        AND Centro = @Emp

【问题讨论】:

  • 您可以根据MERGE 子句的条件UPDATEINSERT:msdn.microsoft.com/en-us/library/bb510625.aspx‎
  • 忘了说是SQL 2005,所以很遗憾不能使用MERGE。

标签: sql-server tsql sql-server-2005


【解决方案1】:

有一个很好的 sql server 子句叫做MERGE,基本的使用模式如下:

MERGE Table1 AS t
USING 
    (
        SELECT  field1,                           
                ...
        FROM Table2
    ) AS s
    ON t.field1 = s.field1
WHEN MATCHED THEN
    UPDATE 
    SET ...
WHEN NOT MATCHED THEN
    INSERT
        (                
            ...
        )
    VALUES
        (                
            ...
        );

因此,您可以在一个 sql 查询中完成所有操作,而不是插入,然后在更新之后完成所有操作

【讨论】:

  • MERGE 恐怕在 SQL2005 中不存在。
【解决方案2】:

这可能对你有帮助,,,

   IF EXISTS (SELECT 1 FROM dbo.COM_EXISTENCIAS WHERE Mes = @Mes ---Proceed your condition)
        BEGIN 
                ----YOUR UPDATE QUERY
        END
    ELSE
        BEGIN
            ---YOUR INSERT QUERY
        END

第二期

 IF EXISTS 
             (
                SELECT 1 FROM dbo.COM_EXISTENCIAS E INNER JOIN COM_INVENTARIOS I ON I.Codigo = E.Codigo WHERE E.Mes = @Mes and E.Centro=@Emp and E.Anyo=@Anyo 
            ) 

        BEGIN 
            UPDATE dbo.COM_EXISTENCIAS SET Stock = T.Stock 
                 FROM (
                       SELECT Codigo,Stock FROM COM_INVENTARIOS 
                       WHERE Centro=@Emp AND Mes=@Mes AND Anyo=@Anyo and NumInv = @NumInv
                       ) AS T 
                       WHERE T.Codigo=dbo.COM_EXISTENCIAS.Codigo AND Mes=@Mes AND Anyo=@Anyo AND Centro=@Emp 
        END ELSE 

【讨论】:

  • 谢谢sureshhh。我已经修改了存储过程:它在第一次执行时运行良好(它插入了正确的寄存器)。然而,它在第二次执行时并没有按预期工作(它没有插入新行,但也没有更新当前行)。我猜这是因为在 SELECT 1 查询中没有使用“codigo”字段(产品代码的字段)。无论如何,我不知道如何在那里调用 Codigo,所以它只更新 COM_INVENTARIOS 中存在的行。
  • 这是我的程序现在的样子:如果存在(从 dbo.COM_EXISTENCIAS 中选择 1,其中 Mes = @Mes 和 Centro=@Emp 和 Anyo=@Anyo)开始更新 dbo.COM_EXISTENCIAS SET Stock = T.Stock FROM (SELECT Codigo,Stock FROM COM_INVENTARIOS WHERE Centro=@Emp AND Mes=@Mes AND Anyo=@Anyo and NumInv = @NumInv) AS T.Codigo=dbo.COM_EXISTENCIAS.Codigo AND Mes=@Mes AND Anyo=@Anyo AND Centro=@Emp END ELSE
  • 如果您考虑使用 dbo.COM_EXISTENCIAS.Codigo 进行更新,您还必须在 if exists () 中进行检查。或者将 @Codigo 作为参数传递。请参阅我编辑的答案
  • 我不能把它作为参数传递,因为我需要这个过程来动态比较 COM_EXISTENCIAS 和 COM_INVENTARIOS 来决定是更新还是插入。(使用 Mes、Anyo、Centro、Codigo 字段进行比较)
  • 如果存在,您必须加入(等等,等等......)
【解决方案3】:

这就是我的查询现在的样子:

ALTER PROCEDURE [dbo].[COM_GRABA_EXISTENCIAS2] 

@Emp  nchar(3),@Mes nchar(2),@Anyo nchar(4),@MesAnt nchar(2),@NumInv int 
AS  
-- INSTRUCCION DE PRUEBA

 IF EXISTS (SELECT 1 FROM dbo.COM_EXISTENCIAS E INNER JOIN COM_INVENTARIOS I ON I.Codigo = E.Codigo WHERE E.Mes = @Mes and E.Centro=@Emp and E.Anyo=@Anyo) 
        BEGIN 
            UPDATE dbo.COM_EXISTENCIAS SET Stock = T.Stock 
                 FROM (
                       SELECT Codigo,Stock FROM COM_INVENTARIOS 
                       WHERE Centro=@Emp AND Mes=@Mes AND Anyo=@Anyo and NumInv = @NumInv
                       ) AS T 
                       WHERE T.Codigo=dbo.COM_EXISTENCIAS.Codigo AND Mes=@Mes AND Anyo=@Anyo AND Centro=@Emp 
        END 
    ELSE
        BEGIN
                    INSERT INTO COM_EXISTENCIAS (Mes,Anyo,Centro,Codigo,Stock,Descripcion)
                    SELECT I.Mes,I.Anyo,I.Centro,I.Codigo,SUM(I.Stock) as STOCK,I.Descripcion
                    FROM COM_INVENTARIOS I
                    WHERE I.Mes=@Mes and I.Centro=@Emp and I.NumInv = @NumInv
                    GROUP BY I.Codigo,I.Mes,I.Anyo,I.Centro,I.Descripcion
        END

【讨论】:

    猜你喜欢
    • 2015-03-02
    • 1970-01-01
    • 2017-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多