Используйте Powershell для вставки данных в несколько столбцов в SQL Server

111
17

Я пытаюсь вставить данные, собранные из VMware vCenter, в базу данных, используя Powershell и SQL Server.

Это то, что у меня есть сейчас:

$conn = New-Object System.Data.SqlClient.SqlConnection
$conn.ConnectionString = "Data Source=.\sqlexpress;Initial Catalog=Computer;Integrated Security=SSPI;"
$conn.open()
$cmd = New-Object System.Data.SqlClient.SqlCommand
$cmd.connection = $conn

$val = 0
$clusterinf = foreach($cluster in Get-Cluster){
$esx = $cluster | Get-VMHost
$ds = Get-Datastore -VMHost $esx | where {$_.Type -eq "VMFS"}

$cluster | Select @{N="VCname";E={$cluster.Uid.Split(':@')[1]}},
@{N="DCname";E={(Get-Datacenter -Cluster $cluster).Name}},
@{N="Clustername";E={$cluster.Name}},
@{N="TotalPhysicalMemory";E={[Math]::Round(($esx | Measure-Object -Property MemoryTotalMB -Sum).Sum /1KB)}},
@{N="TotalUsedMemory";E={[Math]::Round(($esx | Measure-Object -Property MemoryUsageMB -Sum).Sum /1KB)}},
@{N="AvailableMemroy";E={[Math]::Round(($esx | Measure-Object -InputObject {$_.MemoryTotalMB - $_.MemoryUsageMB} -Sum).Sum /1KB)}},
@{N="TotalCPU";E={[Math]::Round(($esx | Measure-Object -Property CpuTotalMhz -Sum).Sum /1KB)}},
@{N="TotalUsedCPU";E={[Math]::Round(($esx | Measure-Object -Property CpuUsageMhz -Sum).Sum /1KB)}},
@{N="AvailableCPU";E={[Math]::Round(($esx | Measure-Object -InputObject {$_.CpuTotalMhz - $_.CpuUsageMhz} -Sum).Sum /1KB)}},
@{N="TotalDiskSpace";E={[Math]::Round(($ds | where {$_.Type -eq "VMFS"} | Measure-Object -Property CapacityMB -Sum).Sum /1KB)}},
@{N="ConfiguredDiskSpace";E={[Math]::Round(($ds | Measure-Object -InputObject {$_.CapacityMB - $_.FreeSpaceMB} -Sum).Sum /1KB)}},
@{N="AvailableDiskSpace";E={[Math]::Round(($ds | Measure-Object -Property FreeSpaceMB -Sum).Sum /1KB)}},
@{N="Total Configured Memory GB For Powered on VMs";E={[Math]::Round(($_ | Get-VM | Where-Object {$_.PowerState -eq "PoweredOn"} | %{$_.MemoryMB} | Measure-Object -Sum | Select -ExpandProperty Sum)/1KB) }}

$cmd.commandtext = "INSERT INTO Clusterinfo (VCname) VALUES('{$val}')" -f $clusterinf.VCname
$cmd.ExecuteNonQuery()
$val++

}
$conn.close()

И это работает, как я предполагал. Теперь мой вопрос: как мне продолжить следующий столбец? Чтобы добавить DCname, Clustername, TotalPhysicalMemory и т.д.?

Я пытался с этим вставкой:

$cmd.commandtext = "INSERT INTO Clusterinfo (VCname, DCname, CLustername) VALUES('$($clusterinf.VCname)','$($clusterinf.DCname)','$($clusterinf.Clustername)')"

Но это не VCname, что он DCname результат, так как он будет вставлять каждое имя VCname, имя DCname и т.д. В одну строку, а не в разные строки.

Я рассматривал этот вопрос: Powershell Как запросить несколько классов и написать в таблицу SQL

Но я, похоже, не могу решить мою проблему.

Кто-нибудь понял, как это решить?

спросил(а) 2021-01-19T21:11:14+03:00 6 месяцев, 1 неделя назад
1
Решение
110

