1

我正在维护基于大型 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。

感谢您的任何建议。

4

2 回答 2

0

我会使用简单的 Powershell 脚本来执行此操作,例如:

Invoke-SqlCommand -query '...' | ExportTo-Csv ...

通常,对于管理功能,您可以将其添加到任务计划程序并完成它。如果您需要根据需要执行此任务,您可以通过xp_cmdshellusing schtasks.exe run Task_NAMEwhich 可能对您更好,因为在给定上下文中在 Powershell 中表达自己比在 T-SQL 中表达自己可能更容易。

其他提到的东西都需要额外的工具(例如 SSIS 需要 VS),这是可移植的,没有依赖关系。

要在没有您的情况下调用脚本,xp_cmdshell应该使用 powershell 步骤创建一个作业并从 t-sql 中运行它。

于 2016-04-04T09:20:07.023 回答
0

您的数据导出选项如下:

  • 使用 xp_cmdshell 调用 bcp.exe - 旧的批量复制方式
  • 使用 CLR - 批量复制的新方法
  • SSIS - 我喜欢这样做的方式;这是示例
  • INSERT INTO OPENROWSET - 如果您在 32 位环境中工作并安装了 text/Jet/任何驱动程序,或者您可以安装 64 位驱动程序(例如 64 位 ODBC 文本驱动程序,请参阅 Microsoft Access 数据库,则可以使用有趣的替代方法引擎 2010 可再发行)
  • SQL Server 导入/导出向导 - 很少按照您希望的方式工作的丑陋手动方式
  • 使用外部 CSV 表 - 尚不支持(SQL Server 2016 承诺它将...)

高温高压

于 2016-04-04T08:40:14.103 回答