2009-04-22 24 views
16

Me gustaría crear un usuario 'foo' en la base de datos 'mydb' si el usuario aún no existe. Actualmente mi guión es el siguiente:crear condicionalmente usuario en SQL Server

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

Sin embargo, si el usuario ya existe, esta falla con un mensaje de error:

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

¿Cómo puedo cambiar la secuencia de comandos para que el usuario sólo se crea si no existe ya?

Gracias!

+0

posible duplicado de [Comprobación de si un inicio de sesión de SQL Server ya existe] (http: // stackoverflow.com/questions/1379437/checking-if-a-sql-server-login-already-exists) – bummi

Respuesta

13

Esto es lo que hacemos ...

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

para nuevo desarrollo en SQL Server 2005 Usaría sys.database_principals en lugar de sysusers y me quedaría con CREATE USER en lugar de sp_grantdbaccess. – Matt

+1

@Matt ¿podría agregar una respuesta que muestre esta solución? –

+0

Un poco viejo, pero debería ser 'sys.server_principals' y no' sys.database_principals' para este caso. – codenamezero

25

Puede consultar los dos catálogos sys.server_principals sistema para comprobar si hay inicios de sesión de servidor, o sys.database_principals en su base de datos específica para los usuarios de la base de datos:

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 

Marc

+0

Esperaría que el nombre del DB (mydb) aparezca en alguna parte, ¿me falta algo? –

+1

tiene que estar en su base de datos, por supuesto, p. "use mydb" antes del cheque –

13

Esencialmente combinando David's answer y marc_s's answer, según lo solicitado por un comentario de Chris.

Libros en pantalla de sp_grantdbaccess dice:

Esta característica se quitará en una versión futura de Microsoft SQL servidor. Evite utilizar esta función en el nuevo trabajo de desarrollo , y planifique modifique las aplicaciones que actualmente usan esta función. Use CREATE USER en su lugar.

Así que sólo crear un usuario si éste no existe, yo haría algo como esto:

/* 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 

A pesar de estar en desuso, sp_grantdbaccess tiene la ventaja de ser capaz de utilizar un parámetro o variable local para el nombre de usuario/inicio de sesión, como en la respuesta de David. La primera alternativa que pude pensar para obtener algo similar para trabajar con CREATE USER fue usar SQL dinámico. Por ejemplo:

/* 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 

Curiosamente, los libros en pantalla también dice que en realidad llama sp_grantdbaccessCREATE USER, y me di cuenta en mi prueba de que si no se asigna explícitamente un esquema, sp_grantdbaccess va a crear un nombre de usuario, mientras CREATE USER usará 'dbo' por defecto.

0

me preguntó exactamente la misma pregunta en relación con el usuario de SQL ya existente cuando el script se ejecuta - la pregunta, y algunas respuestas son muy útiles aquí:

Checking if a SQL Server login already exists

Espero que esto ayude.

-2
USE MyDB 
GO 

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

Siempre que el único error potencial sea que el usuario ya puede iniciar sesión. – Karlth

+1

Downvoted porque si se produce otro error, como "Política de contraseñas" o "Invalid Login", estos errores serán tragados por el 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 
Cuestiones relacionadas