有没有办法在SQL Server上的数据库中查找特定的用户帐户?
通常,您会向SQL Server添加一个帐户,此时您还可以将用户映射到该服务器上的多个数据库。只要没有人做任何坏事,您就可以返回服务器上的帐户属性,看看帐户映射到的数据库。
但是,这种链接很容易被破坏,数据库中存在一个帐户,但它不会显示为在服务器级别映射到该数据库。此外,您无法在服务器上创建一个帐户(如果该帐户已存在于其中一个数据库中),这就是我所处的情况。
有100个数据库,我需要找到这个用户帐户所在的数据库。据我所知,sys.database_principals我们对每个数据库都是唯一的。是否可以对帐户进行跨数据库搜索并返回其中存在的数据库?
答案 0 :(得分:0)
以下是一些帮助程序查询。
声明@returnValue int EXEC @returnValue = sp_change_users_login'Update_One','SXAUtil','SXAUtil' print'/ @ returnValue /' print @returnValue 打印''
select * from master..syslogins where name='MyUser001'
select * from [MyDatabase001]..sysusers where name='MyUser001'
select 1 as 'Match??' , mastSysLogin.sid as mastSysLogin_Sid, localSysLogin.sid as localSysLogin_Sid, mastSysLogin.name as mastSysLogin_Name , localSysLogin.name as localSysLogin_Name from master..syslogins mastSysLogin join [MyDatabase001]..sysusers localSysLogin on mastSysLogin.sid = localSysLogin.sid
where mastSysLogin.name='MyUser001'
go
我认为这个程序已被弃用,但研究它会显示一些“缺失的链接”信息。
Use MyDatabase001
GO
declare @returnValue int
EXEC @returnValue = sp_change_users_login 'Update_One', 'MyUser001', 'MyUser001'
print '/@returnValue/'
print @returnValue
print ''
下面是我编写的用于向登录添加用户以及作为dbusers并映射到某些角色的脚本。
它使用SQLCMD模式。但是,当我尝试编写用于创建用户的代码时,这是一项“多年来”的努力,如果用户已经添加,则不会抛出错误。
/*
--SqlCmd Notes:
--Remove comments and space between ":" and "setvar" to run in sqlcmd mode.
--!!! Checked in code MUST *recomment out* the setvars below !!! (Putting a space between the ":" and the "setvar" is sufficient)
-- (This is not preferred behavior, the issue has been reported at http://connect.microsoft.com/SQLServer/feedback/details/382007/in-sqlcmd-scripts-setvar-should-have-a-lower-precedence-than-command-line-variable-assignments )
: setvar ErrorOutputFileFromCommandLine "c:\wuwutemp\sqlcommmanderrorfile.txt"
: setvar DBNAME "MyDatabaseName"
: setvar DBUSERNAME "MyDomain\someDomainUserThatExists"
*/
Use [$(DBNAME)]
GO
:Error $(ErrorOutputFileFromCommandLine)
declare @databaseName varchar(64)
select @databaseName = db_name()
print '/@databaseName/'
print @databaseName
print ''
set nocount on
declare @CONST_DB_DATAREADER_ROLE varchar(64)
select @CONST_DB_DATAREADER_ROLE = 'db_datareader'
declare @CONST_DB_BACKUPOPERATOR_ROLE varchar(64)
select @CONST_DB_BACKUPOPERATOR_ROLE = 'db_backupoperator'
declare @UserNameHolder table ( IdentityID int identity(101,1) , DatabaseName varchar(128) , LoginName varchar(256) , MassagedLoginName varchar(264) , RoleName varchar(64) not null , AlreadyProcessed bit default 0 not null )
INSERT INTO @UserNameHolder ( DatabaseName , LoginName , RoleName ) values ( '$(DBNAME)' , '$(DBUSERNAME)' , @CONST_DB_DATAREADER_ROLE )
--INSERT INTO @UserNameHolder ( DatabaseName , LoginName , RoleName ) values ( '$(DBNAME)' , '$(DBUSERNAME)' , @CONST_DB_BACKUPOPERATOR_ROLE )
/* Below this line is "common logic code" */
Update @UserNameHolder Set MassagedLoginName = LoginName
/*
sp_grantlogin does NOT like brackets around a domain/user
example : EXEC sp_grantlogin @loginame = N'[MyDomain\MyUser]'
The "massaging" below is a work around to this issue
*/
Update @UserNameHolder Set MassagedLoginName = RIGHT(MassagedLoginName , LEN(MassagedLoginName) -1 ) where LEN(MassagedLoginName)>0 AND LEFT( MassagedLoginName,1)='['
Update @UserNameHolder Set MassagedLoginName = LEFT( MassagedLoginName , LEN(MassagedLoginName) -1 ) where LEN(MassagedLoginName)>0 AND RIGHT(MassagedLoginName,1)=']'
/* Use a iffy rule to figure out NT Names */
--Update @UserNameHolder Set IsNTName = 1 where LEN(LoginName)>0 AND LEFT( LoginName,1)='[' AND RIGHT(LoginName,1)=']'
-- public is built in, do not process it
Update @UserNameHolder Set AlreadyProcessed = 1 where UPPER(LoginName) = UPPER('public')
select * from @UserNameHolder
declare @CurrentIdentityID int
declare @CurrentLoginName varchar(256)
declare @CurrentMassagedLoginName varchar(256)
declare @CurrentDatabaseName varchar(64)
--declare @CurrentIsNTName bit
declare @CurrentRoleName varchar(64)
declare @sp_grantdbaccess_return_value_total int
select @sp_grantdbaccess_return_value_total = 0
declare @sp_addrolemember_return_value_total int
select @sp_addrolemember_return_value_total = 0
while exists (select null from @UserNameHolder where AlreadyProcessed = 0)
begin
select @CurrentIdentityID = (select top 1 IdentityID from @UserNameHolder where AlreadyProcessed = 0)
print '@CurrentIdentityID'
print @CurrentIdentityID
print ''
select @CurrentLoginName = ( select top 1 LoginName from @UserNameHolder where IdentityID = @CurrentIdentityID )
select @CurrentMassagedLoginName = ( select top 1 MassagedLoginName from @UserNameHolder where IdentityID = @CurrentIdentityID )
select @CurrentDatabaseName = ( select top 1 DatabaseName from @UserNameHolder where IdentityID = @CurrentIdentityID )
--select @CurrentIsNTName = ( select top 1 IsNTName from @UserNameHolder where IdentityID = @CurrentIdentityID )
select @CurrentRoleName = ( select top 1 RoleName from @UserNameHolder where IdentityID = @CurrentIdentityID )
print '@CurrentLoginName'
print @CurrentLoginName
print ''
print '@CurrentMassagedLoginName'
print @CurrentMassagedLoginName
print ''
print '@CurrentDatabaseName'
print @CurrentDatabaseName
print ''
--print '@CurrentIsNTName'
--print @CurrentIsNTName
--print ''
print '@CurrentRoleName'
print @CurrentRoleName
print ''
if(1=1) /* 1=1 is helpful while debugging, set to 1=2 to exclude */
begin
-- select name, loginname from master.dbo.syslogins where loginname = @currentLoginName and isntname = 1)
if not exists (select null from master.dbo.syslogins where UPPER(loginname) = UPPER(@CurrentLoginName) ) -- and isntname = 1)
begin
print 'About to execute sp_grantlogin for user:'
print @CurrentMassagedLoginName
EXEC sp_grantlogin @loginame = @CurrentMassagedLoginName
print ''
print ''
print 'About to execute sp_defaultdb for user:'
print @CurrentMassagedLoginName
EXEC sp_defaultdb @loginame = @CurrentMassagedLoginName , @defdb = @CurrentDatabaseName
print ''
print ''
end
else
begin
print 'NOT EXECUTED : sp_grantlogin'
print 'NOT EXECUTED : sp_defaultdb'
end
end
----------------------------------------
declare @sp_grantdbaccess_return_value int
declare @sp_change_users_login_return_value int
declare @needToRunThisIteration bit
select @needToRunThisIteration = 0
-- declare @currentLoginName varchar(64)
if(1=1) /* 1=1 is helpful while debugging, set to 1=2 to exclude */
begin
if not exists
(
select * from master.dbo.syslogins ml inner join dbo.sysusers
su on ml.sid = su.sid where
su.uid < 6382
and
UPPER(ml.name) = UPPER(@CurrentMassagedLoginName)
)
begin
if not exists
(
/* NOTE, this database name variable must be updated if copying/pasting 'common logic code' between database deployments (NEED_TO_REPLACE_A_VALUE) */
select * from master.dbo.syslogins ml Where
UPPER(ml.name) = UPPER(@CurrentMassagedLoginName)
and UPPER(ml.dbname) = UPPER('$(DBNAME)')
)
begin
select @needToRunThisIteration = 1
end
end
if not exists
(
/* NOTE, this database name variable must be updated if copying/pasting 'common logic code' between database deployments (NEED_TO_REPLACE_A_VALUE) */
select * FROM [$(DBNAME)]..sysusers su Where
UPPER(su.name) = UPPER(@CurrentMassagedLoginName)
)
begin
select @needToRunThisIteration = 1
end
/*
Debug
select dbname , loginname , * from master.dbo.syslogins ml where dbname != 'master' order by 1 , 2
select * FROM TPA2Report..sysusers su
*/
declare @stringNameMatchesButNotSid bit
select @stringNameMatchesButNotSid = 0
IF EXISTS (
SELECT dbUsers.name as NameToFix , *
FROM sys.sysusers dbUsers
join sys.syslogins sqlServerLogins on UPPER(dbUsers.name) = UPPER(sqlServerLogins.name)
WHERE dbUsers.sid != sqlServerLogins.sid
and UPPER(dbUsers.name) = UPPER(@CurrentMassagedLoginName)
)
begin
select @stringNameMatchesButNotSid = 1
end
if (@needToRunThisIteration!=0)
begin
if @stringNameMatchesButNotSid = 0
begin
print 'About to execute sp_grantdbaccess for user:'
print @CurrentMassagedLoginName
exec @sp_grantdbaccess_return_value = sp_grantdbaccess @CurrentMassagedLoginName
print ''
print '@sp_grantdbaccess_return_value'
print @sp_grantdbaccess_return_value
print ''
select @sp_grantdbaccess_return_value_total = @sp_grantdbaccess_return_value_total + @sp_grantdbaccess_return_value
end
else
begin
/* There is a mismatched "sid" issue, but with the same names. This will address the issue. */
print 'About to execute sp_change_users_login for user:'
print @CurrentMassagedLoginName
EXEC @sp_change_users_login_return_value = sp_change_users_login @Action='update_one', @UserNamePattern=@CurrentMassagedLoginName,@LoginName=@CurrentMassagedLoginName;
print ''
print '@sp_change_users_login_return_value'
print @sp_change_users_login_return_value
print ''
end
end
end
-------------------------------------------------------
declare @sp_addrolemember_return_value int
if(1=1) /* 1=1 is helpful while debugging, set to 1=2 to exclude */
begin
if not exists
(
SELECT null --, role_principal_id, member_principal_id, princ1.name AS
role_name, princ2.name As member_name
FROM sys.database_role_members AS S LEFT JOIN sys.database_principals AS
princ1 ON S.role_principal_id = princ1.principal_id AND princ1.type = 'R'
LEFT JOIN sys.database_principals AS princ2 ON S.member_principal_id =
princ2.principal_id AND princ2.type IN ('S', 'U')
WHERE princ1.name = @CurrentRoleName and UPPER(princ2.name) = UPPER(@CurrentMassagedLoginName)
)
begin
print 'About to execute sp_grantdbaccess for user:'
print @CurrentMassagedLoginName
print 'For the role:'
print @CurrentRoleName
exec @sp_addrolemember_return_value = sp_addrolemember @CurrentRoleName, @CurrentMassagedLoginName
print ''
print '@sp_addrolemember_return_value'
print @sp_addrolemember_return_value
print ''
select @sp_addrolemember_return_value_total = @sp_addrolemember_return_value_total + @sp_addrolemember_return_value
end
end
Update @UserNameHolder Set AlreadyProcessed = 1 Where IdentityID = @CurrentIdentityID
end
print '/@sp_grantdbaccess_return_value_total/'
print @sp_grantdbaccess_return_value_total
print '/@sp_addrolemember_return_value_total/'
print @sp_addrolemember_return_value_total
GO