Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 为什么我会得到这个错误;“分布式查询中不支持Xml数据类型”;在查询链接服务器的非xml数据时?_Sql Server_Xml_Linked Server - Fatal编程技术网

Sql server 为什么我会得到这个错误;“分布式查询中不支持Xml数据类型”;在查询链接服务器的非xml数据时?

Sql server 为什么我会得到这个错误;“分布式查询中不支持Xml数据类型”;在查询链接服务器的非xml数据时?,sql-server,xml,linked-server,Sql Server,Xml,Linked Server,我有两台SQL Server(运行SQL Server 2008),分别名为DATA01和DATA02DATA02有一个链接服务器定义LINK,指向DATA01,并设置了适当的用户映射。在DATA01上有一个数据库MyDatabase,包含以下两个表: CREATE TABLE T_A ( Id int ) CREATE TABLE T_B ( Id int, Stuff xml ) 当我从DATA02运行此命令时,我得到了预期返回的数据: SELECT Id FRO

我有两台SQL Server(运行SQL Server 2008),分别名为
DATA01
DATA02
DATA02
有一个链接服务器定义
LINK
,指向
DATA01
,并设置了适当的用户映射。在
DATA01
上有一个数据库
MyDatabase
,包含以下两个表:

CREATE TABLE T_A (
    Id int
)

CREATE TABLE T_B (
    Id int,
    Stuff xml
)
当我从
DATA02
运行此命令时,我得到了预期返回的数据:

SELECT Id FROM LINK.MyDatabase.dbo.T_A;
但是,当我从
DATA02
运行此命令时,我得到一个错误:

SELECT Id, Stuff FROM LINK.MyDatabase.dbo.T_B;
错误是

分布式查询中不支持Xml数据类型。远程对象“DATA02.MyDatabase.dbo.T_B”具有xml列

奇怪的是,这个命令:

SELECT Id FROM LINK.MyDatabase.dbo.T_B;

也给出了相同的错误,即使我没有选择xml列发生了什么事?

这是SQL Server内部的一个缺陷。表上仅存在一个xml列,这就阻止了它参与分布式查询(例如通过链接的服务器连接进行查询)。这当前版本的文档中似乎没有提到这一点

过去,Microsoft Connect上有相关的bug报告,但现在这些报告已经“退役”,取而代之的是Azure反馈论坛。在结束时,会有一条指示“请直接从产品文档中提交反馈”,如果产品文档中确实提到了这一点,就可以了。包括从Connect迁移的评论,状态为“未计划”

以前存在的一个Connect bug报告提供了两种解决方法:

  • 在远程服务器上创建没有XML列的[a]视图并查询该视图

    在您的示例中,这将涉及向
    MyDatabase
    看起来是这样的:

    CREATE VIEW V_T_B AS SELECT Id FROM T_B;
    
    然后,您可以通过链接查询此视图以获取
    Id
    数据。注意

    SELECT Id FROM ( SELECT Id FROM T_B ) T_B;
    
    不起作用

  • 在表单中使用传递查询

    这种方法的优点是不需要对 源数据库;不利的一面是不再可能 对本地数据和链接数据使用标准的四部分命名。这个 这个查询看起来像

     SELECT Id FROM OPENQUERY(DATA02, 'SELECT Id FROM T_B') T_B;
    
    请注意,如果您确实需要xml数据,则此方法(以及 与非xml数据类型之间的转换)将需要:

  • 请注意,该漏洞是在SQL Server 2005中首次报告的,但在SQL Server 2017中仍未修复。我还无法检查SQL Server 2019。

    请尝试以下操作:

    • 在源端创建一个视图,将xml转换为nvarchar(最大):
    创建视图VXML测试 作为 从T_B中选择cast(填充为nvarchar(max))作为填充

    • 您可以使用cast-to-xml在目标端选择它
    选择Cast(Stuff as XML)作为Stuff 从OPENQUERY(DATA02,“从VXML测试中选择素材”)


    这个解决方案在2008年R2对我有效。

    我找到了另一种方法:

  • DATA01
    DATA02
    甚至第三台服务器(可能是本地服务器)上创建一个
    链接服务器
  • 使用
    EXEC[linked\u server].[sp\u sqlexecute]
    执行查询
  • 为什么我更喜欢这种方法而不是创建视图或使用
    OPENQUERY

  • 此方法不需要在链接服务器上拥有任何权限(您不需要创建视图)
  • 您可以使用
    sp\u sqlexecute
    语法()将参数传递给查询。对于
    OPENQUERY
    ,必须传递
    字符串
    文本_LEX
    ,这意味着必须将所有值直接键入此函数
  • 以下是一个例子:

    DECLARE @UserID UNIQUEIDENTIFIER = ''
    
    DECLARE @SearchForUserParams NVARCHAR(MAX) = N'@UserID UNIQUEIDENTIFIER';  
    DECLARE @SearchForUserQuery NVARCHAR(MAX) = 
    N'SELECT
        UserID,
        Username,
        Email,
        CONVERT(NVARCHAR(MAX), UserDataXml) AS UserDataXml
    FROM User
    WHERE UserID = @UserID
    '
    
    EXEC [linked_server].[dbo].[sp_executesql] 
        @SearchForUserQuery,
        @SearchForUserParams,
        @UserID = @UserID
    

    您还可以在DATA02上创建一个存储过程,并远程调用该存储过程,而不是尝试远程运行查询。当我在本地数据库上创建视图时,从远程数据库表的select id得到相同的错误…SQL SERVER 2008 R2here@RMiranda必须在远程数据库上创建视图,然后从本地数据库中,您应该能够通过链接查询该视图。多么简单的解决方案!ThanksJust在SQL 2019中偶然发现了它(作为连接服务器)。也许这只是一个被误解的功能。好主意!非常好。当您需要从生产服务器获取一些数据并且无法创建视图时,这是一个很好的答案。但在您的示例中,您忘记了数据库:[linked_server].[database].dbo.[sp_executesql]…当我尝试此操作时,会出现一个错误:没有为RPC配置服务器“MySVR\MyDB”。配置链接服务器时,您需要在属性窗格中打开RPC和RPC。
     SELECT Id, CAST(Stuff AS XML) Stuff 
     FROM OPENQUERY(DATA02, 'SELECT Id, CAST(Stuff AS nvarchar(max)) Stuff 
                             FROM T_B') T_B;
    
    DECLARE @UserID UNIQUEIDENTIFIER = ''
    
    DECLARE @SearchForUserParams NVARCHAR(MAX) = N'@UserID UNIQUEIDENTIFIER';  
    DECLARE @SearchForUserQuery NVARCHAR(MAX) = 
    N'SELECT
        UserID,
        Username,
        Email,
        CONVERT(NVARCHAR(MAX), UserDataXml) AS UserDataXml
    FROM User
    WHERE UserID = @UserID
    '
    
    EXEC [linked_server].[dbo].[sp_executesql] 
        @SearchForUserQuery,
        @SearchForUserParams,
        @UserID = @UserID