Условно создать пользователя в SQL Server
Я хотел бы создать пользователя 'foo' в базе данных 'mydb', если пользователь еще не существует. В настоящее время мой script выглядит следующим образом:
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.
Как я могу изменить script так, чтобы пользователь был создан только в том случае, если он еще не существует?
Спасибо!
Ответы
Ответ 1
Вы можете обратиться к двум системным каталогам 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
Марк
Ответ 2
Это то, что мы делаем...
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
По существу, комбинируя ответ Дэвида и ответ marc_s, как того требует комментарий от Криса.
Книги в Интернете говорят о 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 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 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".
Ответ 4
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
Ответ 5
Я задал точно такой же вопрос относительно пользователя SQL, уже существующего при запуске script - вопрос, и некоторые очень полезные ответы здесь:
Проверка наличия учетной записи SQL Server
Надеюсь, что это поможет.
Ответ 6
USE MyDB
GO
BEGIN TRY
CREATE USER [foo] FOR LOGIN [foo]
END TRY
BEGIN CATCH
-- User exists - do nothing
END CATCH