如何在 PowerShell 中将计算值写入 SQL INSERT/UPDATE
Posted
技术标签:
【中文标题】如何在 PowerShell 中将计算值写入 SQL INSERT/UPDATE【英文标题】:How to write calculated values to SQL INSERT/UPDATE in PowerShell 【发布时间】:2021-12-31 03:56:59 【问题描述】:在我下面的 PowerShell 中,我在 UNC 路径中获取所有第一级文件夹,并计算每个文件夹的文件、文件夹和大小(以 MB 为单位),我需要将其写入 SQL Server 表,但这在将值写入 SQL 字符串时让我有些头疼。
我有 3 个值需要写入 SQL,它们是:
$TotalFileCount $TotalDirectoryCount $TotalFolderSizeInMB'我试着把它们写出来:
$TotalFileCount $($TotalFileCount) $($TotalFileCount.tostring() $($TotalFileCount.value.tostring())但是当我创建Write-Host
时,它们都没有返回任何数据,所以我希望这是因为$TotalFileCount
是一个计算,但是任何找到解决方案来写出它的努力都是不费吹灰之力的,所以我需要一些帮助以找到解决方案。
我的 PS 脚本:
$SQLServer = "SQL_SERVER"
$SQLDatabase = "DATA_BASE"
#SQL function
function Invoke-SQL
param(
[string] $sqlCommand = $(throw "Please specify a query.")
)
$connectionString = "Data Source=$SQLServer; " +
"Integrated Security=SSPI; " +
"Initial Catalog=$SQLDatabase"
$connection = new-object system.data.SqlClient.SQLConnection($connectionString)
$command = new-object system.data.sqlclient.sqlcommand($sqlCommand,$connection)
$connection.Open()
$adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
$dataset = New-Object System.Data.DataSet
$connection.Close()
$dataSet.Tables
Function Get-DirectoryTreeSize
[CmdletBinding(DefaultParameterSetName="Default")]
param(
[Parameter(
Position = 0,
Mandatory = $true
)]
[string] $Path,
[Parameter(
Mandatory = $false,
ParameterSetName = "ShowRecursive"
)]
[switch] $Recurse,
[Parameter(
Mandatory = $false,
ParameterSetName = "ShowTopFolderAllItemsAndAllFolders"
)]
[switch] $AllItemsAndAllFolders
)
BEGIN
#Adding a trailing slash at the end of $path to make it consistent.
if (-not $Path.EndsWith('\'))
$Path = "$Path\"
PROCESS
try
if (-not $PSBoundParameters.ContainsKey("AllItemsAndAllFolders") -and -not $PSBoundParameters.ContainsKey("Recurse"))
$FileStats = Get-ChildItem -Path $Path -File -ErrorAction Stop | Measure-Object -Property Length -Sum
$FileCount = $FileStats.Count
$DirectoryCount = Get-ChildItem -Path $Path -Directory | Measure-Object | select -ExpandProperty Count
$SizeMB = "0:F3" -f ($FileStats.Sum / 1MB) -as [decimal]
[PSCustomObject]@
Path = $Path
FileCount = $FileCount
DirectoryCount = $DirectoryCount
FolderSizeInMB = $SizeMB
if ($PSBoundParameters.ContainsKey("AllItemsAndAllFolders"))
$FileStats = Get-ChildItem -Path $Path -File -Recurse -ErrorAction Stop | Measure-Object -Property Length -Sum
$FileCount = $FileStats.Count
$DirectoryCount = Get-ChildItem -Path $Path -Directory -Recurse | Measure-Object | select -ExpandProperty Count
$SizeMB = "0:F3" -f ($FileStats.Sum / 1MB) -as [decimal]
[PSCustomObject]@
Path = $Path
TotalFileCount = $FileCount
TotalDirectoryCount = $DirectoryCount
TotalFolderSizeInMB = $SizeMB
if ($PSBoundParameters.ContainsKey("Recurse"))
Get-DirectoryTreeSize -Path $Path
$FolderList = Get-ChildItem -Path $Path -Directory -Recurse | select -ExpandProperty FullName
if ($FolderList)
foreach ($Folder in $FolderList)
$FileStats = Get-ChildItem -Path $Folder -File | Measure-Object -Property Length -Sum
$FileCount = $FileStats.Count
$DirectoryCount = Get-ChildItem -Path $Folder -Directory | Measure-Object | select -ExpandProperty Count
$SizeMB = "0:F3" -f ($FileStats.Sum / 1MB) -as [decimal]
[PSCustomObject]@
Path = $Folder
FileCount = $FileCount
DirectoryCount = $DirectoryCount
FolderSizeInMB = $SizeMB
#clearing variables
$null = $FileStats
$null = $FileCount
$null = $DirectoryCount
$null = $SizeMB
catch
Write-Error $_.Exception.Message
END
foreach ($name in Get-ChildItem "\\FILSRV01\home dir$"| Where $_.PSIsContainer | Where $_.PSIsContainer | Select-Object name)
$TopPath = "\\FILSRV01\home dir$\"
$TempPath = Join-Path $TopPath $name."name"
Get-DirectoryTreeSize $TempPath -AllItemsAndAllFolders
$sqlSelectCommand = "SELECT * from EFP_HomeFolder_Stats where UserInitials = '$($name."name")'"
$sqlInsertCommand = "INSERT INTO EFP_HomeFolder_Stats (Path,UserInitials,TotalFileCount,TotalDirectoryCount,TotalFolderSizeInMB,LastUpdated) VALUES('$TempPath','$($name."name")','$($TotalFileCount)','$TotalDirectoryCount','$TotalFolderSizeInMB',GETDATE())"
$sqlUpdateCommand = "UPDATE EFP_HomeFolder_Stats SET Path = '$TempPath', UserInitials = '$($name."name")', TotalFileCount = '$TotalFileCount', TotalDirectoryCount = '$TotalDirectoryCount', TotalFolderSizeInMB = '$TotalFolderSizeInMB', LastUpdated = GETDATE()"
Invoke-SQL -sqlCommand $sqlSelectCommand
Write-host $name.ExistCoun
Invoke-SQL -sqlCommand "
if exists ($sqlSelectCommand)
BEGIN
$sqlUpdateCommand
End
else
BEGIN
$sqlInsertCommand
END
"
【问题讨论】:
devblogs.microsoft.com/powershell/… 嗨@shawnt00 我可能正在监督有关您的链接的一些事情,但正如您在帖子中看到的那样,我已经尝试过了 可能是引号吗?有没有插入任何东西? 删除引号不会改变任何东西..在没有插入 SQL 的那一刻,我意识到了这一点,但想一次解决一个问题,我首先担心的是没有价值写出sql命令的时候写的。即INSERT INTO EFP_HomeFolder_Stats (Path,UserInitials,TotalFileCount,TotalDirectoryCount,TotalFolderSizeInMB,LastUpdated) VALUES('\\FILSRV01\home dir$\MWE','MWE',,,,GETDATE())
和UPDATE EFP_HomeFolder_Stats SET Path = '\\FILSRV01\home dir$\CAN', UserInitials = 'CAN', TotalFileCount = , TotalDirectoryCount = , TotalFolderSizeInMB = , LastUpdated = GETDATE()
两个 sql 语句中的计数都没有值。那肯定会出错。
【参考方案1】:
我现在已经解决了以下问题:通过将 Invoke-SQL 移动到 Get-DirectoryTreeSize
函数中,没有变量写入我的 SQL INSERT/UPDATE 查询,并且当我执行 Write-OutPut 时,值现在被填充到我的查询中的查询。我现在通过$MySplitPath = Split-Path -Path $Path -Leaf
而不是$name."name"
获得的用户姓名首字母..
剩下的问题是 SQL 没有执行,这意味着没有任何东西被插入到我的 SQL 表中,所以我现在需要弄清楚这部分。如果有人有建议,我很乐意在这里提出建议:-)
#statiske vaiabler
$SQLServer = "SQL_SERVER"
$SQLDatabase = "SQL_DB"
#SQL function
function Invoke-SQL
param(
[string] $sqlCommand = $(throw "Please specify a query.")
)
$connectionString = "Data Source=$SQLServer; " +
"Integrated Security=SSPI; " +
"Initial Catalog=$SQLDatabase"
$connection = new-object system.data.SqlClient.SQLConnection($connectionString)
$command = new-object system.data.sqlclient.sqlcommand($sqlCommand,$connection)
$connection.Open()
$adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
$dataset = New-Object System.Data.DataSet
$connection.Close()
$dataSet.Tables
Function Get-DirectoryTreeSize
[CmdletBinding(DefaultParameterSetName="Default")]
param(
[Parameter(
Position = 0,
Mandatory = $true
)]
[string] $Path,
[Parameter(
Mandatory = $false,
ParameterSetName = "ShowRecursive"
)]
[switch] $Recurse,
[Parameter(
Mandatory = $false,
ParameterSetName = "ShowTopFolderAllItemsAndAllFolders"
)]
[switch] $AllItemsAndAllFolders
)
BEGIN
#Adding a trailing slash at the end of $path to make it consistent.
if (-not $Path.EndsWith('\'))
$Path = "$Path\"
if ($Path.EndsWith('\'))
$Path = "$Path\"
PROCESS
try
if (-not $PSBoundParameters.ContainsKey("AllItemsAndAllFolders") -and -not $PSBoundParameters.ContainsKey("Recurse"))
$FileStats = Get-ChildItem -Path $Path -File -ErrorAction Stop | Measure-Object -Property Length -Sum
$FileCount = $FileStats.Count
$DirectoryCount = Get-ChildItem -Path $Path -Directory | Measure-Object | select -ExpandProperty Count
$SizeMB = "0:F3" -f ($FileStats.Sum / 1MB) -as [decimal]
[PSCustomObject]@
Path = $Path
FileCount = $FileCount
DirectoryCount = $DirectoryCount
FolderSizeInMB = $SizeMB
if ($PSBoundParameters.ContainsKey("AllItemsAndAllFolders"))
$FileStats = Get-ChildItem -Path $Path -File -Recurse -ErrorAction Stop | Measure-Object -Property Length -Sum
$FileCount = $FileStats.Count
$DirectoryCount = Get-ChildItem -Path $Path -Directory -Recurse | Measure-Object | select -ExpandProperty Count
$SizeMB = "0:F3" -f ($FileStats.Sum / 1024) -as [decimal]
$MySplitPath = Split-Path -Path $Path -Leaf
Invoke-SQL -sqlCommand = "
IF EXISTS (SELECT * from EFP_HomeFolder_Stats where UserInitials = '$MySplitPath')
BEGIN
UPDATE EFP_HomeFolder_Stats SET UserInitials = '$MySplitPath', TotalFileCount = $FileStats.Count, TotalDirectoryCount = $DirectoryCount, TotalFolderSizeInMB = $SizeMB, LastUpdated = GETDATE()
END
ELSE
BEGIN
INSERT INTO EFP_HomeFolder_Stats (UserInitials,TotalFileCount,TotalDirectoryCount,TotalFolderSizeInMB,LastUpdated) VALUES('$MySplitPath',$FileStats.Count,$DirectoryCount,$SizeMB,GETDATE());
END
"
if ($PSBoundParameters.ContainsKey("Recurse"))
Get-DirectoryTreeSize -Path $Path
$FolderList = Get-ChildItem -Path $Path -Directory -Recurse | select -ExpandProperty FullName
if ($FolderList)
foreach ($Folder in $FolderList)
$FileStats = Get-ChildItem -Path $Folder -File | Measure-Object -Property Length -Sum
$FileCount = $FileStats.Count
$DirectoryCount = Get-ChildItem -Path $Folder -Directory | Measure-Object | select -ExpandProperty Count
$SizeMB = "0:F3" -f ($FileStats.Sum / 1MB) -as [decimal]
[PSCustomObject]@
Path = $Folder
FileCount = $FileCount
DirectoryCount = $DirectoryCount
FolderSizeInMB = $SizeMB
#clearing variables
$null = $FileStats
$null = $FileCount
$null = $DirectoryCount
$null = $SizeMB
catch
Write-Error $_.Exception.Message
END
foreach ($name in Get-ChildItem "\\FILSRV01\home dir$"| Where $_.PSIsContainer | Where $_.PSIsContainer | Select-Object name)
Write-Output $($null)
$TopPath = "\\FILSRV01\home dir$\"
$TempPath = Join-Path $TopPath $name."name"
Get-DirectoryTreeSize $TempPath -AllItemsAndAllFolders
【讨论】:
以上是关于如何在 PowerShell 中将计算值写入 SQL INSERT/UPDATE的主要内容,如果未能解决你的问题,请参考以下文章
如何在powershell中将嵌套的任意关联数组值设置为.psd1文件?
在Powershell中将hashtable与循环中的类似值进行比较