SQL SERVER – Fix : Error : Msg 9514 Xml data type is not supported in distributed queries. Remote object ‘OPENROWSET’ has xml column(s)

Msg 9514 means your query crossed a linked server and found an XML column on the other side. SQL Server will not move the XML type across that boundary. The fix is to stop asking for it as XML, and there are four ways to do that depending on whether you need the contents.

Torn continuous printer paper spilling off a bench under a red desk lamp

Torn continuous printer paper spilling off a bench under a red desk lamp

The Error

Msg 9514, Level 16, State 1, Line 1
Xml data type is not supported in distributed queries. Remote object
'LINKEDSRV.Sales.dbo.Documents' has xml column(s).

Read the object name in the message. It names the exact remote table that has the column, which saves you hunting through a join of six tables.

Why It Happens

XML in SQL Server is not text. It is a parsed, typed structure in its own internal format. The methods on it are part of the engine.

A distributed query hands values between two instances through the OLE DB layer. That layer cannot carry the XML type. So SQL Server stops before it starts, rather than shipping something it cannot rebuild.

A few other types behave the same way. Meet this with XML and you may meet it again with a user defined type.

You May Not Need the Column at All

Check first, because this is the usual answer. SELECT star pulled the column in and nobody wanted it.

-- fails
SELECT * FROM LINKEDSRV.Sales.dbo.Documents;

-- works, because the xml column is not named
SELECT doc_id, created_at, customer_id
FROM LINKEDSRV.Sales.dbo.Documents;

Here is another reason to name your columns. Build a view over the remote table that never mentions the XML column. That solves it for everybody.

Convert It on the Far Side

If you do need the contents, turn the XML into text where it lives. Then bring the text across. OPENQUERY runs the whole statement on the remote server.

SELECT *
FROM OPENQUERY(LINKEDSRV,
    'SELECT doc_id, CAST(payload AS nvarchar(max)) AS payload_text
     FROM Sales.dbo.Documents');

The conversion happens before anything crosses the wire. The boundary only ever sees nvarchar. Cast it back locally to query inside it:

SELECT doc_id,
       CAST(payload_text AS xml).value('(/order/total)[1]', 'decimal(18,2)') AS total
FROM OPENQUERY(LINKEDSRV,
    'SELECT doc_id, CAST(payload AS nvarchar(max)) AS payload_text
     FROM Sales.dbo.Documents');

One caution. CAST to nvarchar loses the XML declaration and can change whitespace. That matters if the document is signed or compared byte for byte.

Pull Out Only What You Want

Often you do not want the document. You want one value inside it. Ask the remote server for that value and nothing else.

SELECT *
FROM OPENQUERY(LINKEDSRV,
    'SELECT doc_id,
            payload.value(''(/order/total)[1]'', ''decimal(18,2)'') AS total,
            payload.value(''(/order/status)[1]'', ''varchar(20)'') AS status
     FROM Sales.dbo.Documents');

Note the doubled single quotes. Everything inside OPENQUERY is a string to the local parser. Every quote in the remote statement has to be escaped. People get this wrong, and the error is confusing because it comes from the remote server.

This version is usually much faster as well. You move a decimal instead of a document.

Push the Work Instead of Pulling It

When you need many rows regularly, stop querying across the link. Have the remote side write what you need into a table on your side, on a schedule.

A linked server query running every few minutes over a large table is slow and fragile anyway. This error is often pointing at a design worth changing.

Finding the Columns Before They Bite

Run this on the remote server so you know where the trouble is:

SELECT SCHEMA_NAME(t.schema_id) AS sch, t.name AS table_name, c.name AS column_name
FROM sys.columns AS c
JOIN sys.tables  AS t ON t.object_id = c.object_id
JOIN sys.types   AS ty ON ty.user_type_id = c.user_type_id
WHERE ty.name = 'xml'
ORDER BY sch, table_name;

Knowing which tables carry XML turns this from a surprise into a thing you plan around.

Msg 9514 is not a limit on XML, it is a limit on what a linked server can carry between two engines.

Published by Pinal Dave on SQLAuthority. More of my work at pinaldave.com.


Discover more from SQL Authority with Pinal Dave

Subscribe to get the latest posts sent to your email.

SQL Error Messages, SQL Scripts, SQL Server, SQL XML
Previous Post
SQL SERVER – Spatial Database Definition and Research Documents
Next Post
SQL SERVER – Fix : Error : An error has occurred while establishing a connect to the server. Solution with Images.

Related Posts

14 Comments. Leave new

  • What are the permissions that are needed to be established on the remote server?

    Is there a workaround using linked server?

    Reply
  • Hi,

    I am archiving data from source table having xml datatype and I am not allowed to create any new objects in the source.
    So I am unable to use the common work around of converting the xml datatype to varchar while inserting data through link server.

    Kindly help me to load xml data from source to target with link server.

    Thanks,
    Akila.

    Reply
  • Hi

    When any single row of the selected set has an xml data column exceeding varchar(max) in size (8000 on our instance), the whole query fails.

    Can you suggest how I can take the first 8000 characters of these problem records – perhaps truncating the xml field prior to casting or casting with truncation?

    Many Thanks
    Brett

    Reply
  • Hi Brett,

    Taking only the first 8,000 characters can lose data and leave invalid XML. varchar(max) itself is not limited to 8,000 characters, so I would first find which conversion or provider is imposing that limit. If the query crosses a linked server, convert the XML to nvarchar(max) on the remote side, or exclude the XML column if you do not need it. I would not truncate the value unless losing the rest is an explicit requirement.

    Regards,
    Pinal Dave

    Reply
  • workaround that worked for me – create view to the XML-containing table on the remote server excluding(if you don’t need it) or converting the XML columns to nvarchar… this will “mask” it to the SQL engine enough to accept distributed query…

    Reply
    • thanks!. the view was a quick an easy solution. when i tried openrowset still had some configuration issues that caused a different error than what started this posting.

      great webiste
      -Paul

      Reply
  • Your website is a bible for SQL beginners. At least for me.

    Thanks a lot
    R

    Reply
  • Hi ,

    I am firing trigger on table which will i have to update one column on another server of table.. but i am getting error… as belows…….

    Xml data type is not supported in distributed queries.

    table which i have to update using trigger have one xml column but i am not updating that column..

    Thanks….

    Reply
  • better solution use import and export option

    Reply
  • Michael Heindel
    March 20, 2013 7:11 pm

    If you don’t need the XML data in your query you can build a view that does not contain the XML column.

    Reply
  • How to insert rows into remote database table that has xml columns.
    I am using like below,

    INSERT INTO [External server].[dbname.[dbo].[table]
    SELECT *
    FROM [dbname].[dbo].[table_Archive]
    where date > getdate()

    I am getting error

    Xml data type is not supported in distributed queries. Remote object ” has xml column(s).

    Thanks

    Reply
  • I have also found that one cannot INSERT from one XML column to another XML column in a different table. The workaround is:

    CAST(CAST(XML_Column AS VarChar(max)) AS XML)

    Thanks for all your very valuable info Pinal; I’m often reading your blog when I get some free time!

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.