【问题标题】:Is it possible to record INSERTed row references for deletion later?是否可以记录插入的行引用以供以后删除?
【发布时间】:2017-01-17 11:36:10
【问题描述】:

为了测试,我将一堆行插入到 SQLServer 数据库中。我想在最后清除它们。虽然这应该是一个特定的仅测试数据库,但我希望表现得很好以防万一。出于同样的原因,我不想在删除我的测试数据时假设数据库中可能已经存在哪些数据,例如删除所有行或日期在一定范围内的所有行。

在插入行时,有一种方法可以捕获对插入的实际行的引用,因此我可以稍后删除这些确切的行,无论其中的数据是否已被修改。所以我知道我为测试“拥有”了哪些确切的行?

我在 ms-test 框架内从 C# 代码调用 SQLServer 查询。

【问题讨论】:

  • 使用临时表来存储这些行怎么样?然后从数据库中删除并查看您的临时表
  • 这很有趣,但实际上是否有可能获得 SQLServer 用来分别识别我的 PK 的每一行的“行 ID”?
  • 是的,您可以将那些插入的 PK 值保存在表变量中。 @Mr.Boy
  • 我建议使用测试框架,例如 tSQLt (tsqlt.org)。它为每次测试运行提供了干净的测试环境所需的所有必要机制。

标签: c# sql-server visual-studio mstest


【解决方案1】:

是的,可以使用OUTPUT 子句。

您需要创建一个中间表来捕获插入的记录标识值。

DECLARE @TAB TABLE(ID INT)

INSERT INTO TABLE1
output inserted.Table1PK into @TAB

SELECT id,name ... ETC

现在检查你的表变量

SELECT * FROM @TAB

如果您想将 Table 变量数据转储到一个 Actual 表中。

更多信息请查看OUTPUT Clause (Transact-SQL)

现在您可以像

一样删除 TABLE1 记录
DELETE FROM TABLE1 WHERE ID IN (SELECT ID FROM @TAB)

【讨论】:

    【解决方案2】:

    您可以使用事务并回滚事务,而不是在测试结束时提交事务。

    您可以通过显式事务执行此操作,或者在会话开始时通过set implicit_transactions on; 执行此操作,而不提交事务。

    begin transaction test /* explicit transaction */
    
    insert into TestTable (pk,col) values
      (1,'val');
    
    update TestTable
      set pk=2 
      where pk=1;
    
    select * 
      from TestTable 
      where pk = 2;
    
    rollback transaction
    --commit transaction
    

    我不会在生产环境中执行此操作,因为事务将保持锁定直到事务完成,但如果您正在测试 pk 可能更改的插入、更新和删除组合,这可能比尝试更安全跟踪所有更改以手动回滚。

    这还可以防止您在测试中出现无法手动回滚的错误。

    相关:How to: Write a SQL Server Unit Test that Runs within the Scope of a Single Transaction

    【讨论】:

    • 有趣。我没有提到我是从 C# 做这个的。有没有机会举个例子(或者如果你不是 C# 人,也可以是其他人)?
    • this example from SqlTransaction.Rollback Method ()的try部分,你只需使用transaction.Rollback();而不是transaction.Commit();
    猜你喜欢
    • 2019-03-06
    • 2013-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多