Wywołaj sqlcmd z PowerShell

Zadanie jest proste: mamy skrypt z poleceniami SQL, który chcemy wywołać przez sqlcmd. Ale – w skrypcie wykorzystujemy zmienną, która na dodatek zawiera ścieżkę do katalogu. Jako przykład niech posłuży taki fragment zapisany w pliku SELECT.sql:

SELECT Imie = 'Bartek', Zmienna = '$(ScriptPath)'

Wywołanie z poziomu cmd nie stwarza problemów:

C:\> cd tmp
C:\tmp> sqlcmd -r1 -v ScriptPath="C:\tmp" -i SELECT.sql -S Serwer-f 1250
Bartek Zmienna
------ -------
Bartek C:\tmp

Poszczególne przełączniki oznaczają:

  • -r1 – chcę zobaczyć błędy na ekranie
  • -v – przekazuję zmienną o nazwie ScriptPath z wartością zawierającą jakąś ścieżkę
  • -i – nazwa skryptu wejściowego
  • -S – mój serwer
  • -f – strona kodowa

I super, a jeśli potrzebujemy uruchomić w PowerShell?

PS C:\tmp> sqlcmd -r1 -v ScriptPath="C:\tmp" -i SELECT.sql -S Serwer -f 1250
Sqlcmd: ':\tmp': Invalid argument. Enter '-?' for help.PS C:\tmp>

Czemu tak?

Powodem nie jest ścieżka, tylko sam dwukropek, który jest dla PowerShell znakiem specjalnym. Problem w tym, że w tym przypadku nie daje się to ładnie obejść (np. przez znak `) i trzeba kombinować. Znalazłem dwa rozwiązania tego problemu. Pierwsze – zadeklarować zmienną jako tablicę i użyć ją w poleceniu, drugie – zastosować tablicę od razu w poleceniu i zrobić wszystko w ramach jednej linijki:

PS C:\tmp> $cmdparams = @('ScriptPath="C:\tmp"')
PS C:\tmp> $cmdparams
ScriptPath="C:\tmp"
PS C:\tmp> sqlcmd -r1 -v $cmdparams -i SELECT.sql -S Serwer -f 1250
Bartek Zmienna
------ -------
Bartek C:\tmp

PS C:\tmp> sqlcmd -r1 -v @('ScriptPath="C:\tmp"') -i SELECT.sql -S Serwer -f 1250
Bartek Zmienna
------ -------
Bartek C:\tmp

Wszystko fajnie, ale mamy podaną ścieżkę wprost. A co jeśli chcemy podać ścieżkę dynamicznie? W tym przypadku też zrobię w jednej linijce, a wynik przekażę do pętli ForEach-Object, w której wykorzystam zmienną $_. Dlaczego do pętli? Bo w przeciwnym przypadku będzie błąd Expressions are only allowed as the first element of a pipeline.

PS C:\tmp> 'ScriptPath="' + (Get-Item -Path '.\' -Verbose).FullName +'"' | ForEach-Object {sqlcmd -r1 -v @($_) -i SELECT.sql -S Serwer -f 1250}
Imie   Zmienna
------ -------
Bartek C:\tmp

Albo krócej, stosując znak % jako alias dla ForEach-Object:

PS C:\tmp> 'ScriptPath="' + (Get-Item -Path '.\' -Verbose).FullName +'"' | % {sqlcmd -r1 -v @($_) -i SELECT.sql -S Serwer -f 1250}
Imie   Zmienna
------ -------
Bartek C:\tmp

Aktualizacja 2015.10.20 Można też zastosować formatowanie za pomocą parametru -f (podpowiedziane przez Maćka J.):

PS C:\tmp> sqlcmd -S Serwer -r1 -v ScriptPath=("""{0}""" -f (Get-Item -Path '.\' -Verbose).FullName) -i SELECT.sql -f 1250

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj /  Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj /  Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj /  Zmień )

Połączenie z %s