写入SQL Server表时Write-DataTable行为不一致

时间:2016-09-21 18:37:14

标签: sql-server powershell

我正在尝试创建一个脚本,使用Write-DataTable函数将源数据从多个数据库服务器导入一个中央数据存储库(源代码here)。如果目标表(RPRMBSDEVDB81.dba_rep..DBBakSizes)为空,我想出的脚本是有效的,但是,如果表中有数据它会爆炸。

我在做什么:

  1. 我通过SQL Server Mgmt Studio从目标表中删除所有内容。
  2. 我运行PowerShell脚本,它运行成功,数据最终在表格中。
  3. 我通过SSMS从目标表中删除一台服务器的数据。
  4. 我再次运行PowerShell脚本,验证我的数据表中有唯一数据,并且它出错(请参阅我脚本下方的完整错误)。
  5. 我的剧本:

    #Clear screen (for testing)
    Clear-Host
    
    #SQLCMD timeout parameter
    $QueryTimeout = 120
    
    #Get list of servers to import data from
    $sql_serverlist = "
    SELECT sl.HostName
        ,sl.ServerName + '.' + sl.Domain AS ServerName
        ,ISNULL(MAX(bs.ReportDate),'1/1/1980') AS ReportDate
    FROM dbo.ServerList sl
        LEFT OUTER JOIN dbo.DBBakSizes bs ON bs.ServerName = sl.HostName
    WHERE sl.Import = 1
    AND sl.Active = 1
    GROUP BY sl.HostName
        ,sl.ServerName + '.' + sl.Domain;
    "
    $servers = Invoke-Sqlcmd -ServerInstance RPRMBSDEVDB81 -Database dba_rep -Query $sql_serverlist
    
    #Define path to Write-DataTable module
    $Location = "C:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\Modules\Write-DataTable"
    #Load Write-DataTable module
    Import-Module $Location\Write-DataTable.psm1
    
    #Setup DataTable
    $dt = New-Object Data.DataTable
    $col1 = New-Object Data.DataColumn ServerName,([string])
    $col2 = New-Object Data.DataColumn DatabaseName,([string])
    $col3 = New-Object Data.DataColumn BackupType,([string])
    $col4 = New-Object Data.DataColumn UsedCompression,([int])
    $col5 = New-Object Data.DataColumn UsedChecksum,([int])
    $col6 = New-Object Data.DataColumn MostRecentFull_Date,([datetime])
    $col7 = New-Object Data.DataColumn MostRecentFull_Sec,([int])
    $col8 = New-Object Data.DataColumn MostRecentFull_MB,([int])
    $col9 = New-Object Data.DataColumn MostRecentOther,([string])
    $col10 = New-Object Data.DataColumn MostRecentOther_Date,([datetime])
    $col11 = New-Object Data.DataColumn MostRecentOther_Sec,([int])
    $col12 = New-Object Data.DataColumn MostRecentOther_MB,([int])
    $col13 = New-Object Data.DataColumn ReportDate,([datetime])
    $dt.columns.add($col1)
    $dt.columns.add($col2)
    $dt.columns.add($col3)
    $dt.columns.add($col4)
    $dt.columns.add($col5)
    $dt.columns.add($col6)
    $dt.columns.add($col7)
    $dt.columns.add($col8)
    $dt.columns.add($col9)
    $dt.columns.add($col10)
    $dt.columns.add($col11)
    $dt.columns.add($col12)
    $dt.columns.add($col13)
    
    #Loop through servers and pull in bak file data
    foreach ($server in $servers)
    {
        #Retrieve ServerName and MAX(ReportDate) from array
        $hostname = $server[0]
        $servername = $server[1]
        $reportdate = $server[2].ToString()
    
        #Build SQL to retrieve records for import
        $sql_bakdata = "
        SELECT  '$hostname' AS ServerName
            ,DatabaseName
            ,BackupType
            ,UsedCompression
            ,UsedChecksum
            ,MostRecentFull_Date
            ,MostRecentFull_Sec
            ,MostRecentFull_MB
            ,MostRecentOther
            ,MostRecentOther_Date
            ,MostRecentOther_Sec
            ,MostRecentOther_MB
            ,ReportDate
        FROM rp_util.dbo.DBBakSizes
        WHERE CAST(ReportDate AS SMALLDATETIME) > '$reportdate';
        "
    
        #Run SQL and capture results in array
        $dt += Invoke-Sqlcmd -ServerInstance $servername -Query $sql_bakdata -QueryTimeout $QueryTimeout
    }
    
    #Load data
    Write-DataTable -ServerInstance "RPRMBSDEVDB81" -Database "dba_rep" -TableName "DBBakSizes" -Data $dt
    

    错误:

    Write-DataTable : System.Management.Automation.MethodInvocationException:
    Exception calling "WriteToServer" with "1" argument(s): "Object reference not
    set to an instance of an object." ---> System.NullReferenceException: Object
    reference not set to an instance of an object.
       at System.Data.SqlClient.SqlBulkCopy.WriteToServer(DataRow[] rows)
       at WriteToServer(Object , Object[] )
       at System.Management.Automation.DotNetAdapter.AuxiliaryMethodInvoke(Object target, Object[] arguments, MethodInformation methodInformation, Object[] originalArguments)
       --- End of inner exception stack trace ---
       at System.Management.Automation.DotNetAdapter.AuxiliaryMethodInvoke(Object target, Object[] arguments, MethodInformation methodInformation, Object[] originalArguments)
       at System.Management.Automation.ParserOps.CallMethod(Token token, Object target, String methodName, Object[] paramArray, Boolean callStatic, Object valueToSet)
       at System.Management.Automation.MethodCallNode.InvokeMethod(Object target, Object[] arguments, Object value)
       at System.Management.Automation.MethodCallNode.Execute(Array input, Pipe outputPipe, ExecutionContext context)
       at System.Management.Automation.ParseTreeNode.Execute(Array input, Pipe outputPipe, ArrayList& resultList, ExecutionContext context)
       at System.Management.Automation.StatementListNode.ExecuteStatement(ParseTreeNode statement, Array input, Pipe outputPipe, ArrayList& resultList, ExecutionContext context).Message
    At line:2 char:16
    + Write-DataTable <<<<  -ServerInstance "RPRMBSDEVDB81" -Database "dba_rep" -TableName "DBBakSizes" -Data $dt
        + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
        + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Write-DataTable

