2010-02-25 59 views
1

我花了一些代码在这里:Check if role consists of particular user in DB?检查用户属于DB角色

SELECT * 
      FROM sys.database_role_members AS RM 
      JOIN sys.database_principals AS U 
      ON RM.member_principal_id = U.principal_id 
      JOIN sys.database_principals AS R 
      ON RM.role_principal_id = R.principal_id 
      WHERE U.name = 'operator1' 
      AND R.name = 'myrole1' 

该查询返回1行。这意味着用户'operator1'属于角色'myrole1'。 现在我试图创建一个存储过程是:

CREATE PROCEDURE [dbo].[Proc1] 
(
    @userName varchar, 
    @roleName varchar 
) 
AS 

IF EXISTS(SELECT * 
      FROM sys.database_role_members AS RM 
      JOIN sys.database_principals AS U 
      ON RM.member_principal_id = U.principal_id 
      JOIN sys.database_principals AS R 
      ON RM.role_principal_id = R.principal_id 
      WHERE U.name = @userName 
      AND R.name = @roleName) 
      RETURN 0 
ELSE RETURN -1 

我使用标准的命令从SQL Server 2008“执行存储过程”

DECLARE @return_value int 

EXEC @return_value = [dbo].[Proc1] 
     @userName = N'operator1', 
     @roleName = N'myrole1' 

SELECT 'Return Value' = @return_value 

GO 

它总是返回-1。 为什么 ???

回答

2

您需要为每个过程参数定义长度属性。如果你改变你的存储过程声明的开头为以下,它将返回正确的响应:

CREATE PROCEDURE [dbo].[Proc1] 
(
    @userName varchar(255), 
    @roleName varchar(255) 
) 
AS 

没有长度的属性时,SQL Server自动定义的变量为1的长度,这样用户和角色分别与“o”和“m”匹配。 SQL Server在处理变量时没有使用长度说明符的行为是不一致的 - 有时它们的长度为30,有时它们的长度为1.最好的做法是始终在字符串变量上指定长度属性。请参阅下面的SQL博客文章以了解更多信息:

http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/09/bad-habits-to-kick-declaring-varchar-without-length.aspx

+0

感谢您的输入,Templar。 对不起,长时间的答案。我不知道我应该把你的答案标记为有用的和其他的东西...... – 2010-03-29 13:21:47

0

此代码是不好的,因为它可以返回false,如果用户是一组,然后是角色的成员的成员。

用户内置函数IS_MEMBER() - 这是非常简单,总是可以保证。