Возврат SQL-запроса в виде массива в Powershell
у меня есть сервер SQL 2008 Ent с базами данных "DBOne", "DBTwo", "DBThree" на сервере DEVSQLSRV.
вот мой сценарий Powershell:
$DBNameList = (Invoke-SQLCmd -query "select Name from sysdatabases" -Server DEVSQLSRV)
это создает мой желаемый список имен баз данных как:
Name
-----
DBOne
DBTwo
DBThree
я предположил, что все, что возвращается в виде списка, является массивом в Powershell. Однако, когда я затем попробую это в Powershell:
$DBNameList -contains 'DBTwo'
он возвращается имеет "False" вместо "True", что приводит меня к поверьте, что мой список не является фактическим массивом.
есть идеи, что я упускаю здесь?
спасибо!
эмо
5 ответов
Я бы сделал так:
$DBNameList = @(Invoke-SQLCmd -query "select Name from sysdatabases" -Server DEVSQLSRV) | select-object -expand Name
это даст вам массив имен.Вариант -contains
должно работать нормально.
в исходном сообщении отсутствует какой-либо тип преобразования из объекта в массив.
Powershell выводит результат $DBNameList, потому что он как бы интерпретирует объект. Но если вам нужно манипулировать этим объектом и определить конкретный пункт, это метод, который я использую:
$Itm = "DBTwo"
$DBNameList = @(Invoke-SQLCmd -query "select Name from sysdatabases" -Server DEVSQLSRV)
$NameList = @($DBNameList | select-object -ExpandProperty Name)
$Name = ($NameList.Split()).Contains($Itm)
Write-Output $Name
True
Я искал это сам некоторое время и, наконец, понял это, поэтому я надеюсь, что это поможет кому-то еще!
заголовок Name предполагает, что это один объект со свойством Name, которое является массивом.
Я считаю, инициализировать пустой массив PS:
$DBNameList = (Invoke-SQLCmd -query "select Name from sysdatabases" -Server DEVSQLSRV)
[Array]$DbNames = @()
$DBNameList.Name | ForEach-Object {$DbNames += $_}
$DbNames -contains "DBTwo"
что-нибудь?
ваш код...
$DBNameList = (Invoke-SQLCmd -query "select Name from sysdatabases" -Server DEVSQLSRV)
...дает вам Datarows обратно..
вы можете проверить это с помощью
$DBNameList | Get-Member
вы также можете видеть, что есть свойство с именем "Name".
Если вы хотите проверить, содержит ли один из потоков данных в вашем $DBNameList имя "DBTwo", вам нужно будет написать следующее:
$DBNameList.Name -contains 'DBTwo'
все еще очень новый для Powershell (менее двух недель): я предлагаю вам попробовать это, если ваш запрос содержит несколько столбцов и строк... Многомерные Массивы. Это была моя первая попытка, и после проверки интернета, учитывая, что я не мог найти простое прямое решение, я закончил писать свое собственное решение. Вот полный набор примеров кода для экспериментов и использования.
полный набор кода образца ниже....
#############################################################################################
# RDSago
# RDSago@gmail.com
# 09/20/2014
#############################################################################################
#
# Capturing database size information from a collection of servers
# and returning that back to an array that can be used to populate
# a SQL table that can be used for monitoring database growth remotely.
# RDSago, RDSago@gmail.com
#
# Note, SQL data retrieved in this manner, does not have to be parsed
# before it is consumed and used elsewhere, just like any array you have defined.
# The data only needs to be addressed by its ".identityname" captured in the
# array $queryResults (shown below).
#
############################################################################################
#############################################################################################
# T-SQL for creating table to hold data returned
#
# CREATE TABLE [dba].[tbl_dbfilesize](
# [ServerNameInstance] [varchar](20) NULL,
# [DatabaseName] [varchar](30) NULL,
# [DataFileSizeMB] [numeric](20, 0) NULL,
# [LogFileSizeMB] [numeric](20, 0) NULL,
# [TotalDatabaseSizeMB] [numeric](20, 0) NULL,
# [CollectionDate] [date] NULL
# ) ON [PRIMARY]
#############################################################################################
Try
{
#define your connection points
# first create an array that will hold the server/instance name of the servers you wish to audit
# the first sever assumes a named instance, the second a default instance name.
$SourceServerName = @("ServerName01/InstanceName", "ServerName02", "ServerName03") # Server you will retrieve data from
#next define the server connection for where you will write your data back to
$TargetServerInstance = "TaretServerName"
# define your sql query that will be used to pull data from SQL on the Source Server
$qryDatabaseInfo = "
SELECT @@ServerName as ServerNameInstance,
DB.name as DatabaseName,
SUM(CASE WHEN type = 0 THEN MF.size * 8 / 1024 ELSE 0 END) AS DataFileSizeMB,
SUM(CASE WHEN type = 1 THEN MF.size * 8 / 1024 ELSE 0 END) AS LogFileSizeMB,
SUM(CASE WHEN type = 1 THEN MF.size * 8 / 1024 ELSE 0 END) + SUM(CASE WHEN type = 0 THEN MF.size * 8 / 1024 ELSE 0 END) AS TotalDatabaseSizeMB
FROM sys.master_files MF
JOIN sys.databases DB ON DB.database_id = MF.database_id
GROUP BY DB.name
ORDER BY DB.NAME ASC
"
#Loop through all the servers you wish to audit
ForEach ($SourceServerName in $SourceServerNames)
{
#execute query to pull data from server into an array
$queryResults = @(Invoke-SQLCmd -query $qryDatabaseInfo -Server $SourceServerInstance)
# Next, construct your insert statement from data in your $queryresults array.
Foreach ($queryResult in $queryResults)
{
$query = "
Insert Into [DBS_AUDIT_SERVERS].[dba].[tbl_dbfilesize]
([ServerNameInstance],
[DatabaseName],
[DataFileSizeMB],
[LogFileSizeMB],
[TotalDatabaseSizeMB],
[CollectionDate])
Values
(" +
"'" + $SourceServerInstance + "'," +
"'" + $queryResult.DatabaseName + "'," +
"'" + $queryResult.DataFileSizeMB + "'," +
"'" + $queryResult.LogFileSizeMB + "'," +
"'" + $queryResult.TotalDatabaseSizeMB + "'," +
"'" + $Date + "'" +
")"
""
#execute insert statement for sql
Invoke-Sqlcmd -Query $query -ServerInstance $TargetServerInstance
}
}
}
Catch [Exception]
{
$ErrorMessage = $_.Exception.Message
Write-Host $ErrorMessage
}
Finally
{
Write-Host "Completed Successfully"
}
Return 0;