none
SQL Server - Job Agent - Query Linkedserver RRS feed

  • Allgemeine Diskussion

  • Sehr geehrte Damen und Herren,

    ich habe mal eine Frage bezüglich einer T-SQL Abfrage im Job. Im Query wird auf einen Verbindungsserver Daten abgefragt! Der Query funktioniert auch einwandfrei, wenn ich den manuell ausführe. Wenn ich aber den Job ausführe, erhalten ich folgende Meldung.

    Ausgeführt als Benutzer:"Domäne\BENUTZER". Falsche Syntax in der Nähe von "LINKEDSERVER"... 

    Ich habe den SQL Server Agent auch mal einen Domänen\Benutzer zugewiesen. Meldung kommt trotzdem noch.

    Hat jemand vill eine Idee, wie ich das Problem beheben kann oder kann mir Tipps geben?

    Gruß

    Mittwoch, 21. Februar 2018 12:59

Alle Antworten

  • a) kommt es auf die Art der Abfrage an: "Select *  from LinkedServer.Database.Schema.Table" oder "select * from OpenQuery('LinkedServer', 'Select * from Table')".

    b) Logon-Informationen für einen Linked-Server sollte man der Einfachheit wegen in die dortige Konfiguration schreiben. Ggf. kommt es hier zum Konflikt da keine Anmeldung erfolgt ist.

    Mittwoch, 21. Februar 2018 13:14
  • a) SELECT * FROM LinkedServer.Databae.Schema.Table

    b) Was genau meinst du damit?

    Mittwoch, 21. Februar 2018 13:30
  • Normalerweise muss man sich auch bei LinkedServer an der Zieldatenbank anmelden.

    Diese Anmeldung kann man statisch in der Konfiguration hinterlegen (User/Kennwort), so dass keine individuelle Anmeldung erfolgen muss.
    Diese Anmeldung erfolgt häufig durch den Treiber selber, der u.U. diese Anmeldung auch cached.
    Deshalb klappts eben im Dialog, aber nicht im Batch, da ja da keiner für die Anmeldung da ist.

    Mittwoch, 21. Februar 2018 13:44
  • Habe das so statisch hinterlegt: Muss ich evtl. die Zuordnung von lokalen Serveranmeldungen eintragen?

    Mittwoch, 21. Februar 2018 14:00
  • Lokale Anmeldungen machst du ja mit deinem Script/Programm.
    Beim LinkedServer kann man eben je lokaler Anmeldung eine individuelle Remoteanmeldung und eben eine Default-Anmeldung hinterlegen.

    Ansonsten hat meine Erfahrung gezeigt, dass es besser ist per OpenQuery() oder EXEC (Non-Queries) auf LinkedServer (außer wenn es ein entfernter SQL-Sever ist) zuzugreifen, da es sonst u.U. zu SQL-Dialektproblemen kommt.

    Mittwoch, 21. Februar 2018 14:18
  • Ja gut, dass habe ich ja gemacht, jedoch hat es mir keinen Erfolg gebracht.OpenQuery() habe ich auch schon probiert.

    SELECT * FROM OpenQuery(LinkedServer,
    '
    DELCARE var1 INT, var2 INT
    SET var1 = Wert1
    SET var2 = Wert2
    SELECT COUNT(var1 + var2)
    ')
    

    Funkioniert so nicht. Habe das Gefühl das er nicht mit Variablen arbeiten kann. Stimmt das? Bin halt noch blutiger Anfänger.

    Mittwoch, 21. Februar 2018 14:32
  • Nun, was du da abgibst hat nicht entfernt mit SQL zu tun.
    Das ist irgendeine rudimentäre Geschichte aus SQL-Script u.a.

    Wenn du einen LinkedServer zu einer DB hast, machdoch erst mal einen

    select * from OpenQuery(LinkedServer, 'select * from MyTable')

    wobei MyTable eine dir bekannte Tabelle im Zielserver sein muss.

    Mittwoch, 21. Februar 2018 15:36
  • Habe das mal mit einer normalen Abfrage getestet ohne jeglichen schnick schnack!

    Wenn ich das wieder direkt ausführe, klappt es einwandfrei. Jedoch wenn ich das über den Trigger laufen lasse als Job geht es nicht.

    Habe aber diesmal eine bessere Fehlermeldung bekommen:

    Meldung "208",Ebene "16", Status "1", Server "LinkedServer" ....

    "Anweisung konnte nicht vorbereitet werden." Der OLE DB-Anbieter "SQLNCLI11" für den Verbindungsserver hat die Meldung "Die verzögerte Bereitstellung konnte nicht beendet werden." zurückgegeben.

    Mittwoch, 21. Februar 2018 19:49
  • Daher noch mal die Frage: Machst du einen native SQL oder einen OpenQuery?

    "Anweisung konnte nicht vorbereitet werden." => Wahrscheinlich ein Problem der SQl-Syntax/des Dialekts.

    Donnerstag, 22. Februar 2018 08:20
  • Poste doch mal das Statement!

    Vermeide außerdem möglichst ein "Select *"!

    Wie bereits erwähnt ist die Verwendung mit OpenQuery sicherer in der Handhabung!


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

    Donnerstag, 22. Februar 2018 09:36
  • Ein einfaches Beispiel der Inkompatibilität:

    Im SQL-Server werden Namen, deren Konvention nicht eingehalten werden, in eckige Klammern gesetzt.
    Im SQL-Standard sind das Anführungszeichen:

    SQL-Server: select [Artikel-Nr] from [Artikel-Stamm]
    SQL-Standard: Select "Artikel-Nr" from "Artikel-Stamm"

    Verwendest du nun einen "Select * from VerbServer.DB.Schema.Table" wird vom SQL-Server das Schema abgefragt um die Felder zu erhalten und den Select umzubauen.
    Hat die Quelltabelle nun ungültige Namen, so setzt der SQL-Server diese in eckige Klammern, da Microsoft der Meinung ist, jeder andere SQL-Anbieter hat dies so zu verstehen.
    Versteht der VerbServer aber keine eckigen Klammern, so wird der SQL wegen Dialekt-Fehler abgewiesen (keine Vorbereitung ....).

    Anders bei OpenQuery:

    select [Artikel-Nr] from OpenQuery(VerbServer, 'select "Artikel-Nr" from MyTable') funktioniert hingegen. Ebenso auch ein "select * ", da die Schemaabfrage nun nur noch auf das Ergebnis des OpenQuery geht und die eckigen Klammern nicht durchgeroutet werden.

    Das selbe gilt auch für viele SQL-Funktionen wie z.B. Substring(), Upper(), Lower() usw., da diese durchaus je SQL-Dialekt unterschiedlich heißen, aufgebaut sind oder gar nicht vorhanden sind.

    Der SQL-Standard gibt diesbezüglich leider sehr wenig her.

    Daher:
    Bei Verbindungsservern (nicht Microsoft SQL-Server) sollte man grundsätzlich OpenQuery() und EXEC 'Native SQL' on VerbServer verwenden, alles andere führt unweigerlich zu diversen Problemen.

    Donnerstag, 22. Februar 2018 10:25
  • Habe jetzt nochmal einfachshalber folgende Querys probiert, die über den Job Agent nicht laufen, aber beide normal funktionieren.

    SELECT * FROM OPENQUERY([LinkedServer],'SELECT * FROM [dbo].[TabellenName]') > die lange Fehlermeldung wie oben beschrieben

    SELECT * FROM OPENQUERY("LinkedServer",'SELECT * FROM "dbo"."TabellenName"') > Fehlermeldung: Falsche Synthax

    Donnerstag, 22. Februar 2018 11:56
  • Dann ist dein LinkedServer ja ein SQL-Server und das Syntaxproblem sollte ja nicht bestehen.

    Vielleicht schaust du dir das noch mal genauer an:

    https://docs.microsoft.com/de-de/sql/relational-databases/linked-servers/create-linked-servers-sql-server-database-engine

    Donnerstag, 22. Februar 2018 12:04
  • Probier doch mal das hier:

    SELECT * FROM OPENQUERY(LinkedServer,'SELECT * FROM [dbo].[TabellenName]');


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

    Donnerstag, 22. Februar 2018 14:50
  • Hat er doch:

    "SELECT * FROM OPENQUERY([LinkedServer],'SELECT * FROM [dbo].[TabellenName]') > die lange Fehlermeldung wie oben beschrieben"

    Donnerstag, 22. Februar 2018 14:51
  • Den Link von bfuerchau habe ich mir auch schon angeschaut.

    Habe sogar schon MS DTC aktiviert lt. der Anleitung:

    https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc753510(v=ws.10)

    Das leider auch alles ohne Erfolg. Ich weiß echt nicht mehr weiter. Irgendwas muss ich übersehen haben..

    Donnerstag, 22. Februar 2018 17:29
  • Meiner Meinung nach liegt der Fehler bei der Anlage des LinkedServers. Normalerweise ist der Name des Verbindungsservers auch der Netzwerkname des Servers.

    Also bitte noch mal neu und korrekt anlegen, dann sollte es eigentlich funktionieren.

    Ich kann mir nicht vorstellen, dass die Maschine "LinkedServer" heißt.

    USE [master]
    GO
    EXEC master.dbo.sp_addlinkedserver @server = N'<Netzwerkname>', @srvproduct=N'SQL Server'
    
    GO
    EXEC master.dbo.sp_serveroption @server=N'<Netzwerkname>', @optname=N'collation compatible', @optvalue=N'false'
    GO
    EXEC master.dbo.sp_serveroption @server=N'<Netzwerkname>', @optname=N'data access', @optvalue=N'true'
    GO
    EXEC master.dbo.sp_serveroption @server=N'<Netzwerkname>', @optname=N'dist', @optvalue=N'false'
    GO
    EXEC master.dbo.sp_serveroption @server=N'<Netzwerkname>', @optname=N'pub', @optvalue=N'false'
    GO
    EXEC master.dbo.sp_serveroption @server=N'<Netzwerkname>', @optname=N'rpc', @optvalue=N'false'
    GO
    EXEC master.dbo.sp_serveroption @server=N'<Netzwerkname>', @optname=N'rpc out', @optvalue=N'false'
    GO
    EXEC master.dbo.sp_serveroption @server=N'<Netzwerkname>', @optname=N'sub', @optvalue=N'false'
    GO
    EXEC master.dbo.sp_serveroption @server=N'<Netzwerkname>', @optname=N'connect timeout', @optvalue=N'0'
    GO
    EXEC master.dbo.sp_serveroption @server=N'<Netzwerkname>', @optname=N'collation name', @optvalue=null
    GO
    EXEC master.dbo.sp_serveroption @server=N'<Netzwerkname>', @optname=N'lazy schema validation', @optvalue=N'false'
    GO
    EXEC master.dbo.sp_serveroption @server=N'<Netzwerkname>', @optname=N'query timeout', @optvalue=N'0'
    GO
    EXEC master.dbo.sp_serveroption @server=N'<Netzwerkname>', @optname=N'use remote collation', @optvalue=N'true'
    GO
    EXEC master.dbo.sp_serveroption @server=N'<Netzwerkname>', @optname=N'remote proc transaction promotion', @optvalue=N'true'
    GO
    USE [master]
    GO
    EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname = N'<Netzwerkname>', @locallogin = NULL , @useself = N'True'
    GO


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


    Freitag, 23. Februar 2018 08:16
  • Die Maschine heißt defintiv nicht 'LinkedServer'.. Das war neu ein ALIAS für den richtigten Netzwerknamen vom Verbindungsserver. Werde aber später versuchen, den Verbindungsserver mal auf deinen Weg einzurichten.
    Freitag, 23. Februar 2018 12:52
  • Ich habe jetzt mal mit deinem Script den Verbindungsserver angelegt.

    Jetzt bekomme ich schon bei einer normalen Abfrage folgende Fehlermeldung:

    Der OLE DB-Anbieter "SQLNCLI11" für den Verbindungsserver "<Netzwerkname(LinkedServer)>" hat die Meldung "Die verzögerte Bereitstellung konnte nicht beendet werden." zurückgeben.
    Meldung 8180, Ebene 16, Status 1, Zeile 1
    Anweisung(en) konnte(n) nicht vorbereitet werden.
    Meldung 208, Ebene 16, Status 1, Zeile 1
    Ungültiger Objektname 'dbo.<Tabellenname>'.
    

    Genau die selbe Abfrage hat, jedoch vorher normal funktioniert gehabt.

    Freitag, 23. Februar 2018 14:38
  • Also normalerweise ist der Name des LinkedServer's vollkommen egal, da man über die Verbindungseigenschaften einen Treiber (OLEDB) oder ODBC (ggf. mit DSN-Konfiguration) sowie gezielt mit einer Datenbank verbindet.

    Bei nativen SQL's per OpenQuery ist dann also der Name der DB nicht mehr anzugeben, da man ja bereits mit der DB verbunden ist.

    Nun gibt es noch die Möglichkeit, innerhalb einer DB mehrere Schemas einzurichten, was quasi wie eine DB in einer DB wäre. Dann müssten Tabellen mit "Schemaname.TableName" referenziert werden.
    I.d.R. wird aber beim SQL-Server nicht mit Schemas gearbeitet und soweit ich weiß ist "dbo" der Name einer Datenbank auf dem SQL-Server.

    Nun kommt es also noch mal darauf an, wie du deinen Linked Server konfiguriert hast.

    Außerdem habe ich auch schon festgestellt, dass man mache Treiber nur "Out of Process" verwenden kann (Konfiguration).

    Samstag, 24. Februar 2018 11:08
  • Das dazugehörige SQL wäre schon noch interessant gewesen. Hast Du auch den Datenbank-Namen im SQL mit aufgeführt?

    Der Verbindungsserver stellt nur die Verbindung zum Server her und Du landest in der Default-Database des aktuellen Kontos. Für andere Datenbanken solltest Du dann die dreiteilige Syntax verwenden: Datenbank.Schema.Objektname


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

    Donnerstag, 1. März 2018 12:28