SQL Server How to get the list of all database users

a0x5cqrl  于 2023-04-10  发布在  其他
关注(0)|答案(8)|浏览(204)

I am going to get the list of all users, including Windows users and 'sa', who have access to a particular database in MS SQL Server. Basically, I would like the list to look like as what is shown in SQL Server Management Studio (i.e. the list that is shown when you expand [databse] -> Security -> Users ) with one important exception: I do not want to see the 'dbo' in the list. Rather, I would like to see the actual user who owns the database. So, for example, if 'sa' is the 'dbo' , 'sa' must be included in the list instead of 'dbo' . Another note not to be missed is, the list in the SQL Server Management Studio normally shows Windows users in addition to SQL users, And I would like those users to be included as well.

So far, I have been able to come up with the following query:

SELECT * FROM sys.database_principals where (type='S' or type = 'U')

This query is almost right but the problem is it doesn't satisfy the 'dbo' condition.

How can I change this query or should I use another one?

xdnvmnnf

xdnvmnnf1#

For the SQL Server Owner, you should be able to use:

select suser_sname(owner_sid) as 'Owner', state_desc, *
from sys.databases

For a list of SQL Users:

select * from master.sys.server_principals

Ref. SQL Server Tip: How to find the owner of a database through T-SQL

How do you test for the existence of a user in SQL Server?

rpppsulh

rpppsulh2#

EXEC sp_helpuser

or

SELECT * FROM sysusers

Both of these select all the users of the current database (not the server).

5sxhfpxr

5sxhfpxr3#

Whenever you 'see' something in the GUI (SSMS) and you're like "that's what I need", you can always run Sql Profiler to fish for the query that was used.

Run Sql Profiler. Attach it to your database of course.

Then right click in the GUI (in SSMS) and click "Refresh".
And then go see what Profiler "catches".

I got the below when I was in MyDatabase / Security / Users and clicked "refresh" on the "Users".

Again, I didn't come up with the WHERE clause and the LEFT OUTER JOIN, it was a part of the SSMS query. And this query is something that somebody at Microsoft has written (you know, the peeps who know the product inside and out, aka, the experts), so they are familiar with all the weird "flags" in the database.

But the SSMS/GUI -> Sql Profiler tricks works in many scenarios.

