none
Datenbankverbindung per Variable steuern (Auslieferung in verschiedene Umgebungen) RRS feed

  • Frage

  • Hallo,

    ich soll zu einem zugekauften Standardprogramm eine Schnittstelle zu unserer bestehenden Datenhaltung erstellen. Technisch stelle ich dafür auf in "unserer" Datenbank Views zur Verfügung, auf die ich über einen Verbindungsserver von dem neuen Programmserver aus zugreife.

    Natürlich gibt es von unserer Datenbank mehrere Instanzen: Entwicklung, Test, Live... und auch das neue Programm hat eine Live-Installation und eine Entwicklungs- und Testinstallation.

    Severversion ist jeweils 2016.

    Nun hätte ich gerne von Visual Studio folgendes Verhalten:

    Wenn ich das Projekt in die Entwicklungsdatenbank veröffentliche, sollte der Verbindungsserver natürlich auch auf die Entwicklungsdatenbank der alten Datenhaltung zeigen. Nach Abschluss der Tests veröffentliche ich auf den Live-Server und der Verbindungsserver "zeigt" auf die Live-Datenbank.

    Mein Plan war folgender: In den Pre-Deployment-Skripten setze ich in Abhängikeit vom Ziel der Veröffentlichung die Variablen $(LinkedServer) etc. In den Skripten zur Erstellung konnte ich diese Variablen schon einbauen. Leider erhalte ich im Skript aber bei

    :setvar LinkedServer [A1-SQL-Test]
    eine Fehlermeldung SQL80001:Incorrect Syntax near :

    Ist das also überhaupt der richtige Weg? Und wenn ja, wie bekomme ich ihn zum Laufen?

    Vielen Dank schon mal

    Wolfgang

    Dienstag, 7. April 2020 13:24

Antworten

  • :setvar LinkedServer [A1-SQL-Test]

    eine Fehlermeldung SQL80001:Incorrect Syntax near :

    Hallo Wolfgang,

    diese Fehlermeldung erhält man in SSMS in einem normalen Query Window oder in eigenen Programmen, weil diese Syntax kein echtes T-SQL ist.

    Die Art der Variablendeklaration kennt nur das Tool SqlCmd und SSMS, wenn man über Menu "Abfrage" in den SQLCMD-Modus umschaltet, sowie SSDT Datenbankprojekte, hier aber auch nur in den Pre- und Postdeployment Skripten.


    Olaf Helper

    [ Blog] [ Xing] [ MVP]

    • Als Antwort markiert AWombl Donnerstag, 16. April 2020 09:42
    Mittwoch, 8. April 2020 06:24
  • SQL71561: "Sicht: [dbo].[MyView]" enthält einen nicht aufgelösten Verweis auf "Objekt [$(ServerName)].[$(DatabaseName)].[SchemaName].[ViewName]".    

    Hallo Wolfgang,

    4-Part Qualifier, also Verweise auf einen Verbindungsserver, funktionieren in SSDT Datenbankprojekte gar nicht und 3-Part Qualifier funktionieren nur, wenn Du im Projekt einen entsprechenden Datenbankverweis hinzufügst, das gilt auch für die Systemdatenbanken "master" und "msdb".


    Olaf Helper

    [ Blog] [ Xing] [ MVP]

    Donnerstag, 9. April 2020 06:55

