I have a stored procedure that finds all the existing databases and reads from a table in each one.
Is there a way I can give a login read access to all databases, and to all future databases i.e., I won't have to do anything when a new database is added?
Is there a server role that would work? Is there a way to make a SQL agent job add the permissions on any new databases? Or is there some other method?
For new databases, add the user in the model database. This is used as the template for all new databases.
USE model
CREATE USER ... FROM LOGIN...
EXEC sp_addrolemember 'db_datareader', '...'
For existing databases, use sp_MSForEachDb
EXEC sp_MSForEachDb '
USE ?
CREATE USER ... FROM LOGIN...
EXEC sp_addrolemember ''db_datareader'', ''...''
'
USE [master]
GO
--IF Not EXISTS (SELECT * FROM syslogins where loginname = 'replace with Login name ')
--CREATE LOGIN [replace with Login name ] FROM WINDOWS WITH DEFAULT_DATABASE=[master]
--GO
DECLARE @SQL VARCHAR(MAX)
DECLARE @DatabaseName VARCHAR(255)
DECLARE crFetch CURSOR FOR
--SELECT NAME FROM SYSDATABASES WHERE name in
--('master','model','tempdb','msdb','distribution')
SELECT NAME FROM SYS.DATABASES WHERE name not in
('master','model','tempdb','msdb','distribution')
OPEN crFetch
FETCH NEXT FROM crFetch INTO @DatabaseName
WHILE @@FETCH_STATUS <> -1
BEGIN
SET @SQL =
'USE [' + @DatabaseName + ']' +
'if not exists (select name from sysusers where name='+ ''''+ 'replace with Login name '+ ''''+ ')' +
'CREATE USER [replace with Login name ] FOR LOGIN [replace with Login name ]' +
'EXEC sp_addrolemember N' + '''' + 'db_ETL' + '''' + ', N' + '''' + 'replace with Login name ' + '''' +'
'
--'EXEC sp_addrolemember N' + '''' + 'db_datareader' + '''' + ', N' + '''' + 'replace with Login name ' + '''' +
--'if not exists(select name from sysusers where name='+ ''''+ 'db_executor'+''''+ 'and issqlrole=1)' +
--'create ROLE db_executor' + ' ' +
--'GRANT EXECUTE TO db_executor' + ' ' +
--'EXEC sp_addrolemember N' + '''' + 'db_executor' + '''' + ', N' + '''' + 'replace with Login name ' + '''' +'
--PRINT @SQL
EXEC(@SQL)
FETCH NEXT FROM crFetch INTO @DatabaseName
END
CLOSE crFetch
DEALLOCATE crFetch