2009-04-22 3 views
16

Я хотел бы создать пользователя 'foo' в базе данных 'mydb', если пользователь еще не существует. В настоящее время мой сценарий выглядит следующим образом:условно создать пользователя в SQL Server

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. 

Как я могу изменить сценарий так, что пользователь только создается, если они еще не существует?

Спасибо!

+0

возможно дубликат [Проверка, если Войти SQL Server уже существует] (HTTP: // StackOverflow.com/questions/1379437/check-if-a-sql-server-login-уже существует) – bummi

ответ

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 
+1

для новой разработки на SQL Server 2005 Я бы использовал sys.database_principals вместо sysusers и придерживался CREATE USER вместо sp_grantdbaccess. – Matt

+1

@Matt вы могли бы добавить ответ, который показывает это решение? –

+0

Немного старый, но для этого случая он должен быть 'sys.server_principals', а не' sys.database_principals'. – codenamezero

25

Вы можете проконсультироваться два системных каталогов 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 

Марк

+0

Я бы ожидал, что имя DB (mydb) появится где-то там, я что-то упустил? – 2009-04-22 18:31:27

+1

Вы должны быть на своем дБ, конечно, например. «используйте mydb» перед проверкой –

13

David's answer существу объединение и marc_s's answer по просьбе комментарий от Криса.

Книги Интернет говорит sp_grantdbaccess:

Эта функция будет удалена в будущей версии Microsoft SQL Server. Избегайте использования этой функции в новых разработках и планируйте до изменять приложения, которые в настоящее время используют эту функцию. Вместо этого используйте 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 имеет преимущество в возможности использовать параметр или локальная переменная для имени пользователя/имени пользователя, как в ответе Дэвида. Первой альтернативой, которую я мог бы придумать, чтобы получить что-то похожее на работу с 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» по умолчанию.

0

я точно задал тот же вопрос относительно пользователя SQL уже существующего при выполнении сценария - вопрос, и некоторые очень полезные ответов здесь:

Checking if a SQL Server login already exists

Надеется, что это помогает.

-2
USE MyDB 
GO 

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

Пока единственная потенциальная ошибка заключается в том, что пользователь уже может войти в систему. – Karlth

+1

Downvoted, потому что, если возникает какая-либо другая ошибка, например «Политика паролей» или «Недействительный вход», эти ошибки будут проглатываться с помощью Try/Catch – Raffaeu

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 
Смежные вопросы