通过 CLR 的 SQLDatareader 没有以正确的方式返回 SQL 消息

Posted

技术标签:

【中文标题】通过 CLR 的 SQLDatareader 没有以正确的方式返回 SQL 消息【英文标题】:SQLDatareader via CLR not returning SQL Message right way 【发布时间】:2010-07-28 19:09:02 【问题描述】:

我通过CLR执行下面的代码,消息没有打印到SQL Server有什么原因,是否需要等到存储过程返回所有行(大约有70亿行要返回)

    SqlCommand cmd = new SqlCommand();
        cmd.Connection = conn;
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.CommandText = "spCommand_Select_Rows_For_Delete";
        cmd.CommandTimeout = 41600;

        SqlDataReader reader = cmd.ExecuteReader();
        try
        
            string strSQL = "";
            SqlContext.Pipe.Send(DateTime.Now.ToString() + " - Started working with ProductTable");

            while (reader.Read())
            
                strSQL = "DELETE FROM ProductTable WHERE ProductId = " + reader["ProductId"].ToString();

                SqlCommand cmdDelete = new SqlCommand(strSQL, conn);

                cmdDelete.Connection = conn;
                cmdDelete.CommandTimeout = 20800;
                cmdDelete.ExecuteNonQuery();
            

            SqlContext.Pipe.Send(DateTime.Now.ToString() + " - Completed working with ProductTable");
        
        finally
        
            // Always call Close when done reading.
            reader.Close();
        

我的存储过程:

SELECT ProductId FROM ProductTable
    WHERE ProductInfoId IN
    (
    SELECT ProductInfoId from DeletedProducts
    )

【问题讨论】:

70 亿行来自存储过程?因此,您要一个接一个从较大的行中删除 70 亿行? 哇,这就是 RBAR 中有 A 的原因。 【参考方案1】:

以下是使用基于集合的良好操作删除 70 亿行的方法。您不会abuse在 CLR 中遍历数据读取器。

 SELECT 'Starting'
 WHILE ROWCOUNT <> 0
    DELETE TOP (1000000) P
    FROM  ProductTable P
    WHERE EXISTS (
        SELECT * from DeletedProducts DP WHERE P.ProductInfoId = DP.ProductInfoId
    )

更多,请看这个问题Bulk DELETE on SQL Server 2008

但是要回答您的问题,是的,SQL Server 不会立即PRINT(您正在做的事情)

【讨论】:

这是否会在它到达顶部 (1000000) 时立即跳出表格,而不是继续扫描整个表格? @RPS:会因为WHILE分批删除1000000个(现在我修正了错字) 这不会导致 SQL LOG 变得非常大吗? 逐个删除 70 亿行,或者分 7000 批删除几乎无关紧要 我想删除很多行,但我不想占用大量磁盘空间,也不想花费数周时间来删除。【参考方案2】:

您可能可以使用带有RAISERROR WITH NOWAIT 的 SqlContext.Pipe.ExecuteAndSend 来对消息执行您想要的操作。

但我同意 gbn 关于批量删除不需要 CLR 的回答。

【讨论】:

以上是关于通过 CLR 的 SQLDatareader 没有以正确的方式返回 SQL 消息的主要内容,如果未能解决你的问题,请参考以下文章

如何检查 SQLDataReader 是不是没有行

有没有办法将任务并行库(TPL)与 SQLDataReader 一起使用?

将 DataTableReader 转换为 SqlDataReader

没有CLR版本v4。被加载到目标进程中。 - CLR Profiler错误

使用 SQLDataReader 读取 IP 地址

SqlDataReader - 如何将当前行转换为字典