检查 SQL Server 登录是不是已存在

Posted

技术标签:

【中文标题】检查 SQL Server 登录是不是已存在【英文标题】:Checking if a SQL Server login already exists检查 SQL Server 登录是否已存在 【发布时间】:2010-11-25 15:38:57 【问题描述】:

我需要检查 SQL Server 上是否已经存在特定登录,如果不存在,则需要添加它。

我找到了以下代码来实际将登录名添加到数据库中,但我想将其包装在一个 IF 语句中(以某种方式)以首先检查登录名是否存在。

CREATE LOGIN [myUsername] WITH PASSWORD=N'myPassword', 
DEFAULT_LANGUAGE=[us_english], 
CHECK_EXPIRATION=OFF, 
CHECK_POLICY=OFF 
GO

我知道我需要查询系统数据库,但不知道从哪里开始!

【问题讨论】:

这是一个重要的问题,但正如措辞所言,它似乎忽略了一个重要的区别:用户与登录。 Jon 链接到的潜在副本似乎与用户有关。此问题在标题中显示“用户”,但在问题代码和接受的答案中处理登录。我相应地编辑了标题和问题。 只是添加到@LarsH 的评论中,logins 与 SQL 服务器实例相关联,而 users 与特定数据库相关联。可以从服务器登录创建数据库用户,因此他们可以访问特定数据库。请参阅this excellent article,实际上它是整个系列的一部分(Stariway 到 SQL Server 安全性) 【参考方案1】:

开始 SQL 2016:

DROP USER IF EXISTS [userName]

CREATE USER [userName] FOR LOGIN [loginName]

【讨论】:

【参考方案2】:

为了处理登录名、角色、用户等之间的命名冲突,您应该根据Microsoft sys.database_principals documentation检查type

为了处理用户名等中的特殊字符,请相应地使用N'<name>'[<name>]

创建登录

USE MASTER
IF NOT EXISTS (SELECT 1 FROM master.sys.server_principals WHERE 
[name] = N'<loginname>' and [type] IN ('C','E', 'G', 'K', 'S', 'U'))
    CREATE LOGIN [<loginname>] <further parameters>

创建数据库用户

USE [<databasename>]
IF NOT EXISTS (SELECT 1 FROM sys.database_principals WHERE 
[name] = N'<username>' and [type] IN ('C','E', 'G', 'K', 'S', 'U'))
    CREATE USER [<username>] FOR LOGIN [<loginname>]

创建数据库角色

USE [<databasename>]
IF NOT EXISTS (SELECT 1 FROM sys.database_principals WHERE 
[name] = N'<rolename>' and Type = 'R')
    CREATE ROLE [<rolename>]

将用户添加到角色

USE [<databasename>]
EXEC sp_addrolemember N'<rolename>', N'<username>'

授予角色权限

USE [<databasename>]
GRANT SELECT ON [<tablename>] TO [<rolename>]
GRANT UPDATE ON [<tablename>] ([<columnname>]) TO [<rolename>]
GRANT EXECUTE ON [<procedurename>] TO [<rolename>]

SQL 在 SQL Server 2005、2008、2008 R2、2014、2016、2017、2019 上测试

【讨论】:

【参考方案3】:

这是针对 Azure SQL 的:

IF (EXISTS(SELECT TOP 1 1 FROM sys.sql_logins WHERE [name] = '<login>'))
    DROP LOGIN [<login>];

来源:How to check whether database user already exists in Azure SQL Database

【讨论】:

【参考方案4】:

你可以使用内置函数:

SUSER_ID ( [ 'myUsername' ] )

通过

IF [value] IS NULL [statement]

喜欢:

IF SUSER_ID (N'myUsername') IS NULL
CREATE LOGIN [myUsername] WITH PASSWORD=N'myPassword', 
DEFAULT_LANGUAGE=[us_english], 
CHECK_EXPIRATION=OFF, 
CHECK_POLICY=OFF 
GO

https://technet.microsoft.com/en-us/library/ms176042(v=sql.110).aspx

【讨论】:

这个解决方案很棒,因为它不需要 ALTER ANY LOGIN 权限,而其他所有的都需要。在我的情况下,不可能授予我们的工具权限以查看数据库中的所有登录,但 SUSER_ID('loginName') 仍可用于测试登录是否已存在。谢谢!【参考方案5】:

来自here

If not Exists (select loginname from master.dbo.syslogins 
    where name = @loginName and dbname = 'PUBS')
Begin
    Select @SqlStatement = 'CREATE LOGIN ' + QUOTENAME(@loginName) + ' 
    FROM WINDOWS WITH DEFAULT_DATABASE=[PUBS], DEFAULT_LANGUAGE=[us_english]')

    EXEC sp_executesql @SqlStatement
End

【讨论】:

你应该使用 QUOTENAME 来防止 sql 注入。攻击者可以通过@loginName 像x] with password ''y'';\r\ndrop table foo;\r\n 为什么要创建一个语句作为字符串然后使用sp_executesql,而不是直接输入CREATE LOGIN [@loginName] FROM ...?请原谅我的无知,我想学习... @LarsH:需要将语句创建为字符串,因为 CREATE LOGIN 不能使用参数作为登录名,它需要字符串文字。不知道为什么会这样,但我发现这是真的。 我认为QUOTENAME() 围绕@loginName,而不是整个声明,然后您可以摆脱@loginName 周围的手动[ 和] 分隔符。 syslogins 视图已弃用【参考方案6】:

