Игнорировать пустые результаты цикла с SQL-запросом с помощью PowerShell - PullRequest
0 голосов
/ 15 мая 2018

У меня есть таблица такого типа:

avis,client,image_client,client_do
123,carrefour,,23
45,leclerc,,12
56,auchan,,69
89,casino,,96

Как видите, столбец image_client пуст. Я добавил столбец в этот CSV-файл.

Мой SQL-тип данных такого типа

client_do        |  image_client
12                  12.png
90                  90.png
96                  96.png

Я хотел бы добавить все данные SQL image_client в столбец csv image_client, где строки имеют одинаковые client_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
}

Проблема состоит в том, чтобы игнорировать пустые результаты запроса, и у меня есть ошибка, которая говорит CommandText не был инициализирован для строки $Reader = $Command.ExecuteReader() и Невозможно вызвать нулевое выражение для линии while ($Reader.Read()).

РЕДАКТИРОВАТЬ: Код исправлен BaconBits

1 Ответ

0 голосов
/ 15 мая 2018

Я вижу несколько вопросов.

Во-первых, ваш запрос SQL имеет END, но не BEGIN. Если вы хотите IF EXISTS, тогда должно быть либо:

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

Однако, строго говоря, вам не нужен IF EXISTS вообще. Вы просто заставляете механизм запросов выполнять больше работы, и единственное отличие состоит в том, что вы не получите никакого набора результатов вообще вместо пустого набора результатов, который не сильно отличается в том, что касается SqlDataReader. Наверное, вам следует просто позвонить:

SELECT [image_client] FROM [dbo].[clients] WHERE [client_do] = $Row.client_do

А затем обработать это в вашем скрипте, если у вас есть пустой набор результатов. Однако я не уверен, что это потребует каких-либо изменений в коде.

Далее, вы не можете вызывать свойства встроенных переменных, как вы. Если $Row.client_do равно 12, то "$Row.client_do" вернет что-то вроде [DataRow].client_do. Синтаксический анализатор PowerShell не распознает внедренный период как оператор точки. Вам нужно использовать подвыражение типа "$($Row.client_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"

Или:

$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

В-третьих, в вашей функции эта строка не имеет смысла:

$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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...