有没有办法让我在存储过程中动态编写脚本以将域+用户添加到 Microsoft SQL 服务器?

Is there a way for me to dynamically write a script to add a domain+user to Microsoft SQL server in a stored procedure?

我必须使用下面这个确切的脚本:

ALTER PROCEDURE [dbo].[sp_CheckIfSQLLoginExistsAndCreateLogin] 
    @SearchDomain NVARCHAR(MAX),
    @SearchUsername NVARCHAR(MAX)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
    
    DECLARE @sql NVARCHAR(max);
    DECLARE @params NVARCHAR(MAX);

    IF @SearchUsername != ''
    BEGIN
        SET @sql = N'IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE [name] =  @Domain\@Username) CREATE LOGIN [@Domain\@Username] FROM WINDOWS';
        SET @params = N'@Username NVARCHAR(MAX), @Domain NVARCHAR(MAX)';
    END
            
    exec sp_executesql @sql, @params, @Username=@SearchUsername, @Domain=@SearchDomain      
END

我遇到的问题是每次调用此 SP 时都会出现以下错误:

使用此数据:@SearchDomain = OFFICE 和@SearchUsername = BJackson

这里的问题是你认为 SQL 是一种脚本语言; 不是。例如 '@Domain' 表示 文字串 '@Domain' 而不是 将文字串 '@Domain' 替换为中的值变量 @Domain.

如果你有 EXEC sys.sp_executesql N'SELECT '@V1 + @V2';', N'@V1 varchar(30), @V2 varchar(30)','This', 'works'; 不会 得到值 'Thisworks' 你得到值 '@V1 + @V2' 为什么?因为它们是文字.

您需要做的是安全地为对象名称注入参数,并正确地参数化您的WHERE

ALTER PROCEDURE [dbo].[CheckIfSQLLoginExistsAndCreateLogin] --removed prefix
    @SearchDomain sysname, --Corrected datatype
    @SearchUsername sysname  --Corrected datatype
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;
    
    DECLARE @sql NVARCHAR(max);
    DECLARE @Login sysname = CONCAT(@SearchDomain,'\',@SearchUsername);

    IF @Login != ''
    BEGIN
        SET @sql = N'IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE [name] = @Login) CREATE LOGIN ' + QUOTENAME(Login) + N' FROM WINDOWS';
    END
            
    EXEC sys.sp_executesql @sql, N'@Login sysname', @Login;
END;

这是一个简单的例子:

CREATE OR ALTER PROCEDURE [dbo].[sp_CheckIfSQLLoginExistsAndCreateLogin] 
    @SearchDomain NVARCHAR(MAX),
    @SearchUsername NVARCHAR(MAX)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
    
    DECLARE @sql NVARCHAR(max);
    DECLARE @params NVARCHAR(MAX);

  IF @SearchUsername != ''
    BEGIN
        SET @sql = N'IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE [name] = '''+ @SearchDomain +'\'+ @SearchUsername +''') CREATE LOGIN [@Domain\@Username] FROM WINDOWS';
        SET @params = N'@Username NVARCHAR(MAX), @Domain NVARCHAR(MAX)';
    END
            
    exec sp_executesql @sql, @params, @Username=@SearchUsername, @Domain=@SearchDomain      
END