提问人:Nick Weidemann 提问时间:8/2/2021 最后编辑:Thom ANick Weidemann 更新时间:8/2/2021 访问量:137
有没有办法动态编写脚本以在存储过程中向 Microsoft SQL Server 添加域 + 用户?
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
答:
2赞
Thom A
8/2/2021
#1
这里的问题是你认为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;
评论
1赞
Nick Weidemann
8/2/2021
我完全明白你现在上面的例子的意思!CONCAT函数肯定也有助于堆。我认为我如此困惑的原因是以前的开发人员在代码库中写得非常糟糕,所以当我尝试为它创建一个 SP 时 - 我只是按原样复制它并试图将其全部参数化。谢谢你帮助我学到@Larnu的东西。
-1赞
MohammadAmin Moazami
8/2/2021
#2
下面是一个简单的示例:
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
评论
print @sql
[@Domain]
[@Domain]
@Domain
WHERE [name] = @Domain\@Username
WHERE [name] = '@Domain\@Username'
PRINT