忽略带有PowerShell的SQL查询的循环的空结果

忽略带有PowerShell的SQL查询的循环的空结果,powershell,csv,Powershell,Csv,我有一张这样的桌子: avis,client,image_client,client_do 123,carrefour,,23 45,leclerc,,12 56,auchan,,69 89,casino,,96 如您所见,列image\u client为空。我已经在这个csv文件中添加了这个列 我的SQL datatable就是这种数据 client_do | image_client 12 12.png 90

我有一张这样的桌子:

avis,client,image_client,client_do
123,carrefour,,23
45,leclerc,,12
56,auchan,,69
89,casino,,96
如您所见,列
image\u client
为空。我已经在这个csv文件中添加了这个列

我的SQL datatable就是这种数据

client_do        |  image_client
12                  12.png
90                  90.png
96                  96.png
我想将所有SQL数据
image\u client
添加到csv列
image\u client
中,其中的行具有相同的client\u do

目前,我有以下代码:

$Csv = Import-Csv "$treatmentfolder\4_1_traitement.csv"
$i=0

function GenericSqlQuery ($Server, $Database, $SQLQuery) {
    $Connection = New-Object System.Data.SQLClient.SQLConnection
    $Connection.ConnectionString = $ConnectionString
    $Connection.Open()
    $Command = New-Object System.Data.SQLClient.SQLCommand
    $Command.Connection = $Connection
    $Command.CommandText = $SQLQuery
    $Reader = $Command.ExecuteReader()
    while ($Reader.Read()) {
        $Reader.GetValue(0)
    }

    $Connection.Close()

}

ForEach ($Row in $Csv) {

    $query= $query = "IF EXISTS (SELECT [image_client] FROM [dbo].[clients] WHERE [client_do] = {0}) BEGIN SELECT [image_client] FROM [dbo].[clients] WHERE [client_do] = {0} END" -f $Row.client_do
    $imagefile=GenericSqlQuery($sqlserver,$DB,$query)
    $i += 1
}
问题是忽略查询的空结果,我有一个错误,即没有为行
$Reader=$Command.ExecuteReader()
初始化CommandText,并且在($Reader.Read())期间,无法为行
调用空表达式

编辑:BaconBits更正的代码

我看到了几个问题

首先,您的SQL查询有一个
END
,但没有
BEGIN
。如果需要
如果存在
,则应为:

IF EXISTS (SELECT [image_client] FROM [dbo].[clients] WHERE [client_do] = $Row.client_do) BEGIN SELECT [image_client] FROM [dbo].[clients] WHERE [client_do] = $Row.client_do END
或者,如果只执行一条语句,则可以完全省略
BEGIN…END
块:

IF EXISTS (SELECT [image_client] FROM [dbo].[clients] WHERE [client_do] = $Row.client_do) SELECT [image_client] FROM [dbo].[clients] WHERE [client_do] = $Row.client_do
但是,严格来说,如果存在
,则根本不需要
。您只是让查询引擎做更多的工作,唯一的区别是您根本不会得到结果集,而不是空的结果集,就SqlDataReader而言,空的结果集没有太大的不同。你可能应该打电话:

SELECT [image_client] FROM [dbo].[clients] WHERE [client_do] = $Row.client_do
如果结果集为空,则在脚本中处理它。但是,我不确定它是否需要任何编码更改

接下来,您不能像现在这样调用嵌入变量的属性。如果
$Row.client\u do
为12,则
“$Row.client\u do”
将返回类似于
[DataRow].client\u do的内容。PowerShell解析器无法将嵌入的句点识别为点运算符。您需要使用子表达式,如
“$($Row.client\u-do)”
。因此,您的查询应该是:

$query = "IF EXISTS (SELECT [image_client] FROM [dbo].[clients] WHERE [client_do] = $($Row.client_do)) BEGIN SELECT [image_client] FROM [dbo].[clients] WHERE [client_do] = $($Row.client_do) END"
或:

第三,在您的功能中,这一行没有意义:

$Reader.GetValue($1)
$1
是一个没有值的变量。您实际上是在调用
$Reader.GetValue($null)
,这意味着系统实际上是在调用
$Reader.GetValue(([int]$null))
。它之所以有效,是因为
[int]$null
0
,但这似乎完全是偶然的。应该是:

$Reader.GetValue(0)
最后,这里的整个方法使用字符串连接来构建查询字符串。这意味着您容易受到SQL注入的攻击。如果这是一个一次性脚本就可以了,但是如果您要重复使用这个脚本,那么我强烈建议您使用参数化查询


编辑:事实上,我注意到了一些其他的东西。您的循环没有意义,并且您错误地调用了函数

ForEach ($Row in $Csv) {
    $query = ...
    $imagefile = GenericSqlQuery($sqlserver,$DB,$query)
    $i += 1
}
您在每次迭代中都会覆盖
$imagefile
。然后什么也不做

另外,
GenericSqlQuery($sqlserver,$DB,$query)
的工作方式与您想象的不一样。如前所述,这是调用
GenericSqlQuery-Server($sqlserver,$DB,$query)-Database$null
-SQLQuery$null
。这是一个最大的PowerShell陷阱。它必须是
GenericSqlQuery$sqlserver$DB$query
GenericSqlQuery-Server$sqlserver-Database$DB-SQLQuery$query

您的循环和脚本结尾类似于:

ForEach ($Row in $Csv) {
    $query = ...
    $imagefile = GenericSqlQuery -Server $sqlserver -Database $DB -SQLQuery $query
    $row.image_client = $imagefile -join ','
    $i += 1
}
$Csv | Export-Csv -Path "exportfilename.csv" -NoTypeInformation
我看到了几个问题

首先,您的SQL查询有一个
END
,但没有
BEGIN
。如果需要
如果存在
,则应为:

IF EXISTS (SELECT [image_client] FROM [dbo].[clients] WHERE [client_do] = $Row.client_do) BEGIN SELECT [image_client] FROM [dbo].[clients] WHERE [client_do] = $Row.client_do END
或者,如果只执行一条语句,则可以完全省略
BEGIN…END
块:

IF EXISTS (SELECT [image_client] FROM [dbo].[clients] WHERE [client_do] = $Row.client_do) SELECT [image_client] FROM [dbo].[clients] WHERE [client_do] = $Row.client_do
但是,严格来说,如果存在
,则根本不需要
。您只是让查询引擎做更多的工作,唯一的区别是您根本不会得到结果集,而不是空的结果集,就SqlDataReader而言,空的结果集没有太大的不同。你可能应该打电话:

SELECT [image_client] FROM [dbo].[clients] WHERE [client_do] = $Row.client_do
如果结果集为空,则在脚本中处理它。但是,我不确定它是否需要任何编码更改

接下来,您不能像现在这样调用嵌入变量的属性。如果
$Row.client\u do
为12,则
“$Row.client\u do”
将返回类似于
[DataRow].client\u do的内容。PowerShell解析器无法将嵌入的句点识别为点运算符。您需要使用子表达式,如
“$($Row.client\u-do)”
。因此,您的查询应该是:

$query = "IF EXISTS (SELECT [image_client] FROM [dbo].[clients] WHERE [client_do] = $($Row.client_do)) BEGIN SELECT [image_client] FROM [dbo].[clients] WHERE [client_do] = $($Row.client_do) END"
或:

第三,在您的功能中,这一行没有意义:

$Reader.GetValue($1)
$1
是一个没有值的变量。您实际上是在调用
$Reader.GetValue($null)
,这意味着系统实际上是在调用
$Reader.GetValue(([int]$null))
。它之所以有效,是因为
[int]$null
0
,但这似乎完全是偶然的。应该是:

$Reader.GetValue(0)
最后,这里的整个方法使用字符串连接来构建查询字符串。这意味着您容易受到SQL注入的攻击。如果这是一个一次性脚本就可以了,但是如果您要重复使用这个脚本,那么我强烈建议您使用参数化查询


编辑:事实上,我注意到了一些其他的东西。您的循环没有意义,并且您错误地调用了函数

ForEach ($Row in $Csv) {
    $query = ...
    $imagefile = GenericSqlQuery($sqlserver,$DB,$query)
    $i += 1
}
您在每次迭代中都会覆盖
$imagefile
。然后什么也不做

另外,
GenericSqlQuery($sqlserver,$DB,$query)
的工作方式与您想象的不一样。如前所述,这是调用
GenericSqlQuery-Server($sqlserver,$DB,$query)-Database$null
-SQLQuery$null
。这是一个最大的PowerShell陷阱。它必须是
GenericSqlQuery$sqlserver$DB$query
GenericSqlQuery-Server$sqlserver-Database$DB-SQLQuery$query

您的循环和脚本结尾类似于:

ForEach ($Row in $Csv) {
    $query = ...
    $imagefile = GenericSqlQuery -Server $sqlserver -Database $DB -SQLQuery $query
    $row.image_client = $imagefile -join ','
    $i += 1
}
$Csv | Export-Csv -Path "exportfilename.csv" -NoTypeInformation

只需指出:在
GetV之后,您的代码示例中似乎有一个额外的花括号