AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 119334
Accepted
RBarryYoung
RBarryYoung
Asked: 2015-10-28 08:00:56 +0800 CST2015-10-28 08:00:56 +0800 CST 2015-10-28 08:00:56 +0800 CST

我怎样才能像 SSMS 一样获得单独的行数?

  • 772

我有一个客户端 c# 程序正在通过 执行存储过程,包括使用 InfoMessage 事件ExectueNonQuery捕获和错误输出。PRINT它工作正常,但我注意到一些奇怪的事情。

当我从 SSMS 执行存储过程时,它会显示在“消息”选项卡中执行的每个单独 SQL 语句的行数(就好像它来自 InfoMessages)。但是我的程序从来没有看到这些消息,尽管它确实捕获了所有相同的其他输出。相反,它只返回在 ExecuteNonQuery 函数结果中受影响的行,该结果是所有单个行计数的总和(这有点无用)。

例如,这个过程:

use [tempdb]
go

SELECT  * 
INTO    MyCols
FROM    sys.columns
go

CREATE PROC foo As

    UPDATE  MyCols
    SET     name = name + N''
-- SSMS shows (662 row(s) affected)

    UPDATE  MyCols
    SET     name = name + N''
    WHERE   name like '%x%'
-- SSMS shows (59 row(s) affected)

PRINT 'bar'
-- both SSMS and ExecuteNonQuery get this

-- ExecuteNonQuery returns 721 rows affected
GO

当fooproc 运行时,SSMS 显示 662 和 59 的行数,但ExecuteNonQuery只返回总数 721。

那么,我怎样才能获得与 SSMS 相同的信息呢?


在这里要明确一点:我对如何更改存储过程以PRINT @@ROWCOUNT在每个 SQL 语句后添加 s 不感兴趣。我知道该怎么做,但出于各种原因,大多数时候这不是一个选择。

我在问如何做 SSMS 在这里做的事情。我现在可以随心所欲地更改客户端代码(无论如何现在),我想做对。

sql-server sql-server-2008-r2
  • 2 2 个回答
  • 771 Views

2 个回答

  • Voted
  1. Best Answer
    Solomon Rutzky
    2015-10-28T09:45:38+08:002015-10-28T09:45:38+08:00

    该SqlCommand.StatementCompleted事件将在批处理中的每个语句之后触发,事件的属性之一(好吧,几乎是唯一的属性)是受触发事件的语句影响的行数。

    一些注意事项:

    • 获取此信息的一个要求是您没有指定,SET NOCOUNT ON;或者相反,您确实指定了SET NOCOUNT OFF;。
    • 所有事件都在每个事件完成时触发Execute___(),而不是在执行期间触发。
    • StatementCompletedEventArgs.RecordCount包括来自语句的行数SELECT,而SqlDataReader.RecordsAffected属性仅报告来自 DML 语句(INSERT、UPDATE、DELETE等)的行数。
    • 该StatementCompleted事件不包括触发该事件的批处理中的单个 SQL 语句。但是,事件处理程序sender作为输入参数发送,这是SqlCommand查询批处理的,您可以通过转换sender为SqlCommand然后查看CommandText属性来查看该批处理(如下例所示)。

    关于这方面的文档非常少,所以我编写了一个示例来显示针对ExecuteNonQuery和ExecuteScalar以及即席查询和存储过程(即SqlCommand.CommandTypevs Text)触发的事件StoredProcedure:

    using System;
    using System.Data;
    using System.Data.SqlClient;
    
    namespace StatementCompletedFiring
    {
        class Program
        {
            static void Main(string[] args)
            {
                using (SqlConnection _Connection =
                              new SqlConnection("Integrated Security = True;"))
                {
                    using (SqlCommand _Command = new SqlCommand(@"
    SET NOCOUNT OFF; --  ensures that the 'StatementCompleted' event fires
    
    EXEC('
    CREATE PROCEDURE #TestProc
    AS
    SELECT * FROM sys.objects;
    
    SELECT * FROM sys.tables;
    ');
    
    SELECT * FROM sys.objects;
    ", _Connection))
                    {
    
                        _Command.StatementCompleted += _Command_StatementCompleted;
    
                        try
                        {
                            _Connection.Open();
    
                            _Command.ExecuteNonQuery();
    
                            _Command.CommandText = @"
    SELECT 123 AS [Bob];
    
    WAITFOR DELAY '00:00:05.000'; --5 second pause to shows when the events fire
    
    SELECT 2 AS [Sally]
    UNION ALL
    SELECT 5;
    ";
                            Console.WriteLine("\n\t");
                            Console.WriteLine(_Command.ExecuteScalar().ToString());
                            Console.WriteLine("\n");
    
    
                            _Command.CommandType = CommandType.StoredProcedure;
                            _Command.CommandText = "#TestProc";
                            _Command.ExecuteNonQuery();
                        }
                        catch (Exception _Exception)
                        {
                            throw new Exception(_Exception.Message);
                        }
                    }
                }
            }
    
            static void _Command_StatementCompleted(object sender,
                                                    StatementCompletedEventArgs e)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.Write("\nQuery Batch: ");
                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine(((SqlCommand)sender).CommandText);
    
                Console.ForegroundColor = ConsoleColor.Red;
                Console.Write("Row(s) affected: ");
                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine(e.RecordCount.ToString() + "\n");
    
                Console.ResetColor();
            }
        }
    }
    

    输出:

    查询批次:
    SET NOCOUNT OFF;-- 确保“StatementCompleted”事件触发

    EXEC(' CREATE PROCEDURE #TestProc AS SELECT * FROM sys.objects;

    从 sys.tables 中选择 *;');

    选择 * 来自 sys.objects;

    受影响的行数: 453

    查询批次:
    SELECT 123 AS [Bob];

    等待延迟“00:00:05.000”;--5 秒停顿

    SELECT 2 AS [Sally] UNION ALL SELECT 5;

    受影响的行: 1

    查询批次:
    SELECT 123 AS [Bob];

    等待延迟“00:00:05.000”;--5 秒停顿

    SELECT 2 AS [Sally] UNION ALL SELECT 5;

    受影响的行: 2

    123

    查询批次: #TestProc
    受影响的行: 453

    查询批次: #TestProc
    受影响的行: 17

    • 7
  2. Jonathan Fite
    2015-10-28T08:23:45+08:002015-10-28T08:23:45+08:00

    executenonquery 结果不会在这里执行您想要的操作。但是您仍然可以到达那里,这仅取决于您要将这些信息用于什么目的。

    您可以在每次插入“PRINT @@ROWCOUNT”之后添加这一行,并且您应该将受先前操作影响的行数作为输出的一部分(在此处获得“bar”。

    或者,您可以将“OUTPUT”参数添加到存储过程以保存结果,然后在运行 executenonquery 时捕获该结果。

    编辑:

    我设法修改了Jonathan Kehasias放在一起的示例,以包括 statementcompleted 事件处理。只需添加这两行。

    #Add handler for StatementCompleted
    $statementhandler = {param($sender, [System.Data.StatementCompletedEventArgs]$event) Write-Host $event.RecordCount };
    
    #Attach handler...
    $cmd.add_StatementCompleted($statementhandler)
    
    • -1

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve