如何解决此存储过程问题

时间:2010-08-12 19:14:11

标签: sql sql-server sqlbulkcopy

我有2张桌子。以下只是这些表的精简版。

TableA
Id <pk> incrementing
Name varchar(50)

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

现在这些表彼此有关系。

方案

用户1来到我的网站并执行一些操作(在这种情况下向表A添加行)。所以我在表A中使用了SqlBulkCopy所有这些数据。

但是我还需要将数据添加到表B中,但我不知道表A中新创建的Id,因为SQLBulkCopy不会返回这些。

所以我想有一个存储过程找到表B中不存在的所有id,然后将它们插入。

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

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

那么有没有更好的方法来处理使用批量插入时需要更新的两个表?

3 个答案:

答案 0 :(得分:3)

SQLBulkCopy使这变得复杂,所以我考虑使用临时表和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

注意:

  • temptable将是连接的本地,并被隔离

  • 对A和B的写入将是原子的
  • 重叠或稍后写入并不关心A和B后面发生的事情
  • 强调最后一点,A和B只会从#temptable
  • 中的行集中填充

替代:

向A和B添加另一个名为sessionid的列,并使用它来识别行批次。

答案 1 :(得分:1)

一种选择是使用SQL Servers输出子句:

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

这会将插入行的id, name返回给客户端,因此您可以在第二个表的插入操作中使用它们。

答案 2 :(得分:1)

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