为什么 COUNT(*) 需要对 SQL 服务器上所有 table 列的 SELECT 权限?

Why does COUNT(*) require SELECT permission on all table columns on SQL Server?

我最近遇到了 COUNT(*) 要求用户对 table 的每一列都具有 select 权限的问题。 尽管 spec of 'COUNT(*)' 明确表示

it does not use information about any particular column.

它只是 returns 结果中的行数。

因此,如果您想作为受限用户计算 table 中的行数,您将获得权限异常。

这是一个例子:

CREATE TABLE [Product]
([name] nvarchar(100) null, [price] float)

CREATE USER Intern WITHOUT LOGIN;
DENY SELECT ON [Product] (price) TO Intern;

EXECUTE AS Intern;

-- Fails with "The SELECT permission was denied on the column 'price' of the object 'Product'"
SELECT COUNT(*) FROM [Product];

REVERT;

经过一些测试,我发现即使 SELECT COUNT(1) FROM [Product] 无效。

谁能解释一下这种行为背后的原因是什么? 什么是允许 Intern 用户仍然获得 Product.

的准确计数的解决方法

更新: 我最感兴趣的是实习生可以使用的解决方法。因此,即使创建视图对于管理员来说是最佳实践,实习生也没有此选项。

我不知道这种行为背后的原因,但有办法解决它:

SELECT  COUNT(1)
FROM    (
            SELECT  P.name
            FROM    dbo.Product AS P
        ) AS t;

当然,您需要 SELECT 对 Product.name 的许可,但我从您的评论中了解到这应该不是问题。

附录,因为我同意这是意外行为。如果您执行以下操作,您还可以执行计数(如果您在name上有一个索引以及在[=12=上有SELECT权限]):

SELECT  COUNT(1)
FROM    dbo.Product AS P
WHERE   P.name = P.name
    OR  P.name IS NULL 

从想要他们不允许的东西的用户(实习生,在这种情况下)的角度来看,前面的工作很好。从 DBA 的角度来看,存在一种更好的方法来方便该用户。 (从上面 Jeroen Mostert 的评论中复制:)

You can create a view that explicitly excludes columns Intern should not see, and grant SELECT permission on that. This way, queries work as normal without having to introduce circuitous and unintuitive workarounds and you do not need separate DENY permissions per column either -- you don't have to grant SELECT permission on the base table in the first place.