使用 PowerShell 腳本來執行 T-SQL

 

使用 PowerShell 腳本來執行 T-SQL 
觸發查詢並將結果使用 bcp (Bulk Copy Program) 命令導出到 .log 文件

# 定義 SQL Server 的連線資訊
$serverName = "YOUR_SERVER_NAME"
$databaseName = "YOUR_DATABASE_NAME"
$username = "sa"
$password = "YOUR_PASSWORD"
$query = "SELECT * FROM YOUR_TABLE WHERE CONDITION = 'VALUE'"  # 替換為您的 T-SQL 查詢

# 設定 bcp 命令所需的查詢和導出文件路徑
$queryFile = "C:\path\to\yourQuery.sql"
$outputFile = "C:\path\to\output.log"

# 將 SQL 查詢寫入一個文件中
Set-Content -Path $queryFile -Value $query

# 建立 bcp 命令
$bcpCommand = "bcp `"$query`" queryout $outputFile -c -t, -S $serverName -d $databaseName -U $username -P $password"

# 執行 bcp 命令
Invoke-Expression $bcpCommand

# 檢查輸出文件
if (Test-Path $outputFile) {
    Write-Host "文件已成功導出到: $outputFile"
} else {
    Write-Host "導出失敗"
}

  • 定義連線參數,包括伺服器名稱、資料庫名稱、用戶名和密碼。
  • 設定要執行的查詢和結果輸出文件的路徑。
  • 使用 bcp 命令從 SQL Server 導出數據到指定的 .log 文件。


$query 如果很複雜是很多table join 加上cte組合 中間穿插了雙引號、單眼號的話

當您的 T-SQL 查詢相當複雜,包括多個表的連接(joins)、公用表達式(CTE)以及包含特殊字符(如雙引號或單引號)時,處理這種查詢最好的做法是將 SQL 查詢存儲在一個外部文件中,然後讓 bcp 工具直接從該文件中讀取查詢。這樣可以避免在命令行中遇到的許多引號和特殊字符的轉義問題。

創建 SQL 查詢文件: 將您的 SQL 查詢寫入一個 .sql 文件中。假設文件名為 complexQuery.sql
C:\path\to\complexQuery.sql

-- complexQuery.sql
WITH CteExample AS (
    SELECT ColumnA, ColumnB
    FROM Table1
    WHERE ColumnC > 100
)
SELECT t2.ColumnD, cte.ColumnA
FROM Table2 t2
JOIN CteExample cte ON t2.ColumnB = cte.ColumnB
WHERE t2.ColumnE = "SomeValue"

修改 PowerShell 腳本以使用外部 SQL 文件: 修改您的 PowerShell 腳本,讓 bcp 直接從這個 SQL 文件讀取查詢。

# 定義 SQL Server 的連線資訊
$serverName = "YOUR_SERVER_NAME"
$databaseName = "YOUR_DATABASE_NAME"
$username = "sa"
$password = "YOUR_PASSWORD"
$queryFile = "C:\path\to\complexQuery.sql"
$outputFile = "C:\path\to\output.log"

# 建立 bcp 命令
$bcpCommand = "bcp `"" + $(Get-Content -Path $queryFile -Raw) + "`" queryout $outputFile -c -t, -S $serverName -d $databaseName -U $username -P $password"

# 執行 bcp 命令
Invoke-Expression $bcpCommand

# 檢查輸出文件
if (Test-Path $outputFile) {
    Write-Host "文件已成功導出到: $outputFile"
} else {
    Write-Host "導出失敗"
}




Get-Content -Path $queryFile -Raw 用來讀取整個 SQL 文件的內容,作為查詢的一部分傳遞給 bcp。這種方法使得管理複雜的 SQL 查詢變得更加容易,並且減少了因直接在命令行中處理複雜查詢時可能出現的錯誤。

根據日期將輸出文件命名並且每次運行腳本時清除超過兩個月舊的 .log 文件
使用日期動態生成文件名:將輸出文件命名為當天的日期。
定期清除超過兩個月的文件:在腳本開始時添加一段代碼,刪除兩個月之前的 .log 文件。

# 定義基本參數
$serverName = "YOUR_SERVER_NAME"
$databaseName = "YOUR_DATABASE_NAME"
$username = "sa"
$password = "YOUR_PASSWORD"
$queryFile = "C:\path\to\complexQuery.sql"
$logDirectory = "C:\path\to\logs"

# 今天的日期,用於命名日誌文件
$today = Get-Date -Format "yyyy-MM-dd"
$outputFile = "$logDirectory\$today.log"

# 清除兩個月前的日誌文件
$cutOffDate = (Get-Date).AddMonths(-2)
Get-ChildItem -Path $logDirectory -Filter "*.log" | Where-Object { $_.LastWriteTime -lt $cutOffDate } | Remove-Item -Force

# 建立 bcp 命令
$bcpCommand = "bcp `"" + $(Get-Content -Path $queryFile -Raw) + "`" queryout $outputFile -c -t, -S $serverName -d $databaseName -U $username -P $password"

# 執行 bcp 命令
Invoke-Expression $bcpCommand

# 檢查輸出文件
if (Test-Path $outputFile) {
    Write-Host "文件已成功導出到: $outputFile"
} else {
    Write-Host "導出失敗"
}


  • $logDirectory 指定了存儲日誌文件的目錄。
  • $today 生成了一個格式為 yyyy-MM-dd 的日期字符串,用於構建輸出文件的名稱。
  • Get-ChildItem 搜索該目錄下所有 .log 文件,Where-Object 判斷文件的最後寫入時間是否早於兩個月前的日期,並通過 Remove-Item 刪除這些文件。




在 PowerShell 腳本中直接嵌入明文的使用者名稱和密碼是一個安全風險。

1.使用加密的 PowerShell 認證檔案

可以將認證保存在一個加密的檔案中,並在腳本中加載這個檔案。
如何創建和使用加密的認證檔案

# 提示使用者輸入密碼
$credential = Get-Credential -Message "Enter your SQL Server SA credentials"
$credential | Export-Clixml -Path "C:\path\to\your\credentials.xml"

將提示使用者輸入他們的使用者名稱和密碼,並將其保存在一個加密的 XML 檔案中。只有創建檔案的同一個使用者帳戶才能解密該檔案。

在腳本中使用加密的認證檔案

# 從加密檔案加載認證
$credential = Import-Clixml -Path "C:\path\to\your\credentials.xml"
$username = $credential.UserName
$password = $credential.GetNetworkCredential().Password

# 其餘的腳本不變,使用 $username 和 $password 變量



2.使用環境變數

在環境變數中存儲使用者名稱和密碼。這仍然需要一定的安全措施,因為環境變數可能會被同一系統上的其他process讀取。
在 Windows 中,您可以在系統的環境設置中添加環境變數,或使用命令行:

setx SQLUSER "sa" /M
setx SQLPASS "yourpassword" /M
/M 參數表示將變數設置為系統範圍內的環境變數。

在 PowerShell 中讀取環境變數

$username = [System.Environment]::GetEnvironmentVariable("SQLUSER", "Machine")
$password = [System.Environment]::GetEnvironmentVariable("SQLPASS", "Machine")

留言

這個網誌中的熱門文章

何謂淨重(Net Weight)、皮重(Tare Weight)與毛重(Gross Weight)

(2021年度)駕訓學科筆試準備題庫歸納分析_法規是非題

經得起原始碼資安弱點掃描的程式設計習慣培養(五)_Missing HSTS Header