有人可以指出我在下面的 PowerShell 脚本中犯了错误吗?我正在尝试收集 SQL Server 相关信息并将该信息加载到 Oracle 数据库中,该数据库是我们用于保存环境相关信息的存储库。该脚本在更新/插入期间吐出列 Server_Name 不能为空的错误(请参阅日志),但当我回显该变量时,它确实包含 Server_Name 列值。也许我加载数据的方式是错误的,或者也许某个地方存在语法错误?任何帮助将不胜感激。
#Import necessary modules
Import-Module DBAtools
# Path to the Oracle.ManagedDataAccess.dll file
$oracleDllPath = "D:\oracle\product\12.2.0\client_1\odp.net\managed\common\Oracle.ManagedDataAccess.dll"
# Load the assembly
Add-Type -Path $oracleDllPath
# Initialize logging
$logFile = "D:\PowerShell\log.txt"
Start-Transcript -Path $logFile
WRITE-HOST "WE ARE HERE-1"
try {
# Step 1: Get all instance names from Central Management Studio and place them in a variable called $Instances
#$CMSInstance = "CentralManagementServerInstanceName"
#$Instances = Get-DbaCmsRegServer -SqlInstance $CMSInstance -Group "" | Select-Object -ExpandProperty Name
$Instances = "SQLInst1","SQLInst2"
# Initialize arrays to hold accessible and inaccessible instances
$AccessibleInstances = @()
$InaccessibleInstances = @()
# Step 2: Ensure each instance is accessible
foreach ($Instance in $Instances) {
try {
# Check if the instance is accessible
Test-DbaConnection -SqlInstance $Instance -ErrorAction Stop
# If successful, add to AccessibleInstances
$AccessibleInstances += $Instance
} catch {
# If not accessible, add to InaccessibleInstances
$InaccessibleInstances += $Instance
}
}
WRITE-HOST "WE ARE HERE-2"
# Initialize arrays to hold data
$serverStageData = @()
$diskDriveStageData = @()
# Step 5: Loop through each entry in $AccessibleInstances and gather required information
foreach ($Instance in $AccessibleInstances) {
# Example DBAtools commands (replace with actual commands as needed)
$server = Connect-DbaInstance -SqlInstance $Instance
# Gathering Operating System Information
$os = Get-DbaOperatingSystem -ComputerName $server.ComputerName
$computerSystem = Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName $server.ComputerName
$cpu = Get-CimInstance -ClassName Win32_Processor -ComputerName $server.ComputerName
$networkConfig = Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -ComputerName $server.ComputerName | Where-Object { $_.IPAddress -ne $null }
WRITE-HOST "WE ARE HERE-3"
# Creating the output object
$serverInfo = [PSCustomObject]@{
ServerName = $server.ComputerName
OSName = $os.OSVersion
OSVersionCode = $os.Version
OSVendorName = $os.Manufacturer
OSPatchLevelCode = $os.Build
CPUVendorName = $cpu.Name[0]
CPUManufacturerName = $cpu.Manufacturer[0]
CPUFrequencyMSR = $cpu.MaxClockSpeed[0]
PhysicalCoreCount = ($cpu | Measure-Object -Property NumberOfCores -Sum).Sum
TotalCoreCount = ($cpu | Measure-Object -Property NumberOfLogicalProcessors -Sum).Sum
PhysicalRAMGBMSR = [math]::round($computerSystem.TotalPhysicalMemory / 1GB, 2)
RAMGBMSR = [math]::round($computerSystem.TotalPhysicalMemory / 1GB, 2)
DomainName = $computerSystem.Domain
OperationalStatusCode = $computerSystem.Status
ManagedByServerName = 'CMS'
IPAddress = $networkConfig.IPAddress[0]
MANAGED_BY_DATABASE_NAME = 'DBAAdmin'
}
WRITE-HOST "WE ARE HERE-4"
#2.TABLE DISK_DRIVE_STAGE
$diskDriveInfo = Get-DbaDiskSpace -ComputerName $server.ComputerName | Select-Object @{label='SERVER_NAME';expression={$_.ComputerName}}, @{label='DISK_DRIVE_NAME';expression={$_.Label}}, @{label='CAPACITY_GB_MSR';expression={$_.SizeInGB}}, @{label='USED_GB_MSR';expression={$_.SizeInGB - $_.FreeInGB}}, @{label='FREE_SPACE_GB_MSR';expression={$_.FreeInGB}}, @{label='DISK_DRIVE_LETTER_CODE';expression={$_.Name}}, @{label='LINUX_MOUNT_POINT_PATH';expression={'N/A'}}
# Store the gathered information in the respective variables
$serverStageData += $serverInfo
#$diskDriveStageData += $diskDriveInfo
}
# Step 6: Connect to the Oracle database
$oracleConnString = "User Id=myuser;Password=mypwd;Data Source=myoracledb"
$conn = New-Object Oracle.ManagedDataAccess.Client.OracleConnection($oracleConnString)
WRITE-HOST "WE ARE HERE-5"
try {
$conn.Open()
WRITE-HOST "WE ARE HERE-6"
Write-Host "Successfully connected to Oracle database."
} catch {
WRITE-HOST "WE ARE HERE-7"
Write-Host "Failed to connect to Oracle database. Exiting script."
Stop-Transcript
Exit 1
}
WRITE-HOST "WE ARE HERE-8"
# Step 7: Function to update or insert records in Oracle tables.
function Upsert-OracleTable {
param (
[string]$tableName,
[array]$data,
[array]$columns
)
foreach ($record in $data) {
# Ensure no null values are inserted by checking each value
foreach ($column in $columns) {
if ([string]::IsNullOrEmpty($record.$column)) {
Write-Host "Column $column cannot be null. Record: $record"
throw "Column $column cannot be null"
}
}
# Build the query to check if the record exists by comparing all columns
$whereClause = @()
foreach ($column in $columns) {
$whereClause += "$column = :$column"
}
$whereClause = $whereClause -join " AND "
$checkCmd = $conn.CreateCommand()
$checkCmd.CommandText = "SELECT COUNT(*) FROM $tableName WHERE $whereClause"
$checkCmd.Parameters.Clear()
foreach ($column in $columns) {
$checkCmd.Parameters.Add((New-Object Oracle.ManagedDataAccess.Client.OracleParameter($column, $record.$column)))
}
$exists = $checkCmd.ExecuteScalar()
if ($exists -ne 0) {
# Build the update clause
$updateClause = ""
$updateNeeded = $false
foreach ($column in $columns) {
$currentValueCmd = $conn.CreateCommand()
$currentValueCmd.CommandText = "SELECT $column FROM $tableName WHERE $whereClause"
$currentValueCmd.Parameters.Clear()
foreach ($col in $columns) {
$currentValueCmd.Parameters.Add((New-Object Oracle.ManagedDataAccess.Client.OracleParameter($col, $record.$col)))
}
$currentValue = $currentValueCmd.ExecuteScalar()
if ($currentValue -ne $record.$column) {
$updateClause += "$column = :$column, "
$updateNeeded = $true
}
}
if ($updateNeeded) {
# Remove the last comma
$updateClause = $updateClause.Substring(0, $updateClause.Length - 2)
# Build and execute the update command
$updateCmd = $conn.CreateCommand()
$updateCmd.CommandText = "UPDATE $tableName SET $updateClause WHERE $whereClause"
$updateCmd.Parameters.Clear()
foreach ($column in $columns) {
$updateCmd.Parameters.Add((New-Object Oracle.ManagedDataAccess.Client.OracleParameter($column, $record.$column)))
}
$updateCmd.ExecuteNonQuery()
}
} else {
# Build and execute the insert command
$columnsStr = ""
$valuesStr = ""
$insertCmd = $conn.CreateCommand()
foreach ($column in $columns) {
$columnsStr += "$column, "
$valuesStr += ":$column, "
$insertCmd.Parameters.Add((New-Object Oracle.ManagedDataAccess.Client.OracleParameter($column, $record.$column)))
}
# Remove the last commas
$columnsStr = $columnsStr.Substring(0, $columnsStr.Length - 2)
$valuesStr = $valuesStr.Substring(0, $valuesStr.Length - 2)
$insertCmd.CommandText = "INSERT INTO $tableName ($columnsStr) VALUES ($valuesStr)"
Write-Host "Insert Command: $insertCmd.CommandText"
foreach ($param in $insertCmd.Parameters) {
Write-Host "Parameter: $($param.ParameterName) = $($param.Value)"
}
$insertCmd.ExecuteNonQuery()
}
}
}
WRITE-HOST "WE ARE HERE-14"
# Update or insert records in Oracle tables with specific columns
$serverColumns = @("SERVER_NAME", "OPERATING_SYSTEM_NAME", "OPERATING_SYSTEM_VERSION_CODE", "OPERATING_SYSTEM_VENDOR_NAME", "OPERATING_SYSTEM_PTCH_LVL_CODE", "CPU_VENDOR_NAME", "CPU_MANUFACTURER_NAME", "CPU_FREQUENCY_MSR", "PHYSICAL_CORE_CNT", "TOTAL_CORE_CNT", "PHYSICAL_RAM_GB_MSR", "RAM_GB_MSR", "DOMAIN_NAME", "OPERATIONAL_STATUS_CODE", "MANAGED_BY_SERVER_NAME", "IP_ADDRESS", "MANAGED_BY_DATABASE_NAME")
#$diskDriveColumns = @("SERVER_NAME", "DISK_DRIVE_NAME", "CAPACITY_GB_MSR", "FREE_SPACE_GB_MSR", "DISK_DRIVE_LETTER_CODE", "LINUX_MOUNT_POINT_PATH")
WRITE-HOST "WE ARE HERE-15"
# Specify the schema name for each table
$serverTable = "MySchema.SERVER_STAGE_T"
# $diskDriveTable = "MyShema.DISK_DRIVE_STAGE_T"
WRITE-HOST "WE ARE HERE-16"
echo $serverColumns
echo $serverStageData
echo $serverTable
Upsert-OracleTable -tableName $serverTable -data $serverStageData -columns $serverColumns
#Upsert-OracleTable -tableName $diskDriveTable -data $diskDriveStageData -columns $diskDriveColumns
WRITE-HOST "WE ARE HERE-17"
} catch {
Write-Host "An error occurred: $_"
Stop-Transcript
Exit 1
} finally {
# Close the Oracle connection
$conn.Close()
Stop-Transcript
}
与oracle的连接工作正常
用户有足够的权限在表中插入/更新数据。
错误: 列 SERVER_NAME 不能为空。
Record: @{ServerName=Server1; OSName=Microsoft Windows Server 2016 Standard; OSVersionCode=10.0.14393; OSVendorName=Microsoft Corporation; OSPatchLevelCode=14393; CPUVendorName=Intel(R) Xeon(R) Platinum 8170 CPU @ 2.10GHz; CPUManufacturerName=GenuineIntel; CPUFrequencyMSR=2095; PhysicalCoreCount=4; TotalCoreCount=4; PhysicalRAMGBMSR=48; RAMGBMSR=48; DomainName=my.domain; OperationalStatusCode=OK; ManagedByServerName=CMSServer; IPAddress=12.11.196.258; MANAGED_BY_DATABASE_NAME=DBAAdmin}
PS>TerminatingError(): "Column SERVER_NAME cannot be null"
发生错误:列 SERVER_NAME 不能为空
问题是您的
$serverStageData
对象由包含这些键的元素组成:
$serverInfo = [PSCustomObject]@{
ServerName = $server.ComputerName
OSName = $os.OSVersion
OSVersionCode = $os.Version
OSVendorName = $os.Manufacturer
OSPatchLevelCode = $os.Build
CPUVendorName = $cpu.Name[0]
CPUManufacturerName = $cpu.Manufacturer[0]
CPUFrequencyMSR = $cpu.MaxClockSpeed[0]
PhysicalCoreCount = ($cpu | Measure-Object -Property NumberOfCores -Sum).Sum
TotalCoreCount = ($cpu | Measure-Object -Property NumberOfLogicalProcessors -Sum).Sum
PhysicalRAMGBMSR = [math]::round($computerSystem.TotalPhysicalMemory / 1GB, 2)
RAMGBMSR = [math]::round($computerSystem.TotalPhysicalMemory / 1GB, 2)
DomainName = $computerSystem.Domain
OperationalStatusCode = $computerSystem.Status
ManagedByServerName = 'CMS'
IPAddress = $networkConfig.IPAddress[0]
MANAGED_BY_DATABASE_NAME = 'DBAAdmin'
}
并且您正在尝试使用这些列名称插入表中:
$serverColumns = @("SERVER_NAME",
"OPERATING_SYSTEM_NAME",
"OPERATING_SYSTEM_VERSION_CODE",
"OPERATING_SYSTEM_VENDOR_NAME",
"OPERATING_SYSTEM_PTCH_LVL_CODE",
"CPU_VENDOR_NAME",
"CPU_MANUFACTURER_NAME",
"CPU_FREQUENCY_MSR",
"PHYSICAL_CORE_CNT",
"TOTAL_CORE_CNT",
"PHYSICAL_RAM_GB_MSR",
"RAM_GB_MSR",
"DOMAIN_NAME",
"OPERATIONAL_STATUS_CODE",
"MANAGED_BY_SERVER_NAME",
"IP_ADDRESS",
"MANAGED_BY_DATABASE_NAME")
代码失败,因为
$serverInfo
对象的属性名称与您提供的 $serverColumns
不匹配。更新代码以使它们匹配,这可能还需要您更新要向其中插入数据的基础 Oracle 表。
您看到的错误是由于这部分函数造成的:
if ([string]::IsNullOrEmpty($record.$column)) {
Write-Host "Column $column cannot be null. Record: $record"
throw "Column $column cannot be null"
}
您的错误消息显示:
Record: @{ServerName=Server1;
Column SERVER_NAME cannot be null
以下简短的代码片段重现了该错误:
function Upsert-OracleTable {
param (
#[string]$tableName,
[array]$data,
[array]$columns
)
foreach ($record in $data) {
# Ensure no null values are inserted by checking each value
foreach ($column in $columns) {
if ([string]::IsNullOrEmpty($record.$column)) {
Write-Host "Column $column cannot be null. Record: $record"
throw "Column $column cannot be null"
}
}
}
}
$serverStageData = @([PSCustomObject]@{"ServerName"="Server1"})
echo $serverStageData
Upsert-OracleTable `
-data $serverStageData `
-columns @("SERVER_NAME")