2

我一直在努力解决这个问题。让我试着解释一下我想要完成的事情,我希望我能足够清楚。

我正在向 MSSQL 数据库发送两个查询并接收它们。下面的代码完美无缺,但是我想在 XML 写入 XML 文件之前稍微操作一下它的格式。我目前有 3 列(serviceGroupName、numAccounts、numDevices)我想完成两件事中的一件:

1)添加一个名为“ReportType”的新列,并根据它是通过foreach循环的第1个还是第2个来填写“Monthly”或“Total”(SQLQuery1是月度报告,SQLQuery2是自成立以来的总数)

2) 创建一个新的 PSObject 并让它填写适当的信息,例如它接收回来的数据 (serviceGroupName, numAccounts, numDevices)

以下是我当前的代码。正如我所提到的,它确实有效并且它生成了一个 XML,但如果可能的话,我想在管道之前添加一些更多信息到 ConvertTo-XML。

### Dates to use
$Date = (Get-Date -f MM-dd-yyyy)
$FDoTM = ((Get-Date -Day 01).AddMonths(0)).AddDays(0)
$LDo2PM = ((Get-Date -Day 01).AddMonths(-1)).AddDays(-1)
$TempDir = "C:\Temp"
$WebDir =     @("\\x.x.x.x\c$\inetpub\wwwroot\Reports\Accounts","\\x.x.x.x\c$\inetpub\wwwroot\Reports\Accounts")

### Something

$OutputXML = "$Date-Monthly-AccountReport.xml"

### Connection settings, uses windows authentication

$DBServer = "OMMITED"
$databasename = "OMMITED"
$Connection = new-object system.data.sqlclient.sqlconnection #Set new object to connect to sql database
$Connection.ConnectionString ="server=$DBServer;database=$databasename;trusted_connection=True" # Connectiongstring setting for local machine database with window authentication
Write-host "Connection Information:"  -foregroundcolor yellow -backgroundcolor black
$Connection #List connection information


### Connect to Database and Run Query

$SqlCmd = New-Object System.Data.SqlClient.SqlCommand #setting object to use sql commands

$OutputHeader1 = "This Month's counts"
$SqlQuery1 = @"

SET NOCOUNT ON;

WITH AccountDeviceStats(serviceGroupName,numAccounts,numDevices)
AS
(
    SELECT svg.name,COUNT(acct.serviceGroupId) as Accounts, NULL FROM bm_account acct WITH     (NOLOCK)
    INNER JOIN bm_servicegroup svg WITH (NOLOCK) ON svg.servicegroupId = acct.serviceGroupId

    where acct.CreateStamp between '$($LDo2PM)' and '$($FDoTM)'
GROUP BY acct.serviceGroupId,svg.name
UNION ALL
SELECT svg.name, NULL, COUNT(device.serviceGroupId) as Devices FROM bm_device device WITH (NOLOCK)
INNER JOIN bm_servicegroup svg WITH (NOLOCK) ON svg.servicegroupId = device.serviceGroupId, bm_account acct

where device.accountID=acct.accountId and acct.CreateStamp between '$($LDo2PM)' and '$($FDoTM)'
GROUP BY device.serviceGroupId,svg.name
)
SELECT ad1.serviceGroupName,ad1.numAccounts,ad2.numDevices FROM AccountDeviceStats ad1
INNER JOIN AccountDeviceStats ad2 ON ad1.serviceGroupName = ad2.serviceGroupName
WHERE ad1.numAccounts IS NOT NULL AND ad2.numDevices IS NOT NULL
ORDER BY numAccounts DESC,numDevices DESC
"@

$OutputHeader2 = "Total Counts"
$SqlQuery2 = @"

SET NOCOUNT ON;

WITH AccountDeviceStats(serviceGroupName,numAccounts,numDevices)
AS
(
SELECT svg.name,COUNT(acct.serviceGroupId) as Accounts, NULL FROM bm_account acct WITH     (NOLOCK)
INNER JOIN bm_servicegroup svg WITH (NOLOCK) ON svg.servicegroupId = acct.serviceGroupId

where acct.CreateStamp < '12-31-2099'
GROUP BY acct.serviceGroupId,svg.name
UNION ALL
SELECT svg.name, NULL, COUNT(device.serviceGroupId) as Devices FROM bm_device device WITH (NOLOCK)
INNER JOIN bm_servicegroup svg WITH (NOLOCK) ON svg.servicegroupId = device.serviceGroupId, bm_account acct

where device.accountID=acct.accountId and acct.CreateStamp < '12-31-2099'
GROUP BY device.serviceGroupId,svg.name
)
SELECT ad1.serviceGroupName,ad1.numAccounts,ad2.numDevices FROM AccountDeviceStats ad1
INNER JOIN AccountDeviceStats ad2 ON ad1.serviceGroupName = ad2.serviceGroupName
WHERE ad1.numAccounts IS NOT NULL AND ad2.numDevices IS NOT NULL
ORDER BY numAccounts DESC,numDevices DESC
"@

