【问题标题】:Direct linked server querying VS querying via openquery直接链接服务器查询 VS 通过 openquery 查询
【发布时间】:2017-05-17 08:05:54
【问题描述】:

在 SQL Server Management Studio 中,我创建了一个链接到另一个 SQL Server 的服务器。我创建的链接服务器的名称是“linkedserver”。链接服务器使用 Microsoft OLE DB 提供程序。但是,下面描述的问题也会发生在其他提供商身上。

在远程 SQL 服务器中,模式 [schema] 中有一个数据库 [db] 和一个表 [table]。 [table] 有两列,[column] 和 [column2]。

我在远程 SQL 服务器中有一个 SQL 用户“用户”,它只有 [column] 的读取权限,但没有 [column2] 的读取权限。问题是,当我尝试像下面的示例那样查询数据时,我得到一个错误,我在 [column2] 中没有访问权限,尽管 [column2] 没有出现在查询中。我的解决方法是创建开放查询,但这并不方便。

-- Fetch one column via the linked server - DOES NOT WORK
SELECT TOP 1 [column]
FROM [linkedserver].[db].[schema].[table]

第一个失败查询的错误信息是:

消息 2557,级别 16,状态 7,过程 sp_table_statistics2_rowset,第 105 行
用户 'user' 没有权限为对象 '[db].[schema].[table]' 运行 DBCC SHOW_STATISTICS。

消息 230,级别 14,状态 1,过程 sp_table_statistics2_rowset,第 105 行
对象“表”、数据库“db”、模式“schema”的列“column2”的 SELECT 权限被拒绝。

openquery 的解决方法是:

-- Fetch one column via the linked server through an openquery - WORKS
SELECT *
FROM OpenQuery (linkedserver
'SELECT TOP 1 [column]
 FROM  [db].[schema].[table]')

您知道如何克服这个问题,或者为什么这样做?我的假设是第一个查询尝试获取 [table] 的所有列并在 SQL Manager Studio 中应用过滤器。我是对的吗?我能以某种方式克服这个问题吗?

【问题讨论】:

    标签: sql-server linked-server openquery


    【解决方案1】:

    在链接服务器上执行查询时,会在链接服务器上调用 sp_table_statistics2_rowset。你可以执行

     exec sp_helptext 'sp_table_statistics2_rowset'
    

    查看代码并在光标(第 105 行)中找到以下代码:

    dbcc show_statistics(@qtbl, @statname) with stat_header join density_vector
    

    所以要执行这个sp,你的链接服务器上的用户必须有执行dbcc show_statistics的权限,这对于不同版本的SQL Server是不一样的。在 SQL Server 2012 SP1 之前,要求是“用户必须拥有表或用户必须是 sysadmin 固定服务器角色、db_owner 固定数据库角色或 db_ddladmin 固定数据库角色的成员”,但大多数情况并非如此的情况(当用户不是链接服务器上的 db_owner 时),所以旧的提供者会默默地吃掉这个错误,并且在不使用统计信息的情况下优化了查询。 SQL Server 2012 SP1 更改了行为,所需的权限更改如下:

    SQL Server 2012 SP1 修改了权限限制,允许 具有 SELECT 权限的用户可以使用此命令。请注意, SELECT 权限必须满足以下要求 运行命令: + 用户必须拥有所有列的权限 统计信息对象用户必须对 a 中的所有列具有权限 过滤条件(如果存在) 表不能有行级 安全政策。

    所以我认为您的服务器版本 >= 2012 SP1 并且您的用户没有通过要求,因为他对某些列没有权限。 我无法重现您的问题,因为我有 SQL Server 2008 R2,您的案例运行良好,因此我可以建议您使用旧的数据库提供程序,使用 SQLNCLI10 创建另一个链接服务器并测试问题是否消失。 检查dbcc权限的链接:https://docs.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-show-statistics-transact-sql

    这篇文章说你可以使用 TF9485 关闭这个行为,但我不知道它是否会影响只执行 dbcc 所需的权限,或者它也会影响本机客户端的行为

    【讨论】:

    • 感谢您的回复。我查看属性时的远程服务器版本似乎是“11.0.6567.0”。不幸的是,我无权在创建链接服务器的 SQL 服务器中安装 SQLNCLI10 提供程序。仅安装 SQLNCLI11 提供程序。不过,您的解决方案听起来很有希望,我希望我可以尝试一下。
    • 我试图重现您的错误,该错误与仅对 SQL Server 2012 SP3 上表中的一列具有权限的用户创建相同的情况,从 2014 年开始创建指向它的链接,并从其本身创建(环回)我无法使用来自链接服务器的直接选择或使用 openquery 得到相同的错误,尽管该用户在目标 2012 上对该表运行直接 sp_table_statistics2_rowset 确实会导致错误。所以我想知道服务器的确切版本是否重要,我用谷歌搜索并找到了这个连接项:
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-27
    • 1970-01-01
    • 2012-01-01
    • 1970-01-01
    相关资源
    最近更新 更多