Alle Antworten

  • Hallo Wolfgang,

    ich denke, Alias-Namen könnten Dir hier helfen!

    SSIS Pakete verteilen

    Ich hatte das zu SSIS-Paketen und SSRS-Reports geschrieben, aber Verbindungsserver sollten auch so funktionieren. 


    Einen schönen Tag noch, Christoph - http://www.insidesql.org/blogs/cmu

    Dienstag, 7. April 2020 13:54
  • Der Verbindungsserver ist ja datenbankneutral und stellt nur einen Dienst bereit.
    Du kannst aber in der jeweiilgen DB eine View erstellen, die korrekt auf den richtigen Verbindungsserver verweist-.
    Der Name der View ist in allen DB's identisch.

    create view Ziel as (select * from openquery(verbserver, 'select * from mytable'))

    Das schöne daran ist  auch, dass eine View dieser Art auch Insert/Update/Delete unterstützt.
    https://docs.microsoft.com/de-de/sql/t-sql/functions/openquery-transact-sql?view=sql-server-ver15

    Dienstag, 7. April 2020 13:59
  • Hallo, Christoph,

    danke für den Link und die Hinweise. Habe ich das richtig verstanden, dass ich über den Alias den Namen des Zielservers vereinheitliche, eine Auswahl der Datenbank (Entwicklung und Test liegen auf einem Server) muss über einen zweiten Schritt geschehen?

    Danke und Gruß

    Wolfgang

    Dienstag, 7. April 2020 16:58
  • Eine semantische (und nicht technische) Namenswahl beim Verbindungsserver macht hier natürlich mehr Sinn als mein Konstrukt. Trotzdem schaffe ich es nicht, den Code gleich zu lassen und auf einem Server zwei unterschiedliche Datenbanken anzusteuern (Entwicklung und Test).

    Hast Du dafür auch noch einen Tip?

    Danke und Gruß

    Wolfgang

    Dienstag, 7. April 2020 17:20
  • :setvar LinkedServer [A1-SQL-Test]

    eine Fehlermeldung SQL80001:Incorrect Syntax near :

    Hallo Wolfgang,

    diese Fehlermeldung erhält man in SSMS in einem normalen Query Window oder in eigenen Programmen, weil diese Syntax kein echtes T-SQL ist.

    Die Art der Variablendeklaration kennt nur das Tool SqlCmd und SSMS, wenn man über Menu "Abfrage" in den SQLCMD-Modus umschaltet, sowie SSDT Datenbankprojekte, hier aber auch nur in den Pre- und Postdeployment Skripten.


    Olaf Helper

    [ Blog] [ Xing] [ MVP]

    • Als Antwort markiert AWombl Donnerstag, 16. April 2020 09:42
    Mittwoch, 8. April 2020 06:24
  • Das hast du (leider) falsch verstanden.

    Wenn eine App mit einer DB verknüpft ist, enthält diese normalerweise alle Tabellen und Sichten, die benötigt werden.
    Den Unterschied, ob eine Tabelle in der DB liegt oder via Verbindungsserver erreicht wird, braucht die App letztlich nicht zu interessieren.

    Du richtest also deine 2 Verbindungen via Verbindungsserver ein, also z.B. "DBEcht" und "DBTest".
    In der Datenbank "MyDBEcht" erstellst du eine View "ZielTabelle" auf "DBEcht" und in der Datenbank "MyDBTest" eine View "ZielTabelle" auf "DBTest" .

    Deine App arbeitet letztlich immer mit "Zieltabelle".
    Dies lässt sich mit beliebig vielen Echt/Test-DB's durchziehen.

    Mittwoch, 8. April 2020 08:15
  • Hallo Olaf,

    danke, das hilft doch schon einmal weiter.

    Nun würde ich gerne eine View erzeugen in der Art

    CREATE VIEW [dbo].[MyView]
    	AS SELECT * FROM  [$(OtherServer)].[$(DatabaseName)].[SchemaName].[ViewName]

    Ich habe natürlich die Zieldatenbank als Datenbankverweis angelegt. Allerdings erkennt das System die Variablen ServerName und DatabaseName nicht. Hier hat das System den Wunsch, eine Variable zu verwenden, die genauso heißt, wie die Datenbank bzw. der Server (gut, damit könnte ich leben, ich würde nur gern verstehen, wo und wie diese Variablen angelegt werden).

    Aber ich erhalte auch die Fehlermeldung

    SQL71561: "Sicht: [dbo].[MyView]" enthält einen nicht aufgelösten Verweis auf "Objekt [$(ServerName)].[$(DatabaseName)].[SchemaName].[ViewName]".   

    (wie soll dem Interpreter auch klar sein, wie diese Verbindung zustande kommen soll, das kann ja erst funktionieren, wenn die Variablen belegt sind)

    /*

    Und ich erhalte einen ganzen Haufen Fehlermeldungen von der Sorte

    Der Verweis auf externe Elemente der Quelle mit dem Namen 'master.dacpac' konnte nicht aufgelöst werden, da keine derartige Quelle geladen wurde,

    sowohl für die master- als auch für die msdb-Datenbank.

    Zumindest dieser Teil der Frage hat sich erledigt. Ich weiß, warum das System die Verweise haben will und konnte sie einbinden.

    */

    Ist eine solche Verwendung überhaupt möglich (Da Du von den Pre- und Post-Deployment-Skripten schreibst, habe ich Zweifel an der Auflösung dieser Konstrukte in der Definition einer View)

    Vielen Dank im Vorfeld schon mal für Deine Zeit und den Input,

    Wolfgang


    • Bearbeitet AWombl Mittwoch, 8. April 2020 18:38
    Mittwoch, 8. April 2020 15:08
  • Genau da ist ja das Problem. Ich habe ein Projektfile, das ich gerne auf verschiedene Server und in verschiedene Datenbanken ausliefern möchte. Und in Abhängigkeit vom Ziel der Auslieferung soll sich diese Verbindung automatisch auf den korrekten Gegenpart einstellen.

    Mit Deinem Modell müsste ich entweder verschiedene Projektfiles führen, da der Verweis auf MyDBEcht und MyDBTest in der View-Definition hart verdrahtet ist. Und das möchte ich gern vermeiden, um der To-Do-Liste für eine Auslieferung nicht noch einen Punkt hinzuzufügen, der im schlimmsten (Fehler)Fall eine Testinstallation mit der Live-Datenbank verbindet.

    Ein semantisch benannter Verbindungsserver, der auf allen Systemen gleich heißt (und der nicht Teil der Projektdatei sein darf, der muss manuell auf jedem Server angelegt sein) bzw. ein Alias lösen das Problem auch nur halb, da ich den Verbindungsserver/Alias auf jedem Server genau einmal einrichten kann. Da müsste ich mir dann für jede zusätzliche Instanz (Test2, SpielwieseFuerEntwicklungsprojekt,...) einen eigenen SQL-Server auf einer eigenen virtuellen Maschine einrichten. Den Aufwand scheue ich auch.

    Ich hoffe, ich verstehe Dich (immer noch) falsch...

    Danke und Gruß

    Wolfgang

    Mittwoch, 8. April 2020 15:25
  • Ein SQL-Server kann beliebig viele DB's und ebenso beliebig viele Verbindungsserver verwalten (je nach Lizenz).
    Es besteht also kein Grund neue Instanzen zu installieren (außer wenn du verschiedene Versionen betreibst).

    Eine View kann man nicht so dynamisch erstellen wie du es gerne hättest. Die Definition ist ebenso statisch wie eine Tabelle.

    Wenn du eine DB auslieferst würde ich ein Programm anbieten, dass den Vorgang
    - Erstellen Verbindungsserver
    - Erstellen View auf die benötigten Tabellen
    für die auszuwählende DB einrichtet.
    Dies könnte auch eine Funktion innerhalb deiner App sein (Optionsdialog Schnittstelle aktivieren/deaktivieren).

    https://docs.microsoft.com/de-de/sql/relational-databases/linked-servers/create-linked-servers-sql-server-database-engine?view=sql-server-ver15#TsqlProcedure

    Das sollte doch flexibel genug für einen Kunden sein, dass dieser die DB's benennen kann.
    Zur Laufzeit weißt du durch die Existenz der View/s ob die Schnittstelle eingerichtet ist.

    Mit der obigen Syntax für "Create View ..." bist du auf bestimmte Datenbanken beschränkt, die SQL-Server-Syntax unterstützen.
    Mittels OPENQUERY bist du Datenbankneutral und kannst sogar Excel-/CSV-Dateien einbinden.
    Mittwoch, 8. April 2020 16:19
  • Hallo Wolfgang,

    ja das ist richtig. Wenn Du zwei Umgebungen auf dem gleichen Server hast, dann kannst Du mit einem Alias alleine nicht arbeiten.


    Einen schönen Tag noch, Christoph - http://www.insidesql.org/blogs/cmu

    Donnerstag, 9. April 2020 06:36
  • SQL71561: "Sicht: [dbo].[MyView]" enthält einen nicht aufgelösten Verweis auf "Objekt [$(ServerName)].[$(DatabaseName)].[SchemaName].[ViewName]".    

    Hallo Wolfgang,

    4-Part Qualifier, also Verweise auf einen Verbindungsserver, funktionieren in SSDT Datenbankprojekte gar nicht und 3-Part Qualifier funktionieren nur, wenn Du im Projekt einen entsprechenden Datenbankverweis hinzufügst, das gilt auch für die Systemdatenbanken "master" und "msdb".


    Olaf Helper

    [ Blog] [ Xing] [ MVP]

    Donnerstag, 9. April 2020 06:55