PowerShell 脚本插入记录失败

问题描述 投票:0回答:1

有人可以指出我在下面的 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 不能为空

oracle powershell dbatools
1个回答
0
投票

问题是您的

$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")
© www.soinside.com 2019 - 2024. All rights reserved.