Problem
Consider a situation when you have a large number of databases on your SQL Server, and you are requested to grant user access to all SQL Server databases. How can you grant access to a user for all databases on a SQL Server instance?
Solution
You have a few different options, in SQL Server Management Studio, you can tick each checkbox for all databases from the user mapping interface in the login properties to grant the access. This can take a long time to finish due to the large number of databases. The solution that I prefer, is to create a script that loops through all the databases and grants the user the requested access to each database. In this example, I will use a SQL Server Cursor which is a database object that is used to manipulate data on a row-by-row basis, instead of the typical T-SQL command that operates on all the rows at one time. In this example, I use a simple cursor with the LOCAL and FAST_FORWARD options to optimize its performance. Here is a brief explanation of these options:
- LOCAL – Specifies that the cursor can be available only in the batch in which the cursor was created, and will be de-allocated once the batch terminates.
- FAST_FORWARD – Specifies that the cursor produces the least amount of overhead on SQL Server by choosing the lowest cost static or dynamic plan.
SQL Server CREATE LOGIN Example
Let’s begin with creating a SQL Server login using the T-SQL code below:
USE [master] GO CREATE LOGIN [TipsDemoUser] WITH PASSWORD=N'Tips_DemoUser@123', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=ON GO
Grant User Access to All SQL Server Databases
Based on the code above that we need to generate, let’s exaplain the cursor code:
- Step 1 – Get a list of all user databases on our SQL Server instance, excluding the system databases (master, model, msdb, tempdb and distribution) from the sysdatabases table.
- Step 2 – Once the databases list is ready, loop through these database to create a user for that login and grant it read and write access on each database.
- Step 3 – Execute the string that was generated to create the user and grant permissions
Use master
GO
DECLARE @dbname VARCHAR(50)
DECLARE @statement NVARCHAR(max)
DECLARE db_cursor CURSOR
LOCAL FAST_FORWARD
FOR
SELECT name
FROM MASTER.dbo.sysdatabases
WHERE name NOT IN ('master','model','msdb','tempdb','distribution')
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @dbname
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @statement = 'use '+@dbname +';'+ 'CREATE USER [TipsDemoUser]
FOR LOGIN [TipsDemoUser]; EXEC sp_addrolemember N''db_datareader'',
[TipsDemoUser];EXEC sp_addrolemember N''db_datawriter'', [TipsDemoUser]'
exec sp_executesql @statement
FETCH NEXT FROM db_cursor INTO @dbname
END
CLOSE db_cursor
DEALLOCATE db_cursor
After executing the above script successfully, you can check the granted access from the Login Properties dialog box in SQL Server Management Studio below by expanding the Server Security and Logins nodes:
Next Steps
- Check out the Cursor options.
- Review the SQL Server Security Tips.

Ahmad has a Bachelor’s Degree in Computer Engineering from the University of Jordan and five years of experience working as a SQL DBA, gaining valuable knowledge of database structures, practices, principles and theories. His experience also includes.NET development, working with database applications, scripting and creating SQL queries and views. His personal abilities include having very strong communication and interpersonal skills, the ability to prioritize and to make good sound decisions that benefit the company. He has experience in upgrading, configuring, securing, tuning and monitoring SQL Servers since SQL Server 2005. This includes SQL Server performance tuning, SQL Server resource governor management, SQL Server maintenance plans, SQL Server data collection (Reports) analyzing and SQL databases design, developing, indexing and query optimization. In addition, he is familiar with installing and configuring SSRS, SSIS and SSAS. When it comes to disaster recovery and high availability, he has a solid foundation in SQL backup and recovery scenarios, mirroring, replication, log shipping, SQL clustering and AlwaysOn technology.
- MSSQLTips Awards: Author Contender – 2016-2017 | Trendsetter (25+ tips) – 2016 | Rookie Contender – 2015



Guys, just use this script. You can enter the user you want to add using the @UserName parm, and also use the config parms to choose if you want DataReader and Writer. It defaults to printing the results so you can script it. Also it checks if the user already exists in the database and adds it dynamically if needed.
Use master
GO
–CONFIG
DECLARE @UserName VARCHAR(50) = ‘UserName’
DECLARE @PrintOnly bit = 1
DECLARE @Add_DataReader bit = 1
DECLARE @Add_DataWriter bit = 1
——————————————-
DECLARE @dbname VARCHAR(50)
DECLARE @statement NVARCHAR(max)
DECLARE @ParmDefinition NVARCHAR(500);
DECLARE @UserExists bit
DECLARE db_cursor CURSOR
LOCAL FAST_FORWARD
FOR
SELECT name
FROM MASTER.dbo.sysdatabases
WHERE name NOT IN (‘master’,’model’,’msdb’,’tempdb’,’distribution’)
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @dbname
WHILE @@FETCH_STATUS = 0
BEGIN
–Check if user already exists in the database
SET @statement = N’USE ‘ + QUOTENAME(@dbname) + N’;
IF EXISTS (SELECT [name]
FROM [sys].[database_principals]
WHERE [name] = ”’ + @UserName + ”’)
set @UserExistsOUT = 1
else
set @UserExistsOUT = 0′
SET @ParmDefinition = N’@UserExistsOUT bit OUTPUT’;
EXEC sp_executesql @statement, @ParmDefinition, @UserExistsOUT = @UserExists OUTPUT
—-Start Creating Script
SET @statement = ‘use ‘+ @dbname +’;’
–If user doesn’t exist then add CREATE statement
IF @UserExists = 0
BEGIN
SET @statement = @statement + char(10) + ‘CREATE USER [‘+ @UserName +’ FOR LOGIN ‘+ @UserName +’];’
END
IF @Add_DataReader = 1
SET @statement = @statement + char(10) + ‘EXEC sp_addrolemember N”db_datareader”, [‘+ @UserName +’];’
IF @Add_DataWriter = 1
SET @statement = @statement + char(10) + ‘EXEC sp_addrolemember N”db_datawriter”, [‘+ @UserName +’];’
IF @PrintOnly = 1
PRINT @statement
ELSE
exec sp_executesql @statement
FETCH NEXT FROM db_cursor INTO @dbname
END
CLOSE db_cursor
DEALLOCATE db_cursor