$sqlQueries = @($SqlQuery1, $SqlQuery2)

$Results = @()

Foreach ($Query in $sqlQueries){
    $Connection.open()
    Write-host "Connection to database successful." -foregroundcolor green -backgroundcolor black
    $SqlCmd.CommandText = $Query
    $SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
    $SqlAdapter.SelectCommand = $SqlCmd
    $SqlCmd.Connection = $Connection
    $DataSet = New-Object System.Data.DataSet
    $SqlAdapter.Fill($DataSet)
    $Connection.Close()

$Results += $DataSet.Tables[0]

($Results | ConvertTo-XML -NoTypeInformation).Save("$TempDir\$OutputXML")
}

if ((Get-ChildItem $TempDir -filter "$Date-*.xml").count -gt 0){    
Foreach ($file in (Get-ChildItem $TempDir -filter "$Date-*.xml" -recurse)){
    Foreach ($webserver in $WebDir){
        Copy-Item $file.fullname "$webserver\$file" -force
        }
    Remove-Item $file.fullname -force
    }
}

这是 XML 的输出格式

<?xml version="1.0"?>
<Objects>
  <Object>
    <Property Name="serviceGroupName">ServiceGroup1</Property>
    <Property Name="numAccounts">15</Property>
    <Property Name="numDevices">28</Property>
    <Property Name="RowError" />
    <Property Name="RowState">Unchanged</Property>
    <Property Name="Table">
      <Property>System.Data.DataRow</Property>
    </Property>
    <Property Name="ItemArray">
      <Property>ServiceGroup1</Property>
      <Property>15</Property>
      <Property>28</Property>
    </Property>
    <Property Name="HasErrors">False</Property>
  </Object>
  <Object>
    <Property Name="serviceGroupName">ServiceGroup1</Property>
    <Property Name="numAccounts">45</Property>
    <Property Name="numDevices">69</Property>
    <Property Name="RowError" />
    <Property Name="RowState">Unchanged</Property>
    <Property Name="Table">
      <Property>System.Data.DataRow</Property>
    </Property>
    <Property Name="ItemArray">
  <Property>ServiceGroup1</Property>
  <Property>45</Property>
  <Property>69</Property>
</Property>
<Property Name="HasErrors">False</Property>

最后一件事。如果可以从 XML 中删除多余的膨胀,如您所见,它会使数据输出加倍,因为它创建了一个名为 ItemArray 的节点,其中包含所有相同的信息。

我希望这很容易理解。如果您需要更多信息,请告诉我。并提前感谢您的任何帮助。

4

2 回答 2

2

我认为您需要做的就是在 powershell 脚本中更新您的两个 T-sql 查询。第一个,添加如下代码:


...., "Monthly" as ReportType FROM AccountDeviceStats ad1...
第二个,添加如下代码:


...., "Total" as ReportType FROM AccountDeviceStats ad1...

### Dates to use
$Date = (Get-Date -f MM-dd-yyyy)
$FDoTM = ((Get-Date -Day 01).AddMonths(0)).AddDays(0)
$LDo2PM = ((Get-Date -Day 01).AddMonths(-1)).AddDays(-1)
$TempDir = "C:\Temp"
$WebDir =     @("\\x.x.x.x\c$\inetpub\wwwroot\Reports\Accounts","\\x.x.x.x\c$\inetpub\wwwroot\Reports\Accounts")

### Something

$OutputXML = "$Date-Monthly-AccountReport.xml"

### Connection settings, uses windows authentication

$DBServer = "OMMITED"
$databasename = "OMMITED"
$Connection = new-object system.data.sqlclient.sqlconnection #Set new object to connect to sql database
$Connection.ConnectionString ="server=$DBServer;database=$databasename;trusted_connection=True" # Connectiongstring setting for local machine database with window authentication
Write-host "Connection Information:"  -foregroundcolor yellow -backgroundcolor black
$Connection #List connection information


### Connect to Database and Run Query

$SqlCmd = New-Object System.Data.SqlClient.SqlCommand #setting object to use sql commands

$OutputHeader1 = "This Month's counts"
$SqlQuery1 = @"

SET NOCOUNT ON;

