776 字
4 分鐘
瀏覽次數
Stop Manually Granting Permissions! Simplify Management with This SQL Role Design
2026-03-26
2026-04-10

Conclusion#

  • Managing SQL Server permissions using a combination of “custom roles + built-in roles” is more stable and easier to maintain than directly GRANTing permissions to users.

Where It’s Suitable#

  • When the number of database users is growing, and permissions are getting out of control.
  • When new hires, vendors, or support staff require different levels of DB permissions.
  • When you want to establish a fixed template for permission management instead of reconfiguring manually every time.
  • When you want to reduce the difficulty of tracking permissions granted directly to users.

Workflow Steps#

1. Define the Role Model First#

  • Don’t rush to grant permissions to individuals. First, define three standard roles: read-only, general developer, and advanced developer (who can modify schema). The key here isn’t to “create many roles,” but to consolidate common requirements into fixed templates. Afterwards, new personnel only need to be added to the corresponding role. In practice, I unify the naming convention to role_db_* so it’s immediately clear these are custom roles and won’t be confused with built-in roles.
IF NOT EXISTS (SELECT 1 FROM sys.database_principals WHERE name = 'role_db_readonly')
CREATE ROLE role_db_readonly;
IF NOT EXISTS (SELECT 1 FROM sys.database_principals WHERE name = 'role_db_developer')
CREATE ROLE role_db_developer;
IF NOT EXISTS (SELECT 1 FROM sys.database_principals WHERE name = 'role_db_schema_developer')
CREATE ROLE role_db_schema_developer;
GO

2. Use Built-in Roles to Assemble Permission Templates#

  • After creating custom roles, assign the capabilities of built-in roles to them. role_db_readonly grants query and view definition permissions, suitable for reporting or query personnel. role_db_developer adds write capabilities and the ability to execute SPs, suitable for general backend engineers. The advantage of this approach is clear layering, visible permission differences, and avoiding unique, custom permissions for everyone.
ALTER ROLE db_datareader ADD MEMBER role_db_readonly;
GRANT VIEW DEFINITION TO role_db_readonly;
GO
ALTER ROLE db_datareader ADD MEMBER role_db_developer;
ALTER ROLE db_datawriter ADD MEMBER role_db_developer;
GRANT EXECUTE ON SCHEMA::dbo TO role_db_developer;
GRANT VIEW DEFINITION TO role_db_developer;
GO

3. Reserve Advanced Roles for Those Who Truly Need Them#

  • role_db_schema_developer can be further enhanced with db_ddladmin, giving the role DDL capabilities like CREATE / ALTER / DROP. While these permissions are convenient, they can also easily lead to accidental issues. Therefore, do not grant them indiscriminately just because it’s “easier.” It’s generally recommended only for Tech Leads, DBAs, or individuals who genuinely need to adjust object structures.
ALTER ROLE db_datareader ADD MEMBER role_db_schema_developer;
ALTER ROLE db_datawriter ADD MEMBER role_db_schema_developer;
ALTER ROLE db_ddladmin ADD MEMBER role_db_schema_developer;
GRANT EXECUTE ON SCHEMA::dbo TO role_db_schema_developer;
GRANT VIEW DEFINITION TO role_db_schema_developer;
GO

4. Finally, Manage Roles, Not Individuals Directly#

  • Once the permission model is established, users only need to be added to the appropriate role. The key principle is simple: do not grant permissions directly to users. If you directly GRANT SELECT TO user1 today, it will be difficult to understand why this person has that permission tomorrow. However, if they are added to role_db_readonly, the entire source of the permission becomes clear. Permission management is essentially about convergence, not divergence. This isn’t just a profound statement; it can genuinely save you trouble =_=
-- 將使用者加入對應角色
-- ALTER ROLE role_db_readonly ADD MEMBER [user1];
-- ALTER ROLE role_db_developer ADD MEMBER [user2];
-- ALTER ROLE role_db_schema_developer ADD MEMBER [user3];
GO
-- 不建議:直接對使用者給權限
GRANT SELECT TO user1;
-- 建議:把使用者加進角色
ALTER ROLE role_db_readonly ADD MEMBER user1;

Commands / Examples Summary#

Role and Permission Mapping Table#

Role NamePermissionsApplicable To
role_db_readonlyQuery, View DefinitionReports, Queries, Support
role_db_developerQuery, Write, Execute, View DefinitionBackend Engineers, API Development
role_db_schema_developerQuery, Write, Execute, DDL, View DefinitionTech Lead, DBA

SQL Agent Additional Permissions#

  • Many people assume that granting database permissions allows them to view SQL Agent Jobs, only to find a blank screen and start questioning everything. This isn’t SQL Server being broken; it’s because SQL Agent permissions are in msdb and need to be granted separately.
Requirementmsdb Role
View only own JobsSQLAgentUserRole
View all Jobs / HistorySQLAgentReaderRole
View and operate all JobsSQLAgentOperatorRole
USE msdb;
GO
ALTER ROLE SQLAgentUserRole ADD MEMBER [YourLogin];
GO
USE msdb;
GO
ALTER ROLE SQLAgentReaderRole ADD MEMBER [YourLogin];
GO
USE msdb;
GO
ALTER ROLE SQLAgentOperatorRole ADD MEMBER [YourLogin];
GO

Additional Notes#

  • GRANT EXECUTE ON SCHEMA::dbo only covers the dbo schema; if your SPs are not in dbo, you need to grant additional permissions.
  • db_ddladmin is powerful but not equivalent to a full DBA; it focuses on object structure adjustments and does not include all administrative permissions.
  • If your system already has a large number of direct user grants, it’s recommended to inventory them first and then gradually consolidate, rather than making a hard cut all at once, which could easily cause issues.

Wrap-up#

  • By turning permissions into role templates, you’ll be maintaining a set of rules instead of a multitude of individuals. When the rules are stable, the system won’t act up every day.
Stop Manually Granting Permissions! Simplify Management with This SQL Role Design
https://joyceowo.github.io/posts/en/32fa78ea09fa800285daf3ee84dd0fc4/
作者
JoyceOwO
發佈於
2026-03-26
許可協議
CC BY-NC-SA 4.0