从Powershell插入的SQL:将空值插入为“空白”

时间:2012-02-29 22:30:05

标签: sql-server powershell

我正在从Powershell脚本向表中插入行。我遍历PSObjects(“属性包”)的集合,并为每个插入一行。 PSObject上的每个noteProperty对应于表中的一列。其中大多数是字符串,少数是日期,还有一些是布尔值。

Powershell中具有$ null值的属性将作为“空白”字符串插入,而不是在表中插入NULL。 $ null日期值显示为1900-01-01。除了指定了NOT NULL的几列之外,该表没有任何约束。如果我使用NULL作为值进行手动插入,则可以正常工作。

我可以遍历每个对象,寻找$ null属性,然后用字符串NULL替换它,但这似乎是一种黑客而不是“正确”的方式。正如你在下面看到的那样,我已经为booleans做了这个,因为表中相应的列是位。我错误地认为Powershell中的$ null会在SQL中转换为NULL。如果属性在Powershell中的值为$ null,是否有另一种方法可以使它正确地将NULL插入表中?或者,在插入最佳方法之前将$ null转换为字符串“NULL”?

这是我正在使用的代码:

$listOfLunsReport = Import-Clixml e:\powershell\myObjectCollection.xml

$conn = New-Object System.Data.SqlClient.SqlConnection
$conn.ConnectionString = "Data Source=SQLSERVER\MYDATABASE;Initial Catalog=my_report;Integrated Security=SSPI;"
$conn.open()

$cmd = New-Object System.Data.SqlClient.SqlCommand
$cmd.connection = $conn

foreach ($lunObject in $listOfLunsReport)
{
    if ($lunObject.SnapsConfigured -eq $true)
    {
        $snapBit = 1
    }
    else
    {
        $snapBit = 0
    }
    if ($lunObject.isDatastore -eq $true)
    {
        $dsBit = 1
    }
    else
    {
        $dsBit = 0
    }
    $cmd.commandtext = "INSERT INTO listOfLuns (Array,lunNumber,LunUID,CapacityInMB,StorageGroup,`
    SnapsConfigured,SnapName,SnapUID,NumberOfSnaps,LatestSnap,VM,PhysicalServer,isDatastore,`
    DatastoreName,ReportDate,ArrayModel,ArrayLocation) VALUES ('{0}','{1}','{2}','{3}','{4}',`
    '{5}','{6}','{7}','{8}','{9}','{10}','{11}','{12}','{13}','{14}','{15}','{16}')" -f `
    $lunObject.Array,$lunObject.lunNumber,$lunObject.LunUID,[int]$lunObject.CapacityInMB,`
    $lunObject.StorageGroup,$snapBit,$lunObject.SnapName,$lunObject.SnapUID,`
    $lunObject.NumberOfSnaps,$lunObject.LatestSnap,$lunObject.VM,$lunObject.PhysicalServer,`
    $dsBit,$lunObject.DatastoreName,$lunObject.ReportDate,$lunObject.ArrayModel,$lunObject.ArrayLocation
    $cmd.executenonquery()
}

$conn.close()

3 个答案:

答案 0 :(得分:6)

$DBNull = [System.DBNull]::Value 

另请参阅此处的相关问题:Powershell and SQL parameters. If empty string, pass DBNull

答案 1 :(得分:0)

我已使用PS $ null更改了所有空白值,并且Write-SQLTableData成功运行。

Foreach ($incident in $incidents)
    {
    if ($incident.closed_at -eq '')
        {
        $incident.closed_at = $null
        }
    }

$incident | Select "number","opened_at","short_description","closed_at","incident_state","state","u_operation_mode"|`
Write-SqlTableData -ServerInstance $Instance -DatabaseName $Database -SchemaName dbo -TableName $Table -ConnectionTimeout 600 –Force

答案 2 :(得分:0)

第一件事:与其将SQL命令的变量元素“烘焙”到命令字符串中,反而更可靠,更安全的是使用参数化查询,或者使用{{3} },建议使用存储过程;这样,变量元素将作为参数传递。


假设您已将占位符放在'...'(例如'{0}')中,则您的模板字符串假定所有要插入的值都是 strings

鉴于$null传递给Aaron Bertrand-f被转换为空字符串 [1] ,您会以原义''结尾 命令字符串中的参数值,而您真正需要的是逐字词NULL

您可以定义 helper函数

function Expand-SqlQueryTemplate ($template, $values) {
  # Transform the values to SQL syntax.
  $transformedValues = $values | ForEach-Object {
    if ($null -eq $_) {
      'NULL'
    } elseif ($_ -is [string] -or $_ -is [datetime]) { # string or date
      # Enclose in '...', escaping embedded ' as ''
      "'{0}'" -f ($_ -replace "'", "''")
    } else { # other types, such as numbers
      # Use them as-is, though you may need to tweak this,
      # depending on what types you pass.
      $_
    }
  }
  # Expand the template string with the transformed values
  # and output the result.
  $template -f $transformedValues
}

然后您可以按以下方式调用它(我正在使用一个简化的示例):

# Define the command-string template.
$template = 'INSERT INTO SomeTable (Name, Age, Other) VALUES ({0}, {1}, {2})'

# Invoke the function, passing the values to substitute as an array.
Expand-SqlQueryTemplate $template  'J. Doe', 42, $null

上面的代码产生以下字符串:

INSERT INTO SomeTable (Name, Age, Other) VALUES ('J. Doe', 42, NULL)

[1]这同样适用于PowerShell的可扩展字符串("...");例如"[$null]"产生逐字记录[]