我维护大型基于t-sql的应用程序。 它有很多用于通过xp_cmdshell调用的bcp。
这是有问题的,因为xp_cmdshell具有与SQL Server服务帐户相同的安全上下文,并且它不仅仅是工作所必需的。
我摆脱这个缺点的第一个想法是使用CLR代码。 CLR正在运行调用代码的用户的权限。 我创建了以下程序,它工作正常。我可以看到它正在使用运行此代码的帐户权限:
public static void RunBCP(SqlString arguments, out SqlString output_msg, out SqlString error_msg, out SqlInt32 return_val) {
output_msg = string.Empty;
error_msg = string.Empty;
try {
var proc = new Process {
StartInfo = new ProcessStartInfo {
FileName = "bcp",
Arguments = arguments.ToString(),
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
proc.Start();
while (!proc.StandardOutput.EndOfStream) {
output_msg += proc.StandardOutput.ReadLine();
}
return_val = proc.ExitCode;
}
catch (Exception e) {
error_msg = e.Message;
return_val = 1;
}
}
这是一个很好的解决方案,因为我没有弄乱BCP调用(参数是相同的)。逻辑没有重大变化,因此不存在错误风险。
因此,之前在T-SQL中调用BCP的方式是这样的:
declare @ReturnCode int;
declare @cmd varchar(1000);
SELECT @CMD = 'bcp "select FirstName, LastName, DateOfBirth" queryout "c:\temp\OutputFile.csv" -c -t -T -S"(local)"'
EXEC @ReturnCode=xp_cmdshell @CMD,no_output
现在我这样称呼它:
declare @ReturnCode int;
declare @cmd varchar(1000);
SELECT @CMD = '"select FirstName, LastName, DateOfBirth" queryout "c:\temp\OutputFile.csv" -c -t -T -S"(local)"'
exec DataBase.dbo.up_RunBCP @arguments = @cmd;
所以,问题是:有没有其他方法可以摆脱xp_cmdshell bcp代码? 我听说我可以使用PowerShell(sqlps)。但我发现的例子建议创建一个PowerShell脚本。 我可以从t-sql代码调用这样的脚本吗? 如何存储此代码(powershell脚本)?作为数据库对象? 或者也许有其他方式?没必要SSIS。我最想知道的是PowerShell。
感谢您的任何建议。
答案 0 :(得分:0)
您的数据导出选项如下:
HTH
答案 1 :(得分:0)
我会使用简单的Powershell脚本执行此操作,例如:
Invoke-SqlCommand -query '...' | ExportTo-Csv ...
通常,对于管理功能,您可以将其添加到任务计划程序并完成它。如果您需要根据需要执行此任务,可以通过xp_cmdshell
使用schtasks.exe run Task_NAME
来执行此操作,这可能对您更好,因为在Powershell中表达自己可能更容易,然后在给定的上下文中使用T-SQL表达自己
其他提到的东西都需要额外的工具(例如SSIS需要VS),这是可移植的,没有依赖性。
要调用不带xp_cmdshell
的脚本,您应该使用powershell步骤创建一个作业,并在t-sql中运行它。