1 个答案:

答案 0 :(得分:0)

放弃Write-DataTable。我的脚本现在循环遍历DataTable并通过痛苦的行插入行。

#Load data
#Write-DataTable -ServerInstance "RPRMBSDEVDB81" -Database "dba_rep" -TableName "DBBakSizes" -Data $dt
$SqlConnection = new-object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=$DBServer; Database=$DBName; Integrated Security=SSPI;"
$SqlConnection.Open()
$SqlCommand = new-object System.Data.SqlClient.SqlCommand
$SqlCommand.Connection = $SqlConnection

foreach ($dtrow in $dt)
{
  If ($dtrow.ServerName) #Skip NULL/empty records
  {
    $SqlInsert = "INSERT dbo.DBBakSizes VALUES('$($dtrow.ServerName)','$($dtrow.DatabaseName)','$($dtrow.BackupType)',$($dtrow.UsedCompression),$($dtrow.UsedChecksum),'$($dtrow.MostRecentFull_Date)',$($dtrow.MostRecentFull_Sec),$($dtrow.MostRecentFull_MB),'$($dtrow.MostRecentOther)','$($dtrow.MostRecentOther_Date)',$($dtrow.MostRecentOther_Sec),$($dtrow.MostRecentOther_MB),'$($dtrow.ReportDate)')" 
    $SqlCommand.CommandText = $SqlInsert
    $SqlCommand.ExecuteNonQuery()
  }
}

$SqlConnection.Close()