GRANT SELECT ON 视图名 TO 用户名必须带架构前缀且用户须已存在于数据库;视图权限不继承基表权限,DENY会覆盖GRANT且不可绕过;验证需以目标用户身份实际执行SELECT。

GRANT SELECT ON 视图名 TO 用户名 语法必须写对
直接用 GRANT SELECT ON 授予单个视图权限是最常用也最稳妥的方式。关键点在于:视图名必须带架构前缀(如 dbo.v_sales_summary),不能省略;用户名是数据库用户(不是登录名),且该用户必须已存在于当前数据库中。
常见错误现象:
- 执行后报错
The server principal "xxx" is not able to access the database "yyy" under the current security context.→ 用户没映射到该数据库,需先用CREATE USER或sp_adduser(旧版)映射 - 报错
Cannot find the object "v_name" because it does not exist or you do not have permission.→ 视图不存在,或当前会话没有查看该视图元数据的权限(SELECT权限本身不自动赋予元数据可见性)
正确写法示例:
USE SalesDB; GO GRANT SELECT ON dbo.v_customer_active TO app_reader;
视图权限不继承表权限,也不影响底层表可见性
授予视图的 SELECT 权限,只允许用户查询该视图结果集,不会自动获得其引用的基表(如 Customers、Orders)的任何权限。这是安全隔离的关键设计。
使用场景:
- 给 BI 工具账号只开放汇总视图,屏蔽明细表字段
- 为外部合作方提供脱敏后的视图,但禁止其直查原始表
- 避免因误操作修改底层表结构或数据
注意:如果视图定义里用了 WITH SCHEMABINDING,那它绑定的基表必须与视图同属一个所有者(比如都是 dbo),否则 GRANT 能成功,但用户执行 SELECT 时可能因所有权链中断而失败。
DENY 会覆盖 GRANT,慎用于视图权限控制
如果你在视图上执行了 DENY SELECT ON dbo.v_sensitive TO app_reader,哪怕之前已 GRANT 过,用户也会被明确拒绝访问——这个拒绝不可绕过,连 db_owner 角色也无法覆盖。
容易踩的坑:
- 误对
public角色执行DENY,导致所有用户都无法查该视图(包括管理员) - 在角色上
GRANT后,又对同一角色下的某个具体用户DENY,结果该用户失效——这虽合法,但排查时容易忽略层级关系 -
DENY不会阻止用户通过其他视图间接获取相同数据(只要那些视图没被DENY)
验证用户是否真能查到视图,别只看权限语句是否执行成功
执行 GRANT 后,用户仍可能查不到数据,原因往往不在权限本身,而在元数据可见性或执行上下文。
检查步骤:
- 用目标用户身份连接,执行
SELECT TOP 1 * FROM dbo.v_target—— 直接测试,比查权限视图更可靠 - 若报错
The SELECT permission was denied on the object 'v_target', database 'X', schema 'dbo'.,说明GRANT没生效或对象名/架构名写错 - 若返回空结果但无报错,可能是视图逻辑过滤掉了该用户可见的数据(比如加了
WHERE tenant_id = CURRENT_USER这类动态条件) - 若提示
Invalid object name,大概率是用户没权限看到该视图元数据(sys.views不返回该行),此时即使权限已授,SSMS 对象资源管理器里也看不到它
真正起作用的永远是“用户能否执行那条 SELECT”,而不是“权限表里有没有那条记录”。










