应分数据库使用对应方法:mysql用show grants;postgresql需多表拼接;oracle须关联四张dba视图;sql server需覆盖三层权限并查角色成员;所有场景均需注意deny覆盖、grant option状态及权限继承链。
怎么查某个用户被显式授予的 sql 权限语句
mysql 和 postgresql 不会直接保存“授权时用的原始 sql”,但可以通过系统表反推等效语句。重点不是还原一模一样的命令,而是拿到可执行、可审计、可复现的 grant 语句。
- MySQL 用
information_schema.role_table_grants或mysql.tables_priv等表组合查询,但更稳的是用SHOW GRANTS FOR 'user'@'host'—— 它返回的就是当前生效权限对应的授权语句(含角色继承) - PostgreSQL 必须拼接:查
pg_roles确认用户存在,再连查pg_role_use(角色成员)、pg_class/pg_namespace(对象级权限),最后用pg_get_userbyid()和has_table_privilege()辅助验证 - 注意
SHOW GRANTS在 MySQL 中不显示通过角色间接获得的权限(除非启用 roles),而information_schema.role_table_grants只在 8.0+ 且启用 roles 时才有效
Oracle 中如何从 DBA_TAB_PRIVS 反推出 GRANT 语句
Oracle 的 DBA_TAB_PRIVS 记录了对象级授权,但缺了 WITH GRANT OPTION 和 GRANTOR 是否是当前用户这两个关键信息,直接照抄会出错。
- 必须关联
DBA_SYS_PRIVS(系统权限)、DBA_ROLE_PRIVS(角色授权)、DBA_COL_PRIVS(列级权限)三张表,才能覆盖全权限维度 -
GRANTEE是用户名或角色名,如果值为角色,说明这是角色授权,需额外查该角色被谁授予、是否带ADMIN OPTION - 生成语句时,
SELECT权限在视图上可能实际来自底层基表,DBA_TAB_PRIVS不体现这种依赖,得靠ALL_DEPENDENCIES补充判断
SQL Server 用 sys.database_permissions 怎么避免漏掉映射权限
SQL Server 的权限模型分三层:服务器级 → 数据库级 → 对象级,sys.database_permissions 只管数据库内,容易忽略 sys.server_permissions 和登录映射(sys.server_principals)。
- 先查
sys.database_principals确认用户是否为SQL_USER或WINDOWS_USER,再查其default_schema—— 某些权限(如EXECUTE)默认作用于该 schema 下对象 -
sys.database_permissions中class_desc = 'DATABASE'表示数据库级权限(如CREATE TABLE),不能和对象级权限混为一谈;class_desc = 'OBJECT_OR_COLUMN'才对应具体表/视图 - 如果用户属于
db_owner角色,sys.database_permissions里可能查不到任何显式记录 —— 因为角色权限不落表,必须查sys.database_role_members
为什么直接 SELECT * FROM 权限表经常查不准
权限不是静态快照,而是运行时计算结果。系统表只存“显式授予”,不存“隐式继承”或“拒绝(DENY)覆盖”。一个用户看似有某权限,可能因某处 DENY 而实际失效。
- MySQL 的
SHOW GRANTS已做合并计算,但 PostgreSQL 的pg_has_role()和has_database_privilege()才是运行时真实判断依据 - Oracle 中
DBA_TAB_PRIVS不包含REVOKE记录,也不体现GRANT OPTION是否被后续REVOKE GRANT OPTION撤销,得比对DBA_ROLE_PRIVS的admin_option字段 - 所有数据库中,
WITH GRANT OPTION和WITH ADMIN OPTION是两个不同层级的开关,混用会导致生成的语句无法复现原授权意图
权限链越长(用户→角色→角色→系统权限),反推语句越容易丢环节。别信单表查询结果,一定要按权限作用域分层验证。










