Map between SQL Server SIDs and Windows SIDs

By:   |   Updated: 2014-10-13   |   Comments (3)   |   Related: More > Security


I occasionally see people troubleshooting some problem in Windows, where the only information they have is the Windows SID, in the form S-1-5-21-601521654-1178811285-3323947944-1000. Trying to map that to the SID belonging to a login or group in SQL Server is difficult, because they are in a different form, for example: 0x010500000000000515000000F67DDA23953B4346A86B1FC6E8030000. You certainly cannot eyeball that and identify a match, and even manual conversion between these two values is not exactly straightforward.


Based almost entirely on some work done long ago in a forum thread here, I thought that it would make a lot of sense to have a view over sys.server_principals - perhaps in your own utility database - which also exposed the Windows version of the SID. This would make it far easier to troubleshoot issues like this, even if they don't come up very often.

The forum thread above uses two scalar functions to map back and forth, but I am a big stickler for inline, table-valued functions. The benefit, in simplistic terms, is the way inline functions are optimized as part of the plan for the query, unlike scalar functions, which are called per row and optimized separately. Not that this is a situation where you need screaming performance, but it's a good behavior to follow in general.

And we actually only need one function here, because we will always have the SQL version of the SID in sys.server_principals. In order to create the function, though, first we will need a numbers table (this allows us to treat segments of the Windows SID string as a set instead of parsing them manually in an explicit loop):


INSERT dbo.TinyNumbers(Number) 
  FROM master.dbo.spt_values;

We could generate a sequence of numbers in the function, too, without having some table of numbers to draw from, but that would either prevent us from marking the function as SCHEMABINDING (if we were to use a system view like spt_values instead), or lead to much more verbose looping or CTE-type code to generate the sequence without the assistance of any auxiliary objects. Here is the function:

  @sid VARBINARY(85)
    SELECT ADsid = STUFF((SELECT '-' + part FROM 
      SELECT Number = -1, part = 'S-' 
        + '-' 
      SELECT TOP ((LEN(@sid)-5)/4) Number, 
      FROM dbo.TinyNumbers ORDER BY Number
    ) AS x ORDER BY Number
    FOR XML PATH(''), TYPE).value(N'.[1]','nvarchar(max)'),1,1,'')

Then we can simply create a view that pulls certain columns from sys.server_principals, and passes the SID to the function via CROSS APPLY:

CREATE VIEW dbo.server_principal_sids
  SELECT, sp.[sid], ad.ADsid, sp.type_desc
    FROM sys.server_principals AS sp
    CROSS APPLY dbo.GetWindowsSID(sp.[sid]) AS ad
    WHERE [type] IN ('U','G') 
    AND LEN([sid]) % 4 = 0;

Now I can simply say:

SELECT name,[sid],ADSid,type_desc FROM dbo.server_principal_sids;

And I will get results like this:


Disclaimer: The function does a very good job at parsing Windows-based SIDs because they all happen to map to a very particular pattern (S-1-5-... see KB #163846 for details). For things like SQL logins, server roles and certificate-mapped logins, the pattern can be different, and the function does not account for those differences, leading to errors or bogus values. This is why the filters are in place in the view, so please use this function with caution if you are trying to generate Windows-looking SIDs from anything other than Windows logins - you will likely need to make adjustments for that to work.

Next Steps

Last Updated: 2014-10-13

get scripts

next tip button

About the author
MSSQLTips author Aaron Bertrand Aaron Bertrand (@AaronBertrand) is a passionate technologist with industry experience dating back to Classic ASP and SQL Server 6.5. He is editor-in-chief of the performance-related blog,, and also blogs at

View all my tips
Related Resources

Post a comment or let the author know this tip helped.

All comments are reviewed, so stay on subject or we may delete your comment. Note: your email address is not published. Required fields are marked with an asterisk (*).

Email me updates

Signup for our newsletter

I agree by submitting my data to receive communications, account updates and/or special offers about SQL Server from MSSQLTips and/or its Sponsors. I have read the privacy statement and understand I may unsubscribe at any time.

Tuesday, October 24, 2017 - 9:21:25 AM - S.E. Back To Top seems I cannot spare to learn how to cope with XML in TSQL... :)

Very nice and elegant! Thanks!

Tuesday, March 21, 2017 - 11:12:40 AM - Akash Back To Top

Thanks Aaron,

Saved me a lot of effort!

Monday, October 27, 2014 - 8:30:26 AM - Junior Galv„o - MVP Back To Top

Hi Aaoron,

Great article, good job.


get free sql tips

I agree by submitting my data to receive communications, account updates and/or special offers about SQL Server from MSSQLTips and/or its Sponsors. I have read the privacy statement and understand I may unsubscribe at any time.

Learn more about SQL Server tools