微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

PowerShell :: SQL SELECT 只返回第一行

如何解决PowerShell :: SQL SELECT 只返回第一行

我有一种奇怪的感觉,我在这里做错了什么。

这是我的 PowerShell 脚本,当然是从 here 窃取和改编的:

param(
    $instance = "localhost"
)

if (!(Get-Module -ListAvailable -Name "sqlPS")) {
    Write-Host -BackgroundColor Red -ForegroundColor White "Module Invoke-sqlcmd is not loaded"
    exit
}

#Function to execute queries (depending on if the user will be using specific credentials or not)
function Execute-Query([string]$query,[string]$database,[string]$instance,[int]$trusted,[string]$username,[string]$password){
    if($trusted -eq 1){
        try{ 
            Invoke-sqlcmd -Query $query -Database $database -ServerInstance $instance -ErrorAction Stop -ConnectionTimeout 5 -QueryTimeout 0      
        }
        catch{
            Write-Host -BackgroundColor Red -ForegroundColor White $_
            exit
        }
    }
    else{
        try{
            Invoke-sqlcmd -Query $query -Database $database -ServerInstance $instance -Username $username -Password $password -ErrorAction Stop -ConnectionTimeout 5 -QueryTimeout 0
        }
         catch{
            Write-Host -BackgroundColor Red -ForegroundColor White $_
            exit
        }
    }
}

function List-of-Databases([string]$instance,[string]$login,[string]$password){
    $ctpQuery = "
    SELECT name 
    FROM master.dbo.sysdatabases
    "

    return $(Execute-Query $ctpQuery "master" $instance $trusted $login $password)[0]
}

function Check-SysAdminLogins([string]$instance,[string]$password){
    $sysadminLoginsQuery = "
    SELECT   name
    FROM     master.sys.server_principals 
    WHERE    IS_SRVROLEMEMBER ('sysadmin',name) = 1
    ORDER BY name
    "
    return $(Execute-Query $sysadminLoginsQuery "master" $instance $trusted $login $password)
}


$loginChoices = [System.Management.Automation.Host.ChoiceDescription[]] @("&Trusted","&Windows Login","&sql Login")
$loginChoice = $host.UI.PromptForChoice('','Choose login type for instance',$loginChoices,0)
switch($loginChoice)
{
    1 { 
        $login          = Read-Host -Prompt "Enter Windows Login"
        $securePassword = Read-Host -Prompt "Enter Password" -Assecurestring
        $password       = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::securestringToBSTR($securePassword))
      }
    2 { 
        $login          = Read-Host -Prompt "Enter sql Login"
        $securePassword = Read-Host -Prompt "Enter Password" -Assecurestring
        $password       = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::securestringToBSTR($securePassword))
      }
}

#Attempt to connect to the sql Server instance using the information provided by the user
try{
    switch($loginChoice){
        0       {$buildNumber = Execute-Query "SELECT 1" "master" $instance 1 "" ""}
        default {$buildNumber = Execute-Query "SELECT 1" "master" $instance 0 $login $password}   
    }     
}
catch{
    Write-Host -BackgroundColor Red -ForegroundColor White $_
    exit
}

#If the connection succeeds,then proceed with the verification of best practices
Write-Host ""
Write-Host "------------ ------------ ------------ ------------" 
Write-Host "************ ************ ************ ************" 
Write-Host "------------ ----         ----         ------------" 
Write-Host "    ****     ************ ************     ****    " 
Write-Host "    ----     ------------ ------------     ----    " 
Write-Host "    ****     ****                *****     ****    " 
Write-Host "    ----     ------------ ------------     ----    " 
Write-Host "    ****     ************ ************     ****    " 
Write-Host ""
#List of Databases
Write-Host "#####################"
Write-Host "# List of Databases #"
Write-Host "#####################"           
switch($loginChoice){
    0       {$lod = List-of-Databases $instance 1 "" ""}
    default {$lod = List-of-Databases $instance 0 $login $password}   
} 
foreach($database in $lod)
{
    Write-Host $database.name | Format-Table
}
Write-Host ""

#Logins with sysadmin privilege
Write-Host "##################################"
Write-Host "# Logins with sysadmin privilege #"
Write-Host "##################################"
switch($loginChoice){
    0       {$sysadminLogins = Check-SysadminLogins $instance 1 "" ""}
    default {$sysadminLogins = Check-SysadminLogins $instance 0 $login $password}   
} 
foreach($sysadminLogin in $sysadminLogins)
{
    Write-Host $sysadminLogin.name
}

Write-Host ""

如果你运行它,脚本就会成功执行:

enter image description here

问题是第二个查询

SELECT   name
FROM     master.sys.server_principals 
WHERE    IS_SRVROLEMEMBER ('sysadmin',name) = 1
ORDER BY name

正确返回所有行:

enter image description here

##################################
# Logins with sysadmin privilege #
##################################
NT SERVICE\sqlSERVERAGENT
NT SERVICE\sqlWriter
NT SERVICE\Winmgmt
sa

而第一个查询

SELECT name 
FROM master.dbo.sysdatabases

只返回SELECT语句的第一行,当然是master数据库

enter image description here

#####################
# List of Databases #
#####################
master

但是正如你所看到的,我在那里有很多数据库

我哪里错了?

解决方法

注意 return 语句末尾的数组索引:

return $(Execute-Query $ctpQuery "master" $instance $trusted $login $password)[0]

那只会返回第一行。试试:

return $(Execute-Query $ctpQuery "master" $instance $trusted $login $password)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。