10

我不知道这是否是可接受的操作。我需要从 SQL Server 2008 数据库中选择记录,然后删除它们,所有这些都作为 ASP.NET 代码中的单个事务。请注意,.NET 代码必须能够检索第一次选择的数据。

像这样的东西:

SELECT * FROM [tbl] WHERE [id] > 6;
DELETE FROM [tbl] WHERE [id] > 6

我正在使用 SQL Fiddle尝试它,但如果我这样做:

SELECT * FROM [tbl]

我得到了完整的表,好像没有任何内容被删除。

编辑按照下面的要求,这里是检索记录的完整 .NET 代码:

string strSQLStatement = "SELECT * FROM [tbl] WHERE [id] > 6;" +
    "DELETE FROM [tbl] WHERE [id] > 6";

using (SqlCommand cmd = new SqlCommand(strSQLStatement, connectionString))
{
    using (SqlDataReader rdr = cmd.ExecuteReader())
    {
        while(rdr.Read())
        {
            //Read values
            val0 = rdr.GetInt32(0);
            val3 = rdr.GetInt32(3);
            //etc.
        }
    }
}
4

4 回答 4

26

这将同时进行选择和删除:

delete from [tbl] output deleted.* WHERE [id] > 6
于 2013-06-23T05:51:34.147 回答
1

只要两个操作都在同一个事务中登记,就可以在同一个事务中进行选择和删除。

看看这篇文章 .net 中的交易

于 2013-06-23T04:52:30.740 回答
1

使用兼容的提供程序(SQL Server 工作得很好!)实现事务的“最简单”方法是使用TransactionScope。只需确保在打开连接之前创建范围,以便正确登记所有内容。

SelectStuff和方法的内容DeleteStuff无关紧要——只要使用相同的连接,不要手动弄乱连接或事务,执行 SQL 操作是最好的。

// Notes
// - Create scope OUTSIDE/BEFORE connection for automatic enlisting
// - Create only ONE connection inside to avoid DTC and "advanced behavior"
using (var ts = new TransactionScope())
using (var conn = CreateConnection()) {
    // Make sure stuff selected is MATERIALIZED:
    // If a LAZY type (Enumerable/Queryable) is returned and used later it
    // may cause access to the connection outside of when it is valid!
    // Use "ToList" as required to force materialization of such sequences.
    var selectedStuff = SelectStuff(conn);

    DeleteStuff(conn);

    // Commit
    ts.Complete();

    // Know stuff is deleted here, and access selected stuff.
    return selectedStuff; 
}
于 2013-06-23T05:07:47.237 回答
0

多个 SQL 语句的返回值是最后一条语句运行的结果,在本例中是DELETE. 没有从 a 返回的行,因此对于andDELETE没有什么可读取的。val0val3

我可以在这里想到两种解决方案:

  1. 更改您的代码以明确启动事务、执行SELECT、读取值,然后发出DELETE, 或

  2. SELECT进入一个#temp表,执行DELETE,然后SELECT#temp表中,对行做你需要做的事情,然后DROPth.

于 2013-06-23T05:18:35.937 回答