我正在从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()
答案 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]"
产生逐字记录[]
。