How to pass parameter value to a stored procedure rather than text lietral in SQL Server [duplicate]

坚强是说给别人听的谎言 提交于 2020-03-04 23:08:28

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!