sql - 为什么 COUNT(*) 需要对 SQL Server 上的所有表列具有 SELECT 权限?
问题描述
我最近遇到了COUNT(*)
要求用户对表的每一列都具有选择权限的问题。即使'COUNT(*)' 的规范明确指出
它不使用任何特定列的信息。
它只返回结果中的行数。
因此,如果您想将表中的行数计算为受限用户,您将获得权限异常。
这是一个例子:
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;
当然,您需要对 Product.name 的 SELECT 权限,但我从您的评论中收集到这应该不是问题。
附录,因为我同意这是出乎意料的行为。如果您执行以下操作,您还可以执行计数(如果您有索引name
以及 SELECT 权限name
):
SELECT COUNT(1)
FROM dbo.Product AS P
WHERE P.name = P.name
OR P.name IS NULL
从想要他们不允许的东西的用户的角度来看,前面的工作很好(在这种情况下是实习生)。从 DBA 的角度来看,存在一种更好的方法来方便该用户。(从上面 Jeroen Mostert 的评论中复制:)
您可以创建一个明确排除实习生不应该看到的列的视图,并授予 SELECT 权限。这样,查询就可以正常工作,而不必引入迂回和不直观的变通办法,并且您也不需要每列单独的 DENY 权限——您不必首先授予对基表的 SELECT 权限。
推荐阅读
- java - 在单独的线程中初始化 Ktor 可以吗?
- reactjs - 如何使用 React Hooks 在 React 中编写通用 Stomp 客户端?
- matlab - 计算平均值是否比计算总和对数字消除更稳健?
- java - 如何用字符串替换下划线?
- python - python pubsub订阅到期
- javascript - 未捕获的类型错误:无法读取未定义的属性“说话”?
- python - 我可以使用 matplotlib 和 pandas 为每个 x 刻度设置默认值吗?
- dafny - 向方法添加修改会破坏循环不变量
- python - 图像处理:concaveHull 查找图像的缺陷
- vba - Powerpoint - 在组内的文本框中找到指定的单词并添加评论