2011-08-22 14 views
44

Używam projektu bazy danych SQL 2008 (w visual studio) do zarządzania schematem i wstępnymi danymi testowymi dla mojego projektu. Projekt atabase wykorzystuje wdrożenie pocztowe, które zawiera wiele innych skryptów wykorzystujących składnię ": r" SQLCMD.Logika warunkowa w skrypcie PostDeployment.sql przy użyciu SQLCMD

Chciałbym móc warunkowo zawierać określone pliki na podstawie zmiennej SQLCMD. Pozwoli mi to uruchomić projekt kilkakrotnie z naszą nocną kompilacją, aby skonfigurować różne wersje bazy danych z różnymi konfiguracjami danych (dla systemu multi-tenant).

Próbowałem następujące:

IF ('$(ConfigSetting)' = 'Configuration1') 
    BEGIN 
    print 'inserting specific configuration' 
:r .\Configuration1\Data.sql 
    END 
ELSE 
    BEGIN 
    print 'inserting generic data' 
:r .\GenericConfiguration\Data.sql 
    END 

Ale pojawia się błąd kompilacji: SQL01260: Wystąpił błąd krytyczny parser: Script.PostDeployment.sql

Czy ktoś widział ten błąd lub udało się tak skonfigurować skrypt postdeploymentu, aby był elastyczny? Czy też całkowicie niewłaściwie podchodzę do tego?

Dzięki, Rob

PS: Próbowałem również zmienić to wokół, tak aby ścieżka do pliku jest zmienna, similar to this post. Ale to daje mi błąd, mówiąc, że ścieżka jest niepoprawna.

Odpowiedz

31

UPDATE

Mam teraz odkrył, że jeśli składnia/else powyżej nie działa dla mnie, ponieważ niektóre z moich połączonych skryptów wymaga oświadczenia GO. Zasadniczo: r po prostu importuje inline skryptów, więc staje się on nieprawidłowym sytax.

Jeśli potrzebujesz instrukcji GO w połączonych skryptach (tak jak ja), to nie ma łatwego sposobu obejścia tego, w końcu utworzyłem kilka skryptów po wdrożeniu, a następnie zmieniając mój projekt, aby nadpisać główny skrypt wdrożenia stanowiska w czasie kompilacji w zależności od konfiguracji kompilacji. Teraz robi to, czego potrzebuję, ale wydaje się, że powinien być łatwiejszy sposób!

Dla każdego, kto potrzebuje to samo - I found this post useful

Więc w moim projekcie mam następujące opublikować pliki Wdrożenie:

  • Script.PostDeployment.sql (pusty plik, który zostanie zastąpiony)
  • Default.Script.PostDeployment.sql (linki do skryptów potrzebne do standardowej konfiguracji danych)
  • Configuration1.Script.PostDeployment.sql (linki do skryptów potrzebne do określonej konfiguracji danych)

I dodaje następujące do końca pliku projektu (prawy przycisk myszy, aby rozładować, a następnie kliknij prawym przyciskiem Edit):

<Target Name="BeforeBuild"> 
     <Message Text="Copy files task running for configuration: $(Configuration)" Importance="high" /> 
     <Copy Condition=" '$(Configuration)' == 'Release' " SourceFiles="Scripts\Post-Deployment\Default.Script.PostDeployment.sql" DestinationFiles="Scripts\Post-Deployment\Script.PostDeployment.sql" OverwriteReadOnlyFiles="true" /> 
     <Copy Condition=" '$(Configuration)' == 'Debug' " SourceFiles="Scripts\Post-Deployment\Default.Script.PostDeployment.sql" DestinationFiles="Scripts\Post-Deployment\Script.PostDeployment.sql" OverwriteReadOnlyFiles="true" /> 
     <Copy Condition=" '$(Configuration)' == 'Configuration1' " SourceFiles="Scripts\Post-Deployment\Configuration1.Script.PostDeployment.sql" DestinationFiles="Scripts\Post-Deployment\Script.PostDeployment.sql" OverwriteReadOnlyFiles="true" /> 
    </Target> 

Wreszcie, trzeba będzie konfiguracjach budowania dopasowania konfiguracji w roztworze.

Ponadto, dla każdego, kto próbuje innych arounds pracy, ja też próbowałem następujące bez powodzenia:

  1. Tworzenie zdarzenia po kompilacji, aby skopiować pliki zamiast siekać XML pliku projektu. Nie mogłem tego uruchomić, ponieważ nie mogłem utworzyć poprawnej ścieżki do pliku skryptu instalacji poinstalacyjnej. This connect issue describes the problem

  2. Używanie zmiennych dla ścieżki skryptu do przekazania do polecenia: r. Ale natknąłem się na kilka błędów w tym podejściu.

+0

Z wymogu sprawozdania GO, pracowałem wokół tego wcześniej wykonując oświadczenie dynamicznego SQL. To nie był jednak projekt MS Database. YMMV. – fiat

13

Oto, w jaki sposób obsługuję warunkowe wdrażanie w ramach procesu wdrażania po wdrożeniu w celu wdrożenia danych testowych dla konfiguracji debugowania, ale nie wydania.

Najpierw w eksploratorze rozwiązań otwórz folder właściwości projektu i kliknij prawym przyciskiem myszy, aby dodać nowy plik SqlCmd.variables.

Nazwać plik Debug.sqlcmdvars.

W pliku dodaj zmienne niestandardowe, a następnie dodaj ostatnią zmienną o nazwie $(BuildConfiguration) i ustaw wartość Debuguj.

Powtórz ten proces, aby utworzyć plik Release.sqlcmdvars, ustawiając wartość $(BuildConfiguration) na Release.