SELECT
u.name AS [Name],
'Server[@Name=' + quotename(CAST(
        serverproperty(N'Servername')
       AS sysname),'''') + ']' + '/Database[@Name=' + quotename(db_name(),'''') + ']' + '/User[@Name=' + quotename(u.name,'''') + ']' AS [Urn],
u.create_date AS [CreateDate],
u.principal_id AS [ID],
CAST(CASE dp.state WHEN N'G' THEN 1 WHEN 'W' THEN 1 ELSE 0 END AS bit) AS [HasDBAccess]
FROM
sys.database_principals AS u
LEFT OUTER JOIN sys.database_permissions AS dp ON dp.grantee_principal_id = u.principal_id and dp.type = 'CO'
WHERE
(u.type in ('U', 'S', 'G', 'C', 'K' ,'E', 'X'))
ORDER BY
[Name] ASC
nue99wik

nue99wik4#

SELECT name FROM sys.database_principals WHERE
type_desc = 'SQL_USER' AND default_schema_name = 'dbo'

This selects all the users in the SQL server that the administrator created!

2w3rbyxf

2w3rbyxf5#

Go for this:

SELECT name,type_desc FROM sys.sql_logins
rhfm7lfc

rhfm7lfc6#

I try to avoid using the "SELECT * " option and just pull what data I want or need. The code below is what I use, you may cull out or add columns and aliases per your needs.

I also us "IIF" (instant if) to replace binary 0 or 1 with a yes or no. It just makes it easier to read for the non-techie that may want this info.

Here is what I use:

SELECT 
    name AS 'User'
  , PRINCIPAL_ID
  , type AS 'User Type'
  , type_desc AS 'Login Type'
  , CAST(create_date AS DATE) AS 'Date Created' 
  , default_database_name AS 'Database Name'
  , IIF(is_fixed_role LIKE 0, 'No', 'Yes') AS 'Is Active'
FROM master.sys.server_principals
WHERE type LIKE 's' OR type LIKE 'u'
ORDER BY [User], [Database Name]; 
GO

Hope this helps.

tsm1rwdh

tsm1rwdh7#

To run a query returning users of individual databases, try this:

EXEC sp_MSforeachdb 'USE ? <QUERY HERE>'

This will run a query (and return a result) for each database. So to get all users (probably with a lot of internal users and roles you are not interested in, try:

EXEC sp_MSforeachdb 'USE ?; SELECT DB_NAME(), * FROM sys.database_principals;'

Just apply filters mentioned in other replys to get exactly the subset you are looking for.

2izufjch

2izufjch8#

I use the following batch to list all logins of all databases including their owners.

It loops through every database and writes the DB's principals into a temporary table ( ##DBLogin ), appends the owner-information to it, updates the owner's login type if NULL , executes a SELECT on the temporary table and drops the table again, leaving you with a nice tabular result with all logins for each DB (can be executed in a single go).

USE tempdb

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[##DBLogin]') AND type in (N'U'))
DROP TABLE [dbo].[##DBLogin]

SET NOCOUNT ON;
SELECT DB_NAME() AS [DBLogin_Database], name AS DBLogin_Name, type_desc AS DBLogin_Type, 0 AS DBLogin_Owner
INTO ##DBLogin
FROM sys.database_principals WHERE 1 = 2;

DECLARE @Query AS NVARCHAR(MAX) = 'USE ? INSERT INTO ##DBLogin SELECT ''?'' AS [DBLogin_Database], name AS DBLogin_Name, type_desc AS DBLogin_Type, 0 AS DBLogin_Owner FROM sys.database_principals WHERE type != ''R'';'
EXEC sp_MSforeachdb @Query;

INSERT INTO ##DBLogin 
SELECT DB.name AS DBLogin_Database, SUSER_SNAME(DB.owner_sid) AS DBLoginName, type_desc AS DBLogin_Type, 1 AS DBLogin_Owner
FROM sys.databases DB
LEFT OUTER JOIN sys.server_principals SP ON SUSER_SNAME(DB.owner_sid) = SP.name

-- Do some guess-work for the owner's login type (comment out if you prefere to have NULL instead of guess-work)
UPDATE A SET A.DBLogin_Type = (SELECT TOP(1) B.DBLogin_Type FROM ##DBLogin B WHERE B.DBLogin_Name = A.DBLogin_Name AND B.DBLogin_Type IS NOT NULL) FROM ##DBLogin A WHERE (A.DBLogin_Type IS NULL) AND (A.DBLogin_Owner = 1);
UPDATE ##DBLogin SET DBLogin_Type = 'WINDOWS_USER' WHERE (DBLogin_Type IS NULL) AND (DBLogin_Owner = 1) AND (DBLogin_Name LIKE '%_\_%');
UPDATE ##DBLogin SET DBLogin_Type = 'SQL_USER' WHERE (DBLogin_Type IS NULL) AND (DBLogin_Owner = 1) AND (DBLogin_Name NOT LIKE '%_\_%');

SELECT DBLogin_Database, DBLogin_Name, MAX(DBLogin_Type) AS DBLogin_Type, CAST(MAX(DBLogin_Owner) AS BIT) AS DBLogin_Owner FROM ##DBLogin 
GROUP BY DBLogin_Database, DBLogin_Name
ORDER BY DBLogin_Database, DBLogin_Owner DESC, DBLogin_Name, DBLogin_Type

DROP TABLE [dbo].[##DBLogin]

Watch out: The owners login type is a bit taken from here and there and if still unknown, guessed. Comment according lines out if in doubt (the lines that contain UPDATE statements).

相关问题