【问题标题】:Update or insert data depending on whether row exists根据行是否存在更新或插入数据
【发布时间】:2013-01-21 21:11:05
【问题描述】:

我有一组从 Web 服务获取的行。其中一些行将被插入,一些是对现有行的更新。除非我对表中的 ID 进行查询,否则无法判断。如果我找到它,然后更新。如果我没有,请插入。

Select @ID from tbl1 where ID = @ID

IF @@ROWCOUNT = 0
BEGIN
Insert into tbl1
values(1, 'AAAA', 'BBBB', 'CCCC', 'DDD')
END
ELSE
BEGIN
UPDATE tbl1
SET 
A = @AAA,
B = @BBB,
C = @CCC,
D = @DDD
WHERE ID = @ID
END

我正在尝试找出最有效的方法来更新/插入这些行到表中,而不是一次将它们传递到存储过程中。

更新 1

我应该提到我使用的是 SQL Server 2005。另外,如果我有 300 条记录,我不想进行 300 次存储过程调用。

【问题讨论】:

  • 听起来您正在寻找MERGE 声明!

标签: sql sql-server-2005


【解决方案1】:

最有效的方法是首先尝试更新表,如果它返回 0 行更新然后只进行插入。例如。

UPDATE tbl1
    SET 
    A = @AAA,
    B = @BBB,
    C = @CCC,
    D = @DDD
    WHERE ID = @ID    
IF @@ROWCOUNT = 0
    BEGIN
    Insert into tbl1
    values(1, 'AAAA', 'BBBB', 'CCCC', 'DDD')
    END
    ELSE
    BEGIN

END

【讨论】:

    【解决方案2】:

    与其先支付搜索费用,然后使用另一个搜索进行更新,不如继续尝试更新。如果更新没有找到任何行,您仍然只支付了一次查找费用,并且不必引发异常,但您知道可以插入。

    UPDATE dbo.tbl1 SET 
    A = @AAA,
    B = @BBB,
    C = @CCC,
    D = @DDD
    WHERE ID = @ID;
    
    IF @@ROWCOUNT = 0
    BEGIN
      INSERT dbo.tbl1(ID,A,B,C,D)
        VALUES(@ID,@AAA,@BBB,@CCC,@DDD);
    END
    

    您也可以查看MERGE,但我回避这个,因为 (a) 语法令人生畏,并且 (b) 存在许多错误,其中一些仍未解决。

    当然,您应该使用表值参数,而不是一次只使用一个@ID。

    CREATE TYPE dbo.tbl1_type AS TABLE
    ( 
      ID INT UNIQUE,  
      A <datatype>,
      B <datatype>,
      C <datatype>,
      D <datatype>
    );
    

    现在您的存储过程可以如下所示:

    CREATE PROCEDURE dbo.tbl1_Update
      @List AS dbo.tbl1_type READONLY
    AS
    BEGIN
      SET NOCOUNT ON;
    
      UPDATE t 
        SET A = i.A, B = i.B, C = i.C, D = i.D
      FROM dbo.tbl1 AS t
      INNER JOIN @List AS i
      ON t.ID = i.ID;
    
      INSERT dbo.tbl1
      SELECT ID, A, B, C, D
        FROM @List AS i
        WHERE NOT EXISTS 
        (
          SELECT 1
          FROM dbo.tbl1 WHERE ID = i.ID
        );
    END
    GO
    

    现在您可以将 DataTable 或 C# 中的其他集合作为单个参数直接传递到过程中。

    【讨论】:

      【解决方案3】:

      从您从服务器获得的行集合中找出哪些行已经存在:

      select @id from tbl1 where id in (....)
      

      然后你有一个在表中的 id 列表和一个不在表中的 id 列表。 然后您将有 2 个批处理操作:一个用于更新,另一个用于插入。

      【讨论】:

        【解决方案4】:

        我的理解是这样的:

        在前端你发出一条 sql 语句

        ArrayofIDsforInsert = select ID from tbl1 where ID not in ( array of ids at the front end)
        ArrayofIDsforUpdate = (IntialArrayofids at frontend) - (ArrayofIdsforInsert)
        

        一个插入表和一个更新表...

        now call the insert into table with ArrayofIds for insert
        call the update table with ArrayofIds for update..
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-12-22
          • 1970-01-01
          • 1970-01-01
          • 2018-01-20
          • 1970-01-01
          • 2014-05-05
          • 2015-12-17
          • 2020-04-04
          相关资源
          最近更新 更多