#sql #powershell
#sql #powershell
Вопрос:
первый пост здесь. Я занимаюсь разработкой приложений с помощью некоторых сценариев PowerShell; Я знаю, что это не лучший вариант для разработки приложений с графическим интерфейсом, но это то, с чем я знаком, и лучший из известных мне способов взаимодействия с приложениями Office 365, которые моим сотрудникам приходится часто выполнять.
Я пытаюсь создать функции, позволяющие легко заполнять поля со списком, считывать вводимые пользователем данные из списка со списком, а затем запрашивать базу данных Access для получения конкретных результатов на основе этого ввода.
У меня есть другая функция, которая запрашивает базу данных для извлечения списка, который заполняет поле со списком. теперь я хочу создать отдельную функцию, которая
- «считывает» ввод пользователя из выпадающего списка
- открывает OleDB-соединение для запроса базы данных access
- сканирует таблицу базы данных на наличие строки, соответствующей вводимым пользователем данным
- возвращает в виде строки ячейку в другом столбце из той же строки, которую выбрал пользователь
это то, что у меня есть до сих пор:
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()