#tsql #powershell
#tsql #powershell
Вопрос:
Итак, я знаю, как вызвать sp_executeSql
с помощью TVP из кода C #. Что означает, что я могу сделать это в Powershell с ADO.Net .
Но мне любопытно, как это сделать с помощью Invoke-Sqlcmd
команды? Проблема в том, что значения TVP задаются пользователем, и я хочу избежать любой возможности Sql-инъекции.
В настоящее время у меня есть следующий код:
$ControlSql = @"
SELECT ClientId,Namespace,DatabaseConnectionString
FROM Namespace n
JOIN DatabaseConnection dc ON n.DatabaseConnectionId = dc.DatabaseConnectionId
WHERE Namespace IN (SELECT Value FROM @Namespaces)
"@
$ControlParams = "'@Namespaces dbo.TableOfString READONLY'"
$ControlQuery = "EXECUTE sp_executesql @stmt = $ControlSql, @params = $ControlParams, @Namespaces = $Namespaces;"
@Namespaces = $Namespaces
Часть, конечно, неверна. $Namespaces
это список значений, предоставленных пользователем. Я понятия не имею, как заполнить @Namespaces
TVP из него.
Ну, я делаю, но мне интересно, правильно ли это. Я могу генерировать отдельные INSERT INTO @Namespaces ...
инструкции для каждого значения из $Namespaces
перед передачей последнего в конечный SELECT
запрос.
Итак, если $Namespaces
содержит 1000 записей, результирующий sql будет содержать 1000 параметров.
Правильный ли это способ сделать это?
Ответ №1:
Вы можете передать CSV-файл, содержащий значения, разделенные запятой, и использовать массовую вставку для заполнения параметра табличного значения (TVP ). Sql-код является:
BULK INSERT @Namespaces
FROM 'path_to_Namespaces.txt'
WITH
(
FIELDTERMINATOR =' ,',
ROWTERMINATOR =' n'
);
Измените свой код, чтобы передать имя файла (вместо передачи TVP)
Таким образом, вы избегаете передачи параметра большого размера.
Комментарии:
1. Слишком проблематично — серверу sql необходимо иметь доступ к файлу. Это означает настройку общего ресурса так, чтобы он был виден всем соответствующим серверам.
2. Общие ресурсы могут быть защищены для каждого пользователя и невидимы для других, если соответствующие серверы работают в домене, посмотрите: thesqldude.com/2011/12/30 /…
3. Конечно, они могут. Но это создает накладные расходы на настройку. Должен быть более простой способ, и я думаю, что я нашел способ — я должен использовать
DataTable
вместо TVP.4. Но я все еще в недоумении, как передать его с помощью Invoke-SqlCmd. Похоже, если я хочу избежать какой-либо дополнительной настройки, мне нужно прибегнуть к ADO.NET вызывается из скрипта.
5. Это правильно. DataTable совместим с TVP и может быть передан скрипту с помощью Ado.net класс SqlCmd. Invoke-Sqlcmd.не поддерживает определяемый пользователем тип данных, такой как TVP или DataTable.