首先您必须使用 syslogins 视图检查登录是否存在:

IF NOT EXISTS 
    (SELECT name  
     FROM master.sys.server_principals
     WHERE name = 'YourLoginName')
BEGIN
    CREATE LOGIN [YourLoginName] WITH PASSWORD = N'password'
END

然后你必须检查你的数据库是否存在:

USE your_dbname

IF NOT EXISTS
    (SELECT name
     FROM sys.database_principals
     WHERE name = 'your_dbname')
BEGIN
    CREATE USER [your_dbname] FOR LOGIN [YourLoginName] 
END

【讨论】:

我不知道 - 说“您必须使用 syslogins 视图检查登录是否存在”,然后发布不使用该视图的代码看起来像是复制和粘贴问题。此外,在第一条语句之后,“那么你必须检查你的数据库是否存在”这一行,使用并行形式,看起来你是在要求某人检查数据库的存在,而不是数据库级别的用户。并且您需要指定第二批需要在目标数据库中运行。总的来说,这只是一个非常糟糕的解释。而且由于您在获得最高投票的答案五年后添加了它,但更好......【参考方案7】:

您到底想检查登录名或用户什么? 登录是在服务器级别创建的,而用户是在数据库级别创建的,因此登录在服务器中是唯一的

另外一个用户是针对登录创建的,没有登录的用户是一个孤立的用户并且没有用,因为你不能在没有登录的情况下执行 sql server 登录

也许你需要这个

检查登录

select 'X' from master.dbo.syslogins where loginname=<username>

如果登录存在,上述查询返回'X',否则返回null

然后创建一个登录

CREATE LOGIN <username> with PASSWORD=<password>

这会在 sql server 中创建一个登录名。但它只接受强密码

在您要登录的每个数据库中创建一个用户

CREATE USER <username> for login <username>

为用户分配执行权限

 GRANT EXECUTE TO <username>

您必须拥有 SYSADMIN 权限或简称为“sa”

您可以在数据库上为此编写一个 sql 过程

create proc createuser
(
@username varchar(50),
@password varchar(50)
)
as
begin
if not exists(select 'X' from master.dbo.syslogins where loginname=@username)
begin
 if not exists(select 'X' from sysusers where name=@username)
 begin
exec('CREATE LOGIN '+@username+' WITH PASSWORD='''+@password+'''')
exec('CREATE USER '+@username+' FOR LOGIN '+@username)
exec('GRANT EXECUTE TO '+@username)
end
end
end

【讨论】:

【参考方案8】:

以下是在 SQL Server 2005 及更高版本中执行此操作的方法,无需使用已弃用的 syslogins 视图:

IF NOT EXISTS 
    (SELECT name  
     FROM master.sys.server_principals
     WHERE name = 'LoginName')
BEGIN
    CREATE LOGIN [LoginName] WITH PASSWORD = N'password'
END

使用 server_principals 视图代替 sql_logins,因为后者不列出 Windows 登录。

如果您需要在创建之前检查特定数据库中的用户是否存在,那么您可以这样做:

USE your_db_name

IF NOT EXISTS
    (SELECT name
     FROM sys.database_principals
     WHERE name = 'Bob')
BEGIN
    CREATE USER [Bob] FOR LOGIN [Bob] 
END

【讨论】:

最佳答案,不涉及动态 sql,也没有任何已弃用的视图用法。谢谢! 在 SQL Azure 的情况下,两个目标表是 sys.sql_logins 和 sys.sysusers ——在答案中包含这个可能会很好。 如果您的脚本需要使用可变用户名,则无用。 @Derek Morrison 我们可以为 SID 添加一个条件【参考方案9】:

作为此线程的一个小补充,通常您希望避免使用以 sys.sys* 开头的视图,因为 Microsoft 仅包含它们是为了向后兼容。对于您的代码,您可能应该使用 sys.server_principals。这是假设您使用的是 SQL 2005 或更高版本。

【讨论】:

经过测试,有效,并且比其他答案更新。也为你 +1。 是的,2005 年微软取消了对系统表的直接访问。为了避免破坏旧代码,它们包含与旧表同名的视图。但是,它们仅适用于较旧的代码,而较新的代码应使用新视图。在 BOL 中,对 Mapping System Tables 进行搜索以找出您应该使用的内容。【参考方案10】:

试试这个(用实际登录名替换“用户”):

IF NOT EXISTS(
SELECT name 
FROM [master].[sys].[syslogins]
WHERE NAME = 'user')

BEGIN 
    --create login here
END

【讨论】:

@Marc:对不起,你错了。表 [syslogins] 保存登录名,表 [sysusers] 保存用户。【参考方案11】:

这适用于 SQL Server 2000。

use master
select count(*) From sysxlogins WHERE NAME = 'myUsername'

在 SQL 2005 上,将第 2 行更改为

select count(*) From syslogins WHERE NAME = 'myUsername'

我不确定 SQL 2008,但我猜它会与 SQL 2005 相同,如果不是,这应该让您知道从哪里开始寻找。

【讨论】:

以上是关于检查 SQL Server 登录是不是已存在的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 JSTL 检查会话中是不是存在已登录用户?

如何检查Sql server中是不是存在约束?

检查表是不是存在sql server [重复]

如何检查 SQL Server 中是不是存在列?

Sql Server 2008如何检查表中是不是存在列? [复制]

如何检查 SQL Server CE 3.5 中是不是存在表