Teraz skonfiguruj swoje konfiguracje: Otwórz stronę właściwości projektu na karcie Rozmieszczenie. W górnym menu wybierz konfigurację Debuguj. W dolnym menu rozwijanym (zmienne polecenia Sql) ustaw plik na właściwość Properties \ Debug.sqlcmdvars.

Powtórz dla wersji jako: W górnym menu wybierz konfigurację Release. W dolnym menu rozwijanym (zmienne polecenia Sql) ustaw plik na właściwości Właściwości \ Release.sqlcmdvars.

Teraz wewnątrz pliku Script.PostDeployment.sql można określić logiki warunkowej, takich jak:

IF 'Debug' = '$(BuildConfiguration)' 
BEGIN 
PRINT '***** Creating Test Data for Debug configuration *****'; 
:r .\TestData\TestData.sql 
END 

W oknie Solution Explorer kliknij prawym przyciskiem myszy na najwyższym poziomie i otwarte rozwiązania Configuration Manager. Możesz określić, która konfiguracja jest aktywna dla twojej kompilacji. Można również określić konfigurację w wierszu komend MSBUILD.EXE.

W tym miejscu - teraz twoje kompilacje dla programistów mają dane testowe, ale nie twoja wersja wydania!

+9

Jego 2015 i mam najnowsze SSDT i VS2013 U4 i nie ma zakładki o nazwie "Deploy" ani nawet nie widziałem żadnego sposobu importowania pliku zmiennych SQLCMD. Naprawdę zdezorientowany ... – riix

8

Jak Rob pracował, instrukcje GO są niedozwolone w połączonych skryptach SQL, ponieważ zagnieździłoby się to w instrukcjach BEGIN/END.

Mam jednak inne rozwiązanie do swego - jeśli to możliwe, usunąć dowolny GO sprawozdania z przywoływanych skryptów i umieścić pojedynczy jeden po rachunku końcowego:

IF '$(DeployTestData)' = 'True' 
BEGIN 
    :r .\TestData\Data.sql 
END 
GO -- moved from Data.sql 

Zauważ, że ja również utworzony nowa zmienna w moim pliku sqlcmdvars o nazwie $ (DeployTestData), która umożliwia włączanie/wyłączanie wdrażania skryptu testowego.

+1

Zszedłem również na tę ścieżkę, jednak nakłada ona niejawny wymóg, aby wszystkie skrypty miały jednoznacznie nazwane zmienne. Może to stanowić problem w przypadku złożonych baz danych. – bwerks

+0

Poszedłem tą ścieżką i działa dobrze. Dzięki! – Raffaeu

12

Udało mi się obejść problem za pomocą noexec method.

Więc zamiast tego:

IF ('$(ConfigSetting)' = 'Configuration1') 
BEGIN 
    print 'inserting specific configuration' 
    :r .\Configuration1\Data.sql 
END 

I odwrócone warunkowego i ustawić noexec NA przeskoczyć importowanego Statement (s) wygląda następująco:

IF ('$(ConfigSetting)' <> 'Configuration1') 
    SET NOEXEC ON 

:r .\Configuration1\Data.sql 

SET NOEXEC OFF 

Upewnij się go włączyć wycofaj się, jeśli chcesz wykonać dowolne kolejne instrukcje.

+0

Pracowałem dla mnie. Świetny pomysł. Nadal działa w SSDT dla VS 2013 w skryptach PostDeploy. – bwerks

1

Znalazłem hack from an MSDN blog, który działał całkiem dobrze. Sztuką jest napisanie poleceń do pliku skryptu tymczasowego, a następnie wykonanie tego skryptu. Zasadniczo odpowiednik dynamicznego SQL dla SQLCMD.

-- Helper newline variable 
:setvar CRLF "CHAR(13) + CHAR(10)" 
GO 
-- Redirect output to the TempScript.sql file 
:OUT $(TEMP)\TempScript.sql 

IF ('$(ConfigSetting)' = 'Configuration1') 
    BEGIN 
    PRINT 'print ''inserting specific configuration'';' + $(CRLF) 
    PRINT ':r .\Configuration1\Data.sql' + $(CRLF) 
    END 
ELSE 
    BEGIN 
    PRINT 'print ''inserting generic data'';' + $(CRLF) 
    PRINT ':r .\GenericConfiguration\Data.sql' + $(CRLF) 
    END 
GO 
-- Change output to stdout 
:OUT stdout 

-- Now execute the generated script 
:r $(TEMP)\TempScript.sql 
GO 

Plik TempScript.sql wtedy zawierać albo:

print 'inserting specific configuration'; 
:r .\Configuration1\Data.sql 

lub

print 'inserting generic data'; 
:r .\GenericConfiguration\Data.sql 

zależności od wartości $(ConfigSetting) i nie będzie żadnych problemów z GO sprawozdania itp, gdy jest to wykonany.

+0

Szkoda, że ​​to nie działa. Jeśli obsługiwane są skrypty przed/po wdrożeniu: na zewnątrz byłoby świetnie, ale jeśli spróbujesz, otrzymasz komunikat "nieobsługiwany". – bielawski

1

Zainspirowało mnie rozwiązanie Roba Birda. Jednak po prostu używam Build Events, aby zastąpić skrypty po wdrożeniu w oparciu o wybraną konfigurację kompilacji.

  1. Mam jeden pusty "dummy" skrypt wdrażania post.
  2. Konfiguruję zdarzenie poprzedzające kompilację, aby zastąpić ten "fałszywy" plik w oparciu o wybraną konfigurację kompilacji (patrz załączony rysunek).
  3. Skonfigurowałem zdarzenie post-build, aby umieścić plik "dummy" po zakończeniu kompilacji (patrz załączony rysunek). Powodem jest to, że nie chcę generować zmian w kontroli zmian po kompilacji.

Build Events setup example