5

信じられませんが、PowerShell コードがSELECT1 つのレコードをオブジェクトとして検索するクエリの結果を返していることをすべて示していますが、2 つ以上のレコードがある場合、同じコードはオブジェクトの配列を返します。私は何を間違っていますか?

以下はコードです:

function Connect-MySQL([string]$MySQLHost, [string]$user, [string]$pass, [string]$database) { 
    Write-Verbose "Connect-MySQL"
    # Load MySQL .NET Connector Objects 
    [void][system.reflection.Assembly]::LoadWithPartialName("MySql.Data") 

    # Open Connection 
    $connStr = "server=$MySQLHost;port=3306;uid=$user;pwd=$pass;database=$database;Pooling=FALSE" 
    try {
        $con = New-Object MySql.Data.MySqlClient.MySqlConnection($connStr) 
        $con.Open()
    } catch [System.Management.Automation.PSArgumentException] {
        Write-Verbose "Unable to connect to MySQL server, do you have the MySQL connector installed..?"
        Write-Verbose $_
        Exit
    } catch {
        Write-Verbose "Unable to connect to MySQL server..."
        Write-Verbose $_.Exception.GetType().FullName
        Write-Verbose $_.Exception.Message
        exit
    }
    Write-Verbose "Connected to MySQL database $MySQLHost\$database"

    return $con 
}

function Disconnect-MySQL($con) {
    Write-Verbose "Disconnect-MySQL"
    $con.Close()
}

function Execute-MySQLNonQuery($con, [string]$sql) { 
    $cmd = New-Object MySql.Data.MySqlClient.MySqlCommand($sql, $con)            # Create SQL command
    $Rows = $cmd.ExecuteNonQuery()                                               # Execute command
    $cmd.Dispose()                                                               # Dispose of command object
#   if ($Rows) { 
        return $Rows
#   } else { 
#       return $false 
#   } 
} 

function Execute-MySQLQuery($con, [string]$sql) { 
    $cmd = New-Object MySql.Data.MySqlClient.MySqlCommand($sql, $con)            # Create SQL command
    $dataAdapter = New-Object MySql.Data.MySqlClient.MySqlDataAdapter($cmd)      # Create data adapter from query command
    $dataSet = New-Object System.Data.DataSet                                    # Create dataset
    $dataAdapter.Fill($dataSet, "data") | Out-Null                               # Fill dataset from data adapter, with name "data"              
    $cmd.Dispose()                                                               # Dispose of command object
    return $dataSet.Tables["data"]                                               # Returns an array of results
}


# Connection Variables 
$MySQLHost = '10.10.10.111' 
$user = 'user' 
$pass = 'test' 
$database = 'test_db' 

# Connect to MySQL Database 
$con = Connect-MySQL $MySQLHost $user $pass $database

# Get requests
$sql = "
SELECT *
FROM o365_statuses as x
WHERE x.action = 'Z'
AND x.status = 0"
$result = Execute-MySQLQuery $con $sql

Write-Host $result.Count
Foreach ($r in $result) {
    write-host "$($r.id) $($r.email)"
}

$resultが 1 レコードのみの場合、$result.Count何も返さず、列に as$result.idおよび notとしてアクセスできます$result[0].id。返されるレコードが 2 つ以上ある場合は、その逆になります。

私が何か間違ったことをしていて、これが PowerShell の動作ではないことを教えてください。

4

2 に答える 2

5

PowerShell は、次の単純なアルゴリズムに基づいて結果を返します。

  • 複数のアイテム --> それらのアイテムの配列を返す
  • 1点だけ --> 返品する

多くの場合、次のいずれかを使用して、常に配列を返すように PowerShell を強制することをお勧めします。

,(code)
@(code)

ただし、これらの演算子は同一ではありません。配列出力を強制するために、グループ化演算子を何にでも安全に適用できます。たとえば@()、配列には常にプロパティがあります。Count

$a = @(Get-Process | select -First 2); $a.Count   # returns 2
$a = @(Get-Process | select -First 1); $a.Count   # returns 1

一方、コンマ配列構築演算子は次のように機能します。

$a = ,(Get-Process | select -First 2); $a.Count   # returns 1
$a = ,(Get-Process | select -First 1); $a.Count   # returns 1

...与えられたものでネストされた配列を構築するためです。

于 2012-10-31T20:21:55.197 に答える
1

関数は、返されたコレクションを「アンロール」します。つまり、実際には null (0 項目) または単一のオブジェクト (プロパティを持っている場合と持ってCountいない場合がありますが、あなたの場合は持っていません) または 2 つ以上のオブジェクトの配列 (ただし、元のコレクション インスタンスではありません)。

アンロールを回避するには、次の,演算子を使用します。

return , $Rows

コンマ演算子は、単一のオブジェクト (オペランド) の配列、つまり新しいコレクションを作成します。この新しいコレクションも戻り時に展開されますが、再帰的には展開されません。つまり$Rows、同じインスタンスである単一のオブジェクトが返されます。

于 2012-10-29T06:28:07.807 に答える