我需要使用WITH EXECUTE AS CALLER
与不同用户执行存储过程(first_procedure)。为了做到这一点,我创建了一个包含有效用户名的表,我尝试使用EXECUTE AS USER
语句执行第二个调用第一个过程的过程。
我的第二个程序如下:
BEGIN
SET NOCOUNT ON;
DECLARE @LOGIN nvarchar(MAX);
DECLARE cur CURSOR LOCAL for
SELECT USERNAME FROM [dbo].[SIM_TABLE] WHERE USERNAME LIKE 'DIJON%';
OPEN cur
FETCH NEXT FROM cur INTO @LOGIN;
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @LOGIN;
EXECUTE AS USER = @LOGIN;
EXEC dbo.first_procedure;
REVERT;
FETCH NEXT FROM cur INTO @LOGIN;
END;
CLOSE cur
DEALLOCATE cur
END
我面临的问题是,我真的不知道如何在@LOGIN
之后格式化EXECUTE AS USER =
部分才能生效。当我影响到@LOGIN
的字符串时,它会起作用,但是从光标开始它就不会出现。是否需要进行一些转型?
答案 0 :(得分:1)
如果你在这里查看EXECUTE AS
文档的这一部分 - https://msdn.microsoft.com/en-GB/library/ms181362.aspx#_user - 你会看到它说:
EXECUTE AS中指定的用户名或登录名必须作为sys.database_principals或sys.server_principals中的主体存在
这意味着(以及实际上是一个主体 - 即登录)它必须格式化相同。
因此,对于只有username
的SQL登录,以及DomainName\username
的Windows登录。
您可以按如下方式获取数据库主体列表:
SELECT name FROM sys.database_principals
<强>更新强>
事实证明,EXECUTE AS
语句反对的是@LOGIN变量的nvarchar(MAX)数据类型。它不是nvarchar本身的问题,它是(MAX)。这并不奇怪,因为(MAX)数据类型与固定大小版本的工作方式非常不同。
让我们尝试几个例子:
DECLARE @LOGIN nvarchar(MAX)
SET @LOGIN = N'MyUser'
EXECUTE AS LOGIN = @LOGIN
Msg 15533,Level 16,State 2,Line 3
“执行为”中提供了无效的数据类型。言。
使用nvarchar(256):
DECLARE @LOGIN nvarchar(256)
SET @LOGIN = N'MyUser'
EXECUTE AS LOGIN = @LOGIN
命令已成功完成。
实际上,我建议使用sysname
类型,因为这是SQL Server内部用于对象名称的类型 - 尽管在SQL 2008中这只是用于非可空nvarchar(256)的用户定义类型R2起码至少。
答案 1 :(得分:0)
我改变了我的答案,因为下面的评论(在下一个答案中)说表中的用户名是当前的SQL登录名。在这种情况下,您可能应该使用&#34; EXECUTE AS LOGIN&#34;而不是使用&#34; EXECUTE AS USER&#34;。您也可能想要摆脱光标:
BEGIN
SET NOCOUNT ON
DECLARE @LOGIN nvarchar(MAX)
SET @LOGIN = ''
WHILE 1 = 1 BEGIN
SELECT TOP 1 @LOGIN = USERNAME
FROM [dbo].[SIM_TABLE]
WHERE USERNAME LIKE 'DIJON%' AND USERNAME > @LOGIN
ORDER BY USERNAME ASC
IF @@ROWCOUNT = 0 BREAK
EXECUTE AS LOGIN = @LOGIN
EXEC dbo.first_procedure
REVERT
END
END
答案 2 :(得分:0)
经过更多调查,解决方案是施放@LOGIN ......
EXECUTE AS USER = CAST(@LOGIN AS VARCHAR);
我不确定为什么NVARCHAR
在这种情况下不起作用,但在VARCHAR
中进行投射可以完成工作。