Фильтрация SQL-запроса в PowerShell с помощью WHERE

#sql #powershell

#sql #powershell

Вопрос:

первый пост здесь. Я занимаюсь разработкой приложений с помощью некоторых сценариев PowerShell; Я знаю, что это не лучший вариант для разработки приложений с графическим интерфейсом, но это то, с чем я знаком, и лучший из известных мне способов взаимодействия с приложениями Office 365, которые моим сотрудникам приходится часто выполнять.

Я пытаюсь создать функции, позволяющие легко заполнять поля со списком, считывать вводимые пользователем данные из списка со списком, а затем запрашивать базу данных Access для получения конкретных результатов на основе этого ввода.

У меня есть другая функция, которая запрашивает базу данных для извлечения списка, который заполняет поле со списком. теперь я хочу создать отдельную функцию, которая

  1. «считывает» ввод пользователя из выпадающего списка
  2. открывает OleDB-соединение для запроса базы данных access
  3. сканирует таблицу базы данных на наличие строки, соответствующей вводимым пользователем данным
  4. возвращает в виде строки ячейку в другом столбце из той же строки, которую выбрал пользователь

это то, что у меня есть до сих пор:

  function Read-BoxSelection ($sourceBox, $sourceTable, $sourceColumn, $targetColumn){
     $conn = New-Object System.Data.OleDb.OleDbConnection
     $conn.ConnectionString = $connString
     $conn.Open() | Out-Null

     $cmd = New-Object System.Data.OleDb.OleDbCommand
     $cmd.Connection = $conn

     $selectedID = $sourceBox.SelectedItem

     [string]$writeQuery = ("SELECT * FROM $($sourceTable) WHERE $($sourceColumn) = $($selectedID)")

     $cmd.CommandText = "$writeQuery" 

     $reader = $cmd.ExecuteReader()

     while ($reader.read()){
        $readerResult = $reader.getValue($reader.GetOrdinal("$targetColumn"))
        return $readerResult  
     }

     $reader.close()
     $conn.close()
 }
  

Я уверен, что цикл while() нужно будет изменить; он перенесен из более ранней функции, которая заполняет поле со списком содержимым столбца $SourceColumn .

Проблема: моя первая функция называлась Get-BoxData . он открывает соединение, выполняет запрос и использует цикл while() для элементов.Добавьте каждую ячейку из столбца $targetColumn в поле со списком. для функции Get-BoxData следующий код отлично работал для выполнения SQL-запроса:

 [string]$readQuery = ("SELECT * FROM $($targetTable)")

$cmd.CommandText = "$readQuery"

$reader = $cmd.ExecuteReader()
  

но когда я меняю запрос на Read-BoxSelection, а именно, для фильтрации результата на основе пользовательского ввода с помощью WHERE, команда не передается в ExecuteReader, что бы я ни делал. Это очень странно, потому что я установил точку останова в строке ExecuteReader, и Write-Host подтверждает, что как $writeQuery, так и $cmd.CommandText успешно приняли запрос точно так, как написано. еще более странным является то, что ранее проблемы с отладкой ExecuteReader приводили к синтаксической ошибке в SQL-запросе; здесь я получаю следующую ошибку:

 Exception calling "ExecuteReader" with "0" argument(s): "No value given for one or more required parameters."
  

Не уверен, как поступить здесь!

Комментарии:

1. Пожалуйста, покажите Write-Host выходные данные SQL-запроса. ExecuteReader ошибки указывают на то, что команда была достигнута. Вам нужно заключить строковые литералы в WHERE кавычки. Еще лучше использовать параметризацию .

2. Также покажите, как вы вызываете функцию. Вы установили SourceColumn и targetColumn?

3. @parfait Write-Host в точке останова возвращает весь текст $query, как и ожидалось, т.Е. «ВЫБЕРИТЕ * ИЗ myTable, ГДЕ MyColumn = myCellContents»

4. Что такое myCellContents ? Строка, число? Если этот SQL буквально передается как есть в MS Access, это вызовет ошибку неизвестного параметра.

5. он определяется в базе данных как короткий текст, а в моем коде как [строка]

Ответ №1:

Строковые литералы в SQL должны быть заключены в кавычки, независимо от того, используются ли они в SELECT предложениях , JOIN , или WHERE . В противном случае компонент database Engine будет рассматривать объект как идентификатор (таблицу, столбец и т.д.) или параметр. MS Access обрабатывает любой именованный объект без кавычек, не распознанный в таблице, как параметр.

Поэтому короткий ответ заключается в том, чтобы заключить WHERE значение условия в одинарные кавычки, поскольку, как вы прокомментируете, это строковое значение:

 [string]$writeQuery = ("SELECT * FROM $($sourceTable) WHERE $($sourceColumn) = '$($selectedID)'")
  

Однако предпочтительным ответом является использование параметризации, которую можно легко выполнить, поскольку вы уже настроили объект command:

 # PREPARED STATEMENT WITH ? PLACEHOLDER
[string]$writeQuery = ("SELECT * FROM $($sourceTable) WHERE $($sourceColumn) = ?")     
$cmd.CommandText = $writeQuery

# ADD AND BIND PARAMETER
$cmd.Parameters.Add("@param", [System.Data.OleDb.OleDbType]::VarChar, 255)
$cmd.Parameters["@param"].Value = $selectedID

$reader = $cmd.ExecuteReader()