问题
Taking the next step from the recent post (below)
- How to grant access to multiple schemas in one go in SQL Server
I created this stored procedure:
ALTER PROCEDURE dbo.CreateUser
@loginName nvarchar(100),
@userName nvarchar(100) ,
@schemaName nvarchar(10)
AS
SET NOCOUNT ON;
IF NOT EXISTS (SELECT [name] FROM [sys].[database_principals]
WHERE [TYPE] = N'S' AND [name] = @loginName)
BEGIN
CREATE LOGIN [@loginName] WITH PASSWORD = N'123', DEFAULT_DATABASE = [test],
CHECK_EXPIRATION = OFF, CHECK_POLICY = OFF
CREATE USER [@userName] FOR login [@loginName]
GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA :: [dbo] TO [@userName]
GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA :: [@schemaName] TO [@userName]
END
I'm calling this stored procedure like this:
DECLARE @return_value int
EXEC @return_value = [dbo].[CreateUser]
@loginName = N'testlogin1',
@userName = N'testUserLogin1',
@schemaName = N'itl'
SELECT 'Return Value' = @return_value
However, this throws an error:
Upon debugging I see that its not taking the value of the parameters rather the literal.
How do I pass parameter value here to use the values accordingly to create login, user & access?
Thanks!
回答1:
The problem here is you're trying to use a variable to replace literal. That isn't how SQL works (it's not a Scripting Language). For example, take the statement below:
CREATE USER [@userName] FOR login [@loginName]
This will create a USER
called @userName
which is linked to the LOGIN
called @loginName
, not a USER
with a name of the value of @userName
for the LOGIN
with the name of the value of @loginName
.
For things like this, you need to use dynamic SQL and safely inject your parameters.
ALTER PROCEDURE dbo.CreateUser @loginName sysname, --Changed data type throughout to correct one for objects
@userName sysname,
@schemaName sysname
AS
BEGIN
SET NOCOUNT ON;
IF NOT EXISTS (SELECT [name]
FROM [sys].[database_principals]
WHERE [type] = N'S'
AND [name] = @loginName)
BEGIN
DECLARE @SQL nvarchar(MAX),
@CRLF nchar(2) = NCHAR(13) + NCHAR(10);
SET @SQL = N'CREATE LOGIN ' + QUOTENAME(@loginName) + @CRLF +
N' WITH PASSWORD = N''123'',' + @CRLF + --I HIGHLY recommend a better password choice...
N' DEFAULT_DATABASE = [test],' + @CRLF +
N' CHECK_EXPIRATION = OFF,' + @CRLF +
N' CHECK_POLICY = OFF;' + @CRLF +
N'CREATE USER ' + QUOTENAME(@userName) + N' FOR LOGIN ' + QUOTENAME(@loginName) + N';' + @CRLF +
N'GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA::[dbo] TO ' + QUOTENAME(@userName) + N';' + @CRLF +
N'GRANT SELECT,' + @CRLF +
N' INSERT,' + @CRLF +
N' UPDATE,' + @CRLF +
N' DELETE' + @CRLF +
N' ON SCHEMA::' + QUOTENAME(@schemaName) + @CRLF +
N' TO ' + QUOTENAME(@userName) + N';';
--PRINT @SQL; --Your debugging friend
EXEC sys.sp_executesql @SQL;
END;
END;
来源:https://stackoverflow.com/questions/60336362/how-to-pass-parameter-value-to-a-stored-procedure-rather-than-text-lietral-in-sq