it-swarm.com.de

Warum erhalte ich die Fehlermeldung "XML-Datentyp wird in verteilten Abfragen nicht unterstützt", wenn ein Verbindungsserver nach Nicht-XML-Daten abgefragt wird?

Ich habe zwei SQL Server (mit SQL Server 2008) mit den Namen DATA01 und DATA02. DATA02 hat eine Verbindungsserverdefinition LINK, die auf DATA01 zeigt, wobei eine geeignete Benutzerzuordnung eingerichtet ist. Auf DATA01 gibt es eine Datenbank MyDatabase, die diese beiden Tabellen enthält:

CREATE TABLE T_A (
    Id int
)

CREATE TABLE T_B (
    Id int,
    Stuff xml
)

Wenn ich diesen Befehl von DATA02 aus ausführen, erhalte ich die erwarteten Daten:

SELECT Id FROM LINK.MyDatabase.dbo.T_A;

Wenn ich diesen Befehl von DATA02 aus ausführen, erhalte ich jedoch eine Fehlermeldung:

SELECT Id, Stuff FROM LINK.MyDatabase.dbo.T_B;

Der Fehler ist

Der XML-Datentyp wird in verteilten Abfragen nicht unterstützt. Das entfernte Objekt 'DATA02.MyDatabase.dbo.T_B' enthält XML-Spalten.

Und seltsamerweise dieser Befehl:

SELECT Id FROM LINK.MyDatabase.dbo.T_B;

gibt auch den gleichen Fehler, obwohl ich die XML-Spalte nicht SELECTing! Was ist los?

49
AakashM

Dies ist ein Mangel in SQL Server. Die bloße Existenz einer XML-Spalte in der Tabelle hindert sie daran, an verteilten Abfragen (z. B. Abfragen über eine Verbindungsserververbindung) teilzunehmen. Dieses wird in der Dokumentation erwähnt wenn auch nicht besonders prominent. Den main Connect-Fehlerbericht finden Sie hier und einen ähnlichen Bericht hier . Letzteres gibt zwei Problemumgehungen:

  1. Erstellen Sie eine Ansicht [a] ohne die XML-Spalten auf dem Remote-Server und fragen Sie diese ab.

    In Ihrem Beispiel würde dies das Hinzufügen einer Sicht zu MyDatabase Beinhalten, die wie folgt aussieht:

    CREATE VIEW V_T_B AS SELECT Id FROM T_B;
    

    Sie können diese Ansicht dann über den Link abfragen, um die Iddata abzurufen. Beachten Sie das so etwas

    SELECT Id FROM ( SELECT Id FROM T_B ) T_B;
    

    nicht Arbeit.

  2. Verwenden Sie eine Pass-Through-Abfrage im Formular

    SELECT * from OPENQUERY (... )
    

    Diese Methode hat den Vorteil, dass keine Änderung an der -Datenbank erforderlich ist. Der Nachteil ist, dass es nicht mehr möglich ist, die vierteilige Standardbenennung für lokale und verknüpfte Daten zu verwenden. Die Abfrage würde so aussehen

    SELECT Id FROM OPENQUERY(DATA02, 'SELECT Id FROM T_B') T_B;
    

    Wenn Sie tatsächlich do die XML-Daten haben möchten, ist diese Methode (zusammen mit Mit Umwandlung in und aus einem Nicht-XML-Datentyp) erforderlich

    SELECT Id, CAST(Stuff AS XML) Stuff 
    FROM OPENQUERY(DATA02, 'SELECT Id, CAST(Stuff AS nvarchar(max)) Stuff 
                            FROM T_B') T_B;
    

Beachten Sie, dass der Fehler erstmals in SQL Server 2005 gemeldet wurde und in SQL Server 2014 nicht behoben wird.

86
AakashM

Versuche dies:

  • Erstellen Sie eine Ansicht auf der Quellenseite mit XML-Umwandlung in nvarchar (max):

CREATE VIEW vXMLTestASSELECT-Umwandlung (Stuff as nvarchar (max)) als STUFF FROM T_B

  • Sie können es auf der Zielseite mit Umwandlung in XML auswählen

SELECT Cast (Stuff as XML) als Stuff FROM OPENQUERY (DATA02, 'SELECT Stuff FROM vXMLTest')

Diese Lösung funktioniert für mich in 2008R2.

9
Csaba Molnár

Ich habe einen anderen Weg gefunden, dies zu tun:

  1. Erstellen Sie einen Linked Server auf DATA01, DATA02 oder sogar einem dritten Server (möglicherweise lokal).
  2. Führen Sie Ihre Abfrage mit EXEC [linked_server].[sp_sqlexecute] aus.

Warum ziehe ich diese Methode der Erstellung von Ansichten oder der Verwendung von OPENQUERY vor?

  1. Diese Methode erfordert keine Berechtigungen für den Linked Server (Sie müssen keine Ansichten erstellen).
  2. Sie können Ihrer Abfrage Parameter mit der sp_sqlexecute-Syntax übergeben ( Weitere Informationen zu sp_sqlexecute finden Sie hier ). Für OPENQUERY müssen Sie eine STRING oder TEXT_Lex übergeben, was bedeutet, dass alle Werte direkt in diese Funktion eingegeben werden müssen.

Hier ist das Beispiel:

DECLARE @UserID UNIQUEIDENTIFIER = ''

DECLARE @SearchForUserParams NVARCHAR(MAX) = N'@UserID UNIQUEIDENTIFIER';  
DECLARE @SearchForUserQuery NVARCHAR(MAX) = 
N'SELECT
    UserID,
    Username,
    Email,
    CONCART(NVARCHAR(MAX), UserDataXml) AS UserDataXml
FROM User
WHERE UserID = @UserID
'

EXEC [linked_server].[dbo].[sp_executesql] 
    @SearchForUserQuery,
    @SearchForUserParams,
    @UserID = @UserID
1
semptra