$clusterinf должен быть объектом с данными текущего кластера, а не результатом всего цикла foreach.

Я бы попробовал что-то вроде этого:

$conn = New-Object System.Data.SqlClient.SqlConnection
$conn.ConnectionString = "Data Source=.\sqlexpress;Initial Catalog=Computer;Integrated Security=SSPI;"
$conn.open()
$cmd = New-Object System.Data.SqlClient.SqlCommand
$cmd.connection = $conn

foreach($cluster in (Get-Cluster)){

$esx = $cluster | Get-VMHost
$ds = Get-Datastore -VMHost $esx | where {$_.Type -eq "VMFS"}

$clusterinf = $cluster | Select @{N="VCname";E={$cluster.Uid.Split(':@')[1]}},
@{N="DCname";E={(Get-Datacenter -Cluster $cluster).Name}},
@{N="Clustername";E={$cluster.Name}},
@{N="TotalPhysicalMemory";E={[Math]::Round(($esx | Measure-Object -Property MemoryTotalMB -Sum).Sum /1KB)}},
@{N="TotalUsedMemory";E={[Math]::Round(($esx | Measure-Object -Property MemoryUsageMB -Sum).Sum /1KB)}},
@{N="AvailableMemroy";E={[Math]::Round(($esx | Measure-Object -InputObject {$_.MemoryTotalMB - $_.MemoryUsageMB} -Sum).Sum /1KB)}},
@{N="TotalCPU";E={[Math]::Round(($esx | Measure-Object -Property CpuTotalMhz -Sum).Sum /1KB)}},
@{N="TotalUsedCPU";E={[Math]::Round(($esx | Measure-Object -Property CpuUsageMhz -Sum).Sum /1KB)}},
@{N="AvailableCPU";E={[Math]::Round(($esx | Measure-Object -InputObject {$_.CpuTotalMhz - $_.CpuUsageMhz} -Sum).Sum /1KB)}},
@{N="TotalDiskSpace";E={[Math]::Round(($ds | where {$_.Type -eq "VMFS"} | Measure-Object -Property CapacityMB -Sum).Sum /1KB)}},
@{N="ConfiguredDiskSpace";E={[Math]::Round(($ds | Measure-Object -InputObject {$_.CapacityMB - $_.FreeSpaceMB} -Sum).Sum /1KB)}},
@{N="AvailableDiskSpace";E={[Math]::Round(($ds | Measure-Object -Property FreeSpaceMB -Sum).Sum /1KB)}},
@{N="Total Configured Memory GB For Powered on VMs";E={[Math]::Round(($_ | Get-VM | Where-Object {$_.PowerState -eq "PoweredOn"} | %{$_.MemoryMB} | Measure-Object -Sum | Select -ExpandProperty Sum)/1KB) } }

$cmd.commandtext = "INSERT INTO Clusterinfo (VCname, Clustername, TotalPhysicalMemory, TotalUsedMemory, AvailableMemroy, TotalCPU, TotalUsedCPU, AvailableCPU, TotalDiskSpace, ConfiguredDiskSpace, AvailableDiskSpace) VALUES('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}','{8}','{9}','{10}')" -f $clusterinf.VCname, $clusterinf.Clustername, $clusterinf.TotalPhysicalMemory, $clusterinf.TotalUsedMemory, $clusterinf.AvailableMemroy, $clusterinf.TotalCPU, $clusterinf.TotalUsedCPU, $clusterinf.AvailableCPU, $clusterinf.TotalDiskSpace, $clusterinf.ConfiguredDiskSpace, $clusterinf.AvailableDiskSpace
$cmd.ExecuteNonQuery()
}

$conn.close()

В качестве примечания следует заменить командный текст на значения параметрами. Он менее подвержен внедрению SQL и, по моему мнению, намного чище. См. Эту ссылку

ответил(а) 2021-01-19T21:11:14+03:00 6 месяцев, 1 неделя назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема