Powershell和SQL参数。如果为空字符串,则传递DBNull

时间:2009-05-28 14:00:08

标签: sql powershell dbnull

我得到了这个参数:

$objDbCmd.Parameters.Add("@telephone", [System.Data.SqlDbType]::VarChar, 18) | Out-Null;
$objDbCmd.Parameters["@telephone"].Value = $objUser.Telephone;

字符串$objUser.Telephone可以为空。如果它为空,我该如何将其转换为[DBNull]::Value

我试过了:

if ([string]:IsNullOrEmpty($objUser.Telephone)) { $objUser.Telephone = [DBNull]::Value };

但这给了我错误:

  

使用“0”参数调用“ExecuteNonQuery”的异常:“无法将参数值从ResultPropertyValueCollection转换为String。”

如果我将其转换为字符串,则会插入空字符串"",而不是DBNull

如何实现这一目标?

感谢。

4 个答案:

答案 0 :(得分:16)

在PowerShell中,您可以将null / empty字符串视为布尔值。

$x = $null
if ($x) { 'this wont print' }

$x = ""
if ($x) { 'this wont print' }

$x = "blah"
if ($x) { 'this will' }

所以......说过你能说:

$Parameter.Value = $(if ($x) { $x } else { [DBNull]::Value })

但我宁愿把它包装在像以下这样的函数中:

function CatchNull([String]$x) {
   if ($x) { $x } else { [DBNull]::Value }
}

答案 1 :(得分:6)

我不知道powershell,但在C#中我会做这样的事情:

if ([string]::IsNullOrEmpty($objUser.Telephone))
{
 $objDbCmd.Parameters["@telephone"].Value = [DBNull]::Value;
}
else
{
 $objDbCmd.Parameters["@telephone"].Value = $objUser.Telephone;
}

答案 2 :(得分:1)

始终在数据库值的末尾附加+“”...

$ command.Parameters [“@ EmployeeType”]。Value = $ ADResult.EmployeeType +“”

答案 3 :(得分:0)

很多年后,让我澄清一下:

Josh's answer显示了一个有用的简化,用于测试字符串是否为空(依靠PowerShell的隐式到布尔转换 [1] ),但是与汤米(OP)的问题。

相反,错误消息

“无法将参数值从ResultPropertyValueCollection转换为字符串。”

暗示是导致问题的 non -null情况,因为$objDbCmd.Parameters["@telephone"].Value期望 string 值或[DBNull]::Value,而$objUser.Telephone的类型为[ResultPropertyValueCollection],即值的集合

因此,在非null的情况下,必须分配一个 string 值,该值必须从集合中派生;一种选择是获取 first 集合元素的值,另一种方法是使用[string]::Join(';', $objUser.Telephone)将所有值与分隔符连接起来以形成单个字符串,或者使用只需使用"$($objUser.Telephone)"空格是可以接受的(对于多个电话号码来说不是一个好主意)。 [2]

尽管类型不匹配,但通过[string]:IsNullOrEmpty()检测空集合实际上是可行的,这是由于PowerShell在将值传递给[string]类型的方法参数时如何隐式对集合进行字符串化。 [2] < / sup>

类似地,使用隐式到布尔值的转换对集合也同样起作用:空集合的值为$false,非空集合的值为$true(只要因为至少有两个元素或唯一的元素本身会被视为$true [1]

因此,一种解决方案是使用 first 电话号码条目:

$objDbCmd.Parameters["@telephone"].Value = if ($objUser.Telephone) {
    $objUser.Telephone[0].ToString()  # use first entry
  } else {
    [DBNull]::Value
  }

注意:如果$objUser.Telephone[0]直接返回一个[string],则可以省略.ToString()调用。

PowerShell v7 + 中,您也可以通过三元条件来缩短语句:

$objDbCmd.Parameters["@telephone"].Value =
  $objUser.Telephone ? $objUser.Telephone[0].ToString() : [DBNull]::Value

[1]有关PowerShell的自动布尔转换的全面摘要,请参见this answer的底部。

[2]在隐式将集合转换为字符串时,默认情况下,PowerShell以单个空格作为分隔符将集合的字符串化元素连接在一起;您可以使用自动$OFS变量覆盖分隔符,但实际上很少这样做;例如,数组'foo', 'bar'转换为'foo bar';请注意,当您显式调用集合的.ToString()方法 时,此转换不适用,但是它确实适用于可扩展(插值)字符串内部,例如{{1 }}。