invoke-sqlcmd терпит неудачу не показывает результаты по определенному типу запросов - PullRequest
0 голосов
/ 21 октября 2018
Invoke-Sqlcmd -ServerInstance '.' -Database 'MyDB' 
      -Query 'EXEC SprocA  @param1= "value";EXEC SprocB  @param1= "value";'

В основном у меня Invoke-SqlCmd выполняется запрос, который вызывает две хранимые процедуры.Обе хранимые процедуры выводят группу строк.

Однако если sprocA не выводит никаких результатов (пустые результаты выбора или нет строк), то команда invoke, похоже, не выводит выходные данные второй sprocB даже если у него есть данные.

Если я изменю порядок хранимых процедур в параметре запроса моих команд Invoke-SqlCmd, то это прекрасно работает и возвращает вывод первой хранимой процедуры.

Если у меня было три хранимых процедурывызывает, когда первый возвращает данные, а второй нет, а третий - выводит вывод первого и третьего результата.

По сути, он не печатает никаких выходных данных, только если первая хранимая процедура не имеет выходных данных.Кажется странным.

Что я могу сделать, чтобы обойти этот мудрый SQL?Может быть, PowerShell?

Я также смог воспроизвести это с помощью двух операторов Select, в которых одно возвращает данные, а другое - нет.

Ответы [ 2 ]

0 голосов
/ 16 августа 2019

На самом деле, трудно поверить, что MS допустила такую ​​ошибку или, возможно, это не ошибка.Как бы то ни было, когда вы запускаете Invoke-SqlCmd и с запросом, подобным следующему,

select * from table1 where id = 1111 -- non-exists id, this select returns nothing
select * from table2 where id = 2222 -- exists id, this select returns something

В SSMS вы можете видеть 2 набора результатов, первый из которых пуст.

Однако, Invoke-SqlCmd ничего не возвращает, когда первый набор результатов пуст, даже другие наборы результатов нет.Мое лицо было похоже на? _?

Другой подход - написать собственную функцию вызова SQL, например, следующую, чтобы возвращать любые наборы результатов, даже пустые.

    $sql_Conn = New-Object System.Data.SqlClient.SQLConnection
    $sql_Conn.ConnectionString = $sqlConnectionString
    $sql_Conn.Open()
    $sql_cmd = New-Object system.Data.SqlClient.SqlCommand($Query, $sql_Conn)
    $sql_ds = New-Object system.Data.DataSet
    $sql_da = New-Object system.Data.SqlClient.SqlDataAdapter($sql_cmd)
    [void]$sql_da.fill($sql_ds)
    $sql_Conn.Close()
    return $sql_ds

Все хорошо, покаНовая проблема возникает с ключевым словом GO в вашем скрипте, вы должны знать это, если вы используете SSMS.Дело в том, что GO не является командой SQL.это просто разделитель, используемый SSMS.Коды, разработанные MS, могут хорошо обрабатывать GO, например, SSMS, Invoke-SqlCmd и sqlcmd.exe.Если вы используете собственную функцию вызова SQL, вы получите проблему с синтаксисом

Неверный синтаксис рядом с 'GO'

Хотя люди, скорее всего, попросят вас обновить скрипт SQL доудалите все GO строки, однако, вещи не всегда находятся под контролем, обычно нужно работать с разными людьми и командами.

Наконец, я должен урезать GO в моих сценариях, как показано ниже

$Query = $Query -ireplace "(^|\r|\n)[ \t]*\bGO\b[ \t]*(\r|\n|$)", '$1$2'

https://github.com/LarrysGIT/Invoke-Sql

Конечно, история не закончена, тем больше я пытаюсь автоматизировать задачи, связанные с SQL.Чем больше проблема найдена.Существует несколько способов автоматического выполнения сценария SQL.Пока ни один из них не идеален.

Invoke-Sql (Мой собственный сценарий)

* Is able to handle the key separator 'GO'
* Is able to handle duplicate columns
* Fully support multiple result sets, even the first result set is empty
* Unable to handle `Create or alter` keywords if there are contents ahead
* Unable to handle special characters like '194 160' (non-breaking space) in SQL script (edited by some document edit tool, MS word for example)

Invoke-SqlCmd

* Is able to handle the key separator 'GO'
* Is able to handle special characters like 'non-breaking space'
* Unable to handle duplicate columns
* Unable to fully handle multiple result sets (when the first table is empty)

sqlcmd.exe

* Is able to handle all things (briefly tested)
* The returned result sets are plain text, hard to parse

Microsoft.SqlServer.SMO оснастка

* The API of SQL server management studio
* Theoretically should be able to handle all cases
* Need to dig more
0 голосов
/ 21 октября 2018

Это задокументированное поведение invoke-sqlcmd

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

Похоже, что оба набора результатовфактически возвращаются, но не выводятся по умолчанию.

EG

   PS C:\> Invoke-SqlCmd "select 1 a; select 2 b, 3 c;" | % { $_ | Out-Default }

вывод

a
-
1



b c
- -
2 3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...