WITH AccountDeviceStats(serviceGroupName,numAccounts,numDevices)
AS
(
    SELECT svg.name,COUNT(acct.serviceGroupId) as Accounts, NULL FROM bm_account acct WITH     (NOLOCK)
    INNER JOIN bm_servicegroup svg WITH (NOLOCK) ON svg.servicegroupId = acct.serviceGroupId

    where acct.CreateStamp between '$($LDo2PM)' and '$($FDoTM)'
GROUP BY acct.serviceGroupId,svg.name
UNION ALL
SELECT svg.name, NULL, COUNT(device.serviceGroupId) as Devices FROM bm_device device WITH (NOLOCK)
INNER JOIN bm_servicegroup svg WITH (NOLOCK) ON svg.servicegroupId = device.serviceGroupId, bm_account acct

where device.accountID=acct.accountId and acct.CreateStamp between '$($LDo2PM)' and '$($FDoTM)'
GROUP BY device.serviceGroupId,svg.name
)
SELECT ad1.serviceGroupName,ad1.numAccounts,ad2.numDevices, ""Monthly"" as ReportType  FROM AccountDeviceStats ad1
INNER JOIN AccountDeviceStats ad2 ON ad1.serviceGroupName = ad2.serviceGroupName
WHERE ad1.numAccounts IS NOT NULL AND ad2.numDevices IS NOT NULL
ORDER BY numAccounts DESC,numDevices DESC
"@

$OutputHeader2 = "Total Counts"
$SqlQuery2 = @"

SET NOCOUNT ON;

WITH AccountDeviceStats(serviceGroupName,numAccounts,numDevices)
AS
(
SELECT svg.name,COUNT(acct.serviceGroupId) as Accounts, NULL FROM bm_account acct WITH     (NOLOCK)
INNER JOIN bm_servicegroup svg WITH (NOLOCK) ON svg.servicegroupId = acct.serviceGroupId

where acct.CreateStamp < '12-31-2099'
GROUP BY acct.serviceGroupId,svg.name
UNION ALL
SELECT svg.name, NULL, COUNT(device.serviceGroupId) as Devices FROM bm_device device WITH (NOLOCK)
INNER JOIN bm_servicegroup svg WITH (NOLOCK) ON svg.servicegroupId = device.serviceGroupId, bm_account acct

where device.accountID=acct.accountId and acct.CreateStamp < '12-31-2099'
GROUP BY device.serviceGroupId,svg.name
)
SELECT ad1.serviceGroupName,ad1.numAccounts,ad2.numDevices, ""Total"" as ReportType FROM AccountDeviceStats ad1
INNER JOIN AccountDeviceStats ad2 ON ad1.serviceGroupName = ad2.serviceGroupName
WHERE ad1.numAccounts IS NOT NULL AND ad2.numDevices IS NOT NULL
ORDER BY numAccounts DESC,numDevices DESC
"@

$sqlQueries = @($SqlQuery1, $SqlQuery2)

$Results = @()

Foreach ($Query in $sqlQueries){
    $Connection.open()
    Write-host "Connection to database successful." -foregroundcolor green -backgroundcolor black
    $SqlCmd.CommandText = $Query
    $SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
    $SqlAdapter.SelectCommand = $SqlCmd
    $SqlCmd.Connection = $Connection
    $DataSet = New-Object System.Data.DataSet
    $SqlAdapter.Fill($DataSet)
    $Connection.Close()

$Results += $DataSet.Tables[0]

($Results | ConvertTo-XML -NoTypeInformation).Save("$TempDir\$OutputXML")
}

if ((Get-ChildItem $TempDir -filter "$Date-*.xml").count -gt 0){    
Foreach ($file in (Get-ChildItem $TempDir -filter "$Date-*.xml" -recurse)){
    Foreach ($webserver in $WebDir){
        Copy-Item $file.fullname "$webserver\$file" -force
        }
    Remove-Item $file.fullname -force
    }
}
于 2013-04-04T00:03:25.077 回答
2

最初的问题还询问了如何从 XML 中删除臃肿。我正在寻找一种解决方案,其中我从 SQL 结果生成的 XML 必须采用绝对特定的格式,并带有正确的标签和所有内容。我发现一旦你有了你的数据集对象 ($DataSet),那么如果你想看看它有哪些方法和属性可用,($DataSet | gm) 那么其中之一就是 GetXML()。

这会自动格式化您的 SQL 输出,以便每个返回的列(或列别名)作为单独的标记返回(尽管注意,它不会为空值生成空标记)所以在这种情况下,如果您使用 $DataSet.GetXML( )我本来希望看到输出类似于

 <NewDataSet>
  <Table>
    <serviceGroupName>ServiceGroup1</serviceGroupName>
    <numAccounts>15</numAccounts>
    <numDevices>28</numDevices>
  </Table>
</NewDataSet>

所以没有膨胀!

由于这只是一系列字符串,因此您可以执行 ($Dataset.GetXML()).Replace('NewDataSet','OuterTag').Replace('Table','InnerTag') 之类的操作以提供更好的标签XML。一旦你对此感到满意,你可以输出

SET-CONTENT -PATH $xmlfilename -VALUE '<?xml version="1.0" ?>' 

或者一些这样的文件,然后附加 GetXML() 方法的输出,这样你就有了一个更整洁的 XML 格式!

($DataSet.GetXML()).Replace('NewDataSet','OuterTagName').Replace('Table','InnerTagName') | ADD-CONTENT -PATH $xmlfilename
于 2016-04-01T13:15:18.497 回答