有条件地在SQL Server中创建用户

时间:2009-04-22 18:18:44

标签: sql-server sql-server-2005

如果用户尚不存在,我想在数据库'mydb'中创建用户'foo'。目前我的脚本如下所示:

USE [mydb]
CREATE USER [foo] FOR LOGIN [foo]
GO

但是,如果用户已存在,则会失败并显示错误消息:

Msg 15023, Level 16, State 1, Line 2
User, group, or role 'jsrvpp' already exists in the current database.

如何更改脚本以便仅在用户不存在时才创建用户?

谢谢!

6 个答案:

答案 0 :(得分:29)

您可以查阅两个系统目录sys.server_principals,以检查特定数据库中的服务器登录名或sys.database_principals,以供数据库用户使用:

use myDB
GO

if not exists(select * from sys.database_principals where name = 'foo')
  -- create your database user


if not exists(select * from sys.server_principals where name = 'foo')
   -- you need to create a server login first

马克

答案 1 :(得分:16)

根据Chris的评论要求,基本上将David's answermarc_s's answer结合起来。

联机丛书说sp_grantdbaccess

  

此功能将在a中删除   Microsoft SQL的未来版本   服务器。避免使用此功能   新的发展工作,并计划   修改当前使用的应用程序   此功能。请改用CREATE USER。

因此,如果仅在用户尚不存在的情况下创建用户,我会执行以下操作:

/* Make sure User is created in the appropriate database. */
USE mydb
GO

/* Users are typically mapped to logins, as OP's question implies, 
so make sure an appropriate login exists. */
IF NOT EXISTS(SELECT principal_id FROM sys.server_principals WHERE name = 'foo') BEGIN
    /* Syntax for SQL server login.  See BOL for domain logins, etc. */
    CREATE LOGIN foo 
    WITH PASSWORD = 'sufficiently complex password'
END

/* Create the user for the specified login. */
IF NOT EXISTS(SELECT principal_id FROM sys.database_principals WHERE name = 'foo') BEGIN
    CREATE USER foo FOR LOGIN foo
END

尽管被弃用,但sp_grantdbaccess确实具有能够为用户/登录名使用参数或局部变量的优势,如David的回答。我能想到的第一个替代方法是使用CREATE USER来使用动态SQL。例如:

/* Make sure User is created in the appropriate database. */
USE mydb
GO

DECLARE @NewUserName sysname;
DECLARE @NewUsersLogin sysname;

SET @NewUserName = 'foo';
SET @NewUsersLogin = 'bar';

/* Users are typically mapped to logins, as OP's question implies, 
so make sure an appropriate login exists. */
IF NOT EXISTS(SELECT principal_id FROM sys.server_principals WHERE name = @NewUsersLogin) BEGIN
    /* Syntax for SQL server login.  See BOL for domain logins, etc. */
    DECLARE @LoginSQL as varchar(500);
    SET @LoginSQL = 'CREATE LOGIN '+ @NewUsersLogin + 
        ' WITH PASSWORD = ''sufficiently complex password''';
    EXEC (@LoginSQL);
END

/* Create the user for the specified login. */
IF NOT EXISTS(SELECT principal_id FROM sys.database_principals WHERE name = @NewUserName) BEGIN
    DECLARE @UserSQL as varchar(500);
    SET @UserSQL = 'CREATE USER ' + @NewUserName + ' FOR LOGIN ' + @NewUsersLogin;
    EXEC (@UserSQL);
END

有趣的是,联机丛书还说sp_grantdbaccess实际上调用了CREATE USER,我在测试中注意到如果你没有明确地指定一个模式,sp_grantdbaccess将创建一个名为在用户之后,CREATE USER默认使用'dbo'。

答案 2 :(得分:13)

这就是我们所做的......

IF NOT EXISTS (SELECT * FROM DBO.SYSUSERS WHERE NAME = @usrName )
BEGIN
  PRINT 'Granting access to the current database to login ' + @usrName + '...'
  -- Grant access to our database
  EXEC SP_GRANTDBACCESS @usrName
END ELSE BEGIN  
  PRINT 'Login ' + @usrName + ' already granted access to current database.'  
END  

答案 3 :(得分:1)

USE [*Database_Name*];
GO

DECLARE @isUserExist int, @SQL NVARCHAR(max)
SELECT @isUserExist = COUNT(*) from sys.sysusers where name = *User_Name* 
--Checking for User Existence 
IF(@isUserExist = 0) 
BEGIN 
    SET @SQL = 'CREATE USER ' + QUOTENAME(*User_Name*) + ' FOR LOGIN ' + QUOTENAME(*User_Name*); 
    EXECUTE(@SQL); 
END

答案 4 :(得分:0)

关于脚本运行时已经存在的SQL用户,我问了完全相同的问题 - 问题和一些非常有用的答案在这里:

Checking if a SQL Server login already exists

希望这有帮助。

答案 5 :(得分:-2)

USE MyDB
GO

BEGIN TRY
  CREATE USER [foo] FOR LOGIN [foo]
END TRY
BEGIN CATCH
 -- User exists - do nothing
END CATCH