условно создать пользователя в SQL Server - PullRequest
19 голосов
/ 22 апреля 2009

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

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 ]

29 голосов
/ 22 апреля 2009

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

Марк

16 голосов
/ 28 мая 2011

По сути, объединяет ответ Дэвида и ответ marc_s , как было запрошено в комментарии от Криса.

Books Online говорит о sp_grantdbaccess :

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

Интересно, что Books Online также говорит, что sp_grantdbaccess на самом деле вызывает CREATE USER, и я заметил в своем тестировании, что если вы не назначите схему явно, sp_grantdbaccess создаст одну из имен пользователя, а CREATE USER будет использовать 'dbo' по умолчанию.

13 голосов
/ 22 апреля 2009

Это то, что мы делаем ...

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 голос
/ 31 октября 2014
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
0 голосов
/ 11 сентября 2014
USE MyDB
GO

BEGIN TRY
  CREATE USER [foo] FOR LOGIN [foo]
END TRY
BEGIN CATCH
 -- User exists - do nothing
END CATCH
0 голосов
/ 14 января 2013

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

Проверка, существует ли логин SQL Server

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...