簡體   English   中英

從t-sql代碼中刪除xp_cmdshell調用的最佳方法是什么

[英]What is the best to remove xp_cmdshell calls from t-sql code

我正在維護基於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的。

感謝您的任何建議。

數據導出的選項如下:

  • 使用xp_cmdshell調用bcp.exe - 舊的批量復制方式
  • 使用CLR-您批量復制的新方法
  • SSIS-我這樣做的首選方式; 這是一個例子
  • INSERT INTO OPENROWSET-如果您正在安裝了文本/ Jet /任何驅動程序的32位環境中工作,或者可以安裝64位驅動程序(例如64位ODBC文本驅動程序,請參閱Microsoft Access數據庫),可以使用一種有趣的替代方法Engine 2010 Redistributable)
  • SQL Server導入/導出向導-丑陋的手動方式,很少以您希望的方式工作
  • 使用外部CSV表 - 尚不支持(SQL Server 2016承諾它將...)

HTH

我會使用簡單的Powershell腳本執行此操作,例如:

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

通常,對於管理功能,您可以將其添加到Task Scheduler中並使用它來完成。 如果您需要根據需要來執行這個任務,你可以通過做xp_cmdshell使用schtasks.exe run Task_NAME這可能是對你更好,因為它可能會更容易表達自己,在PowerShell中,然后在T-SQL中給出的上下文。

其他提到的東西都需要額外的工具(例如SSIS需要VS),這是可移植的,沒有依賴性。

要在沒有xp_cmdshell情況下調用腳本,您應該使用powershell步驟創建一個作業並從t-sql中運行它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM