从存储过程的结果集中读取第一行

时间:2013-06-25 23:31:09

标签: .net sql-server

我试图在PowerShell脚本中只读取xp_readerrorlog扩展存储过程的第一行。

不幸的是,ExecuteReader()方法读取xp_readerrorlog存储过程返回的所有记录,有时是几百万行或几分钟。

我试图谷歌它并发现使用DAO可以读取SQL Server返回的数据,但DAO已弃用,我不想走这条路。

BeginExecuteReader()似乎没有任何帮助,因为没有任何迹象表明是否有任何数据已经返回,直到执行完成等于ExecuteReader()。 在处理大型记录集时,有没有其他方法可以获得几个第一行/页面?

据我所知,我可以创建一个临时表,将数据转储到其中并从中SELECT TOP 1,但这会引入一些额外的I / O,这不是我正在寻找的解决方案。

2 个答案:

答案 0 :(得分:0)

我认为你对Execute methods work on a ServerConnection有一点误解。它们对存储过程的运行方式没有影响。即使您使用ExecuteScalar(执行Transact-SQL语句并将第一行的第一列作为值类型返回。),整个存储过程也将在服务器上运行,然后只返回第一个值。

提高性能的唯一两个选项是创建一个返回所需行的新过程(Sql性能改进和网络利用率改进)或使用临时表从存储过程返回单行(仅限网络)利用率提高)。

ServerConnection上没有内置方法可以在.Net Framework中执行您想要的操作。

答案 1 :(得分:0)

从.Net 4.5开始SqlCommand类有ExecuteReaderAsync()方法,SqlDataReader类有ReadAsync()方法。只要SQL Server开始使用这些新方法将数据发送到客户端,就可以开始处理数据。

不幸的是,PowerShell中没有等待运算符,所以代码看起来不像在C#中那么漂亮。

$sqlInstance = 'SqlServerName';

$con = New-Object System.Data.SqlClient.SQLConnection;
$con.ConnectionString = "Data Source=$($sqlInstance);Integrated Security=SSPI;Asynchronous Processing=true;";
$con.Open();

$cmd = New-Object System.Data.SqlClient.SQLCommand;
$cmd.Connection = $con;

$cmd.CommandType = [System.Data.CommandType]::StoredProcedure;
$cmd.CommandText = 'xp_readerrorlog';

# add parameters
$cmd.Parameters.Add('p1', [System.Data.SqlDbType]::Int, 1) | out-null;
$cmd.Parameters['p1'].Value = 1;
$cmd.Parameters.Add('p2', [System.Data.SqlDbType]::Int, 1) | out-null;
$cmd.Parameters['p2'].Value = 1;

$cmd.Prepare();

$task = $cmd.ExecuteReaderAsync();

# wait for first rows
While ( $task.IsCompleted -ne $true ) {
    Start-Sleep -m 10;
}

# PowerShell does not have await operator so a SqlDataReader object can be retrieved this way
$reader = $task.GetAwaiter().GetResult();

# read first row
$reader.ReadAsync().GetAwaiter().GetResult() | out-null;

$reader['LogDate'];

$cmd.Cancel(); # cancel execution, there is no need to wait for the whole recordset to be transfered to the client

$con.Close();