Advice on applying variables as part of a statement utilising a cursor / while loop
-
Thursday, May 17, 2012 2:35 PM
Hello all
Please can someone advise on the following. I have a script to update user permissions, which I've been attempting to make dynamic (so a list of username names can be looped through, to apply db permissions via stored procedure).
I've not had a great deal of exposure to tsql / cursors, but I'm getting several incorrect syntax errors with the following: -
while @@fetch_status = 0 begin
CREATE LOGIN '[lg\' + @UserLogin + ']' FROM WINDOWS WITH DEFAULT_DATABASE = [master]USE uhxx
EXEC sp_grantdbaccess '''lg\' + @UserLogin + '''', '''' + Lower (@UserLogin) + ''''
GO
USE wfxx
GO
EXEC sp_grantdbaccess '''lg\' + @UserLogin + '''', '''' + Lower (@UserLogin) + ''''
GO
ALTER USER Lower (@UserLogin) WITH DEFAULT_SCHEMA = Lower (@UserLogin);
GO
EXEC sp_addrolemember 'synchronization', '''' + Lower (@UserLogin) + ''''
GO
fetch next from UserLogins into @UserLogin
endWould appreciate any advice on this. The errors mainly relate to the concatenations used to accomodate the variables: -
Msg 102, Level 15, State 1, Line 12Incorrect syntax near '[lg\'.
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '+'.
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '+'.
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '('.
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '+'.
Msg 137, Level 15, State 2, Line 3
Must declare the scalar variable "@UserLogin".
Regards
Michael
- Edited by MichaelJamesParker Thursday, May 17, 2012 2:44 PM Typo
- Edited by MichaelJamesParker Thursday, May 17, 2012 3:12 PM
All Replies
-
Thursday, May 17, 2012 3:06 PMModerator
First you need to form the string and then use exec (@str) Sample below
declare @UserLogin varchar(100) set @UserLogin = 'Balmukund' declare @loginStr varchar(100) Set @loginStr = 'CREATE LOGIN ' + '[MyDomain\' + @UserLogin + ']' +' FROM WINDOWS WITH DEFAULT_DATABASE = [master]' exec (@loginStr)
Balmukund Lakhani | Please mark solved if I've answered your question, vote for it as helpful to help other user's find a solution quicker
--------------------------------------------------------------------------------
This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------------------------------------------------------------------
My Blog | Team Blog | @Twitter- Proposed As Answer by Naomi NMicrosoft Community Contributor, Moderator Thursday, May 17, 2012 3:17 PM
- Marked As Answer by Peja TaoModerator Thursday, May 24, 2012 3:31 AM
-
Thursday, May 17, 2012 3:35 PM
Thanks for the prompt response Balmukund. I'm still getting errors regarding the declaration of @StringTest2, which I've created to test the changes you've suggested.
Msg 137, Level 15, State 2, Line 1Must declare the scalar variable "@StringTest2".
I have declared this variable at the beggining of the statement, so unsure why I'm receiving this error.- Edited by MichaelJamesParker Thursday, May 17, 2012 3:35 PM
-
Thursday, May 17, 2012 3:46 PMModeratorYou need to show us the new script if you want help debugging it.
For every expert, there is an equal and opposite expert. - Becker's Law
My blog -
Thursday, May 17, 2012 5:36 PM
Set @loginStr = 'CREATE LOGIN ' + '[MyDomain\' + @UserLogin + ']' +' FROM WINDOWS WITH DEFAULT_DATABASE = [master]'
Permit me to point out that this:
'[MyDomain\' + @UserLogin + ']'
should be:
quotename('MyDomain\' + @UserLogin)
While it is highly unlikely that @UserLogin would include a right bracket, there is no reason to attempt to handle this situation. Not the least if @UserLogin could be populated from a source which has been filled up by a malicous user who is engaging in SQL injection.
Another problem in the original post is that there are a lots of GO in the script. GO is not an SQL command. GO is an instruction to the query tool to cut the script here and send this part to SQL Server.
There are also a number of USE commands, this will mess things up and make things more difficult to understand. Rather use the fact that when you say:
EXEC somedb..sp_systemproc
sp_systemproc will execute in the contect ot that database.
Here is an improvment of the cursor loop:
DECLARE cur FOR ....
OPEN cur
WHILE 1 = 1
BEGIN
FETCH cur INTO @UserLogin
IF @@fetch_status <> 0 BREAKSELECT @domainuser = quotename('MyDomain\' + @UserLogin)
SELECT @lc_UserLogin = quotename(lower(@UserLogin))
SELECT @addlogin = 'CREATE LOGIN ' + @domainuser +
' FROM WINDOWS WITH DEFAULT_DATABASE = [master]'
SELECT @adduser = 'CREATE USER ' + @lc_UserLogin +
'FROM ' + @domainuserEXEC sp_executesql @addlogin
EXEC uhxx..sp_executesql @adduser
EXEC wfxx..sp_executesql @adduserSELECT @sql = 'CREATE SCHEMA ' + @lc_UserLogin
EXEC wfxxx..sp_executesql @sqlSELECT @sql = 'ALTER USER ' + @lc_UserLogin ' +
'WITH DEFAULT_SCHEMA = ' + @lc_UserLogin
EXEC wfxxx..sp_executesql @sqlEXEC wfxx..sp_addrolememeber 'synchronization', @lc_UserLogin
ENDDEALLOCATE cur
Note that the argument to sp_executesql must be nvarchar.
Erland Sommarskog, SQL Server MVP, esquel@sommarskog.se- Marked As Answer by MichaelJamesParker Friday, July 06, 2012 3:23 PM

