代码之家  ›  专栏  ›  技术社区  ›  chobo2

如何修复此存储过程问题

  •  2
  • chobo2  · 技术社区  · 15 年前

    我有两张桌子。以下只是这些表的简化版本。

    TableA
    Id <pk> incrementing
    Name varchar(50)
    
    TableB
    TableAId <pk> non incrementing
    Name varchar(50)
    

    现在这些表彼此之间有了关系。

    脚本

    用户1来到我的站点并执行一些操作(在本例中,将行添加到表A)。所以我使用了一个sqlbackcopy表A中的所有数据。

    不过,我也需要将数据添加到表B中,但我不知道表A中新创建的ID,因为sqlbackcopy不会返回这些ID。

    所以我考虑使用一个存储过程来查找表B中不存在的所有ID,然后将它们插入。

    INSERT INTO TableB (TableAId , Name)
    SELECT Id,Name FROM TableA as tableA
    WHERE not exists( ...)
    

    然而,这也带来了一个问题。用户可以随时从表B中删除某些内容,因此,如果用户删除某一行,然后另一个用户出现,或者甚至同一个用户出现,并对表A执行某些操作,则我的存储过程将返回表B中已删除的行。由于该行仍存在于表A中,而不是表B中,因此满足存储过程条件。

    那么,在使用大容量插入时,是否有更好的方法来处理需要更新的两个表?

    3 回复  |  直到 14 年前
        1
  •  3
  •   gbn    15 年前

    sqlbackcopy使这变得复杂,所以我考虑使用临时表和 OUTPUT clause

    例如,在客户机伪代码和SQL的混合中

    create SQLConnection
    
    Create #temptable
    Bulkcopy to #temptable
    
    Call proc on same SQLConnection
    
    proc:
       INSERT tableA (..)
       OUTPUT INSERTED.key, .. INTO TableB
       SELECT .. FROM #temptable
    
    close connection
    

    笔记:

    • 诱人的将是本地连接并被隔离

    • 对A和B的写入将是原子的
    • 重叠或稍后写入不关心A和B之后会发生什么。
    • 强调最后一点,A和B将永远只从诱人的行集合中填充

    替代方案:

    将另一列添加到名为sessionid的A和B中,并使用该列标识行批。

        2
  •  1
  •   Andomar    15 年前

    一个选项是使用SQL Servers输出子句:

    INSERT YourTable (name)
    OUTPUT INSERTED.*
    VALUES ('NewName')
    

    这将返回 id, name 将插入的行中的一行复制到客户端,以便在第二个表的插入操作中使用它们。

        3
  •  1
  •   Rob Hruska MegalomanINA    14 年前

    作为一种替代方案,您可以使用 database triggers 更新第二个表。