我试图在PowerShell脚本中只读取xp_readerrorlog
扩展存储过程的第一行。
不幸的是,ExecuteReader()
方法读取xp_readerrorlog
存储过程返回的所有记录,有时是几百万行或几分钟。
我试图谷歌它并发现使用DAO可以读取SQL Server返回的数据,但DAO已弃用,我不想走这条路。
BeginExecuteReader()
似乎没有任何帮助,因为没有任何迹象表明是否有任何数据已经返回,直到执行完成等于ExecuteReader()
。
在处理大型记录集时,有没有其他方法可以获得几个第一行/页面?
据我所知,我可以创建一个临时表,将数据转储到其中并从中SELECT TOP 1
,但这会引入一些额外的I / O,这不是我正在寻找的解决方案。
答案 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();