Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How can i query Active Directory from my SQL Server 3

Status
Not open for further replies.

soutener

IS-IT--Management
Jul 12, 2006
56
0
0
US
I have an intranet web page that i put reports on to using sql server/asp i have a database of peoples names, titles and thier phone extensions, this data has to be updated separately from Active Directory, i know there is some thing called ADSI wich i can use to query the database and hopefully remove one step from our chores, since all info is kept in AD on our users.

my question is how do i go about doing this, i've tried google, but cant seem to find any thing of use, or i'm not google'ing the right keywords, here's my setup:

SQL Server 2005 SP1 on a separate server i have Windows Server 2003 Standard in native mode AD

thanks!
 
Querying AD isn't very simple to do. It has to be done through funky dynamic sql that doesn't like accepting variables. Here's a thread I started a while back that has an example thread183-1076237.

I recommend simply exporting the data from active directly once or twice a day (depending on how current of data you need) using csvde.exe and then importing the data into SQL.

You might be able to setup SSIS to connect and do a transformation, but I'm not sure. I've never tried.

Denny
MCSA (2003) / MCDBA (SQL 2000) / MCTS (SQL 2005) / MCITP Database Administrator (SQL 2005)

--Anything is possible. All it takes is a little research. (Me)
[noevil]
 
i'll be happy if its once a day.

i'll try that, thank you.
 
no problem.

Denny
MCSA (2003) / MCDBA (SQL 2000) / MCTS (SQL 2005) / MCITP Database Administrator (SQL 2005)

--Anything is possible. All it takes is a little research. (Me)
[noevil]
 
i just used

select *
from openquery
(
ADSI,'SELECT cn, mail, department, title
FROM ''LDAP://domain.com''
WHERE objectCategory = ''Person''
AND objectClass = ''user''
order by mail
'
)


and it worked like a champ

thanks again!
 
Keep in mind, that ADSI will only return 1000 records at a time. If you have more users than that it only return the first 1000.

Denny
MCSA (2003) / MCDBA (SQL 2000) / MCTS (SQL 2005) / MCITP Database Administrator (SQL 2005)

--Anything is possible. All it takes is a little research. (Me)
[noevil]
 
Hi guys
Still having difficulty connecting to AD.
I got SQL 2000 in W2003 standalone box. My
AD is a W2K domain.

exec sp_addlinkedserver 'ADSI', 'Active Directory Service Interfaces', 'ADSDSOObject', 'adsdatasource'
Creates a linked server but cannot execute queries.

I also ran
EXEC sp_addlinkedsrvlogin 'ADSI', 'false', 'MyDomain\UserName', 'UserName', 'Password'

The error I'm getting is ...
Server: Msg 7321, Level 16, State 2, Line 1
An error occurred while preparing a query for execution against OLE DB provider 'ADSDSOObject'.
OLE DB error trace [OLE/DB Provider 'ADSDSOObject' ICommandPrepare::prepare returned 0x80040e14].


Looks like an authentication ISSUE ????...

Your thoughts please...

Thanks

DJ



 
Is your machine a member of the domain? You shouldn't be passing your domain account info to the linked server.

Check the referenced thread above. I posted an example on how to create a link to AD in that thread.

Denny
MCSA (2003) / MCDBA (SQL 2000) / MCTS (SQL 2005) / MCITP Database Administrator (SQL 2005)

--Anything is possible. All it takes is a little research. (Me)
[noevil]
 
i got about 600 users, so i should be OK until i'm not ;)

thanks again
 
There's a free ActiveX component available called JustLDAP that is used to query AD from scripts.
I can see no reason that this can't be called from a SQL Server stored procedure but don't have a Windows domain to test it against.

John
 
I dug around for several days on this same issue. I ended up writing a stored procedure that handles the sp_OA calls to use ADO connections to query LDAP and get around the 1000 record limit.

use master
go
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[spQueryAD]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[spQueryAD]
go
create procedure spQueryAD (@LDAP_Query varchar(255)='', @Verbose bit=0)
as

--verify proper usage and display help if not used properly
if @LDAP_Query ='' --argument was not passed
BEGIN
Print ''
Print 'spQueryAD is a stored procedure to query active directory without the default 1000 record LDAP query limit'
Print ''
Print 'usage -- Exec spQueryAD ''_LDAP_Query_'', Verbose_Output(0 or 1, optional)'
Print ''
Print 'example: Exec spQueryAD ''SELECT EmployeeID, SamAccountName FROM ''''LDAP://dc=domain,dc=com'''' WHERE objectCategory=''''person'''' and objectclass=''''user'''''', 1'
Print ''
Print 'spQueryAD returns records corresponding to fields specified in LDAP query.'
Print 'Use INSERT INTO statement to capture results in temp table.'
Return --'spQueryAD aborted'
END

--declare variables
DECLARE @ADOconn INT -- ADO Connection object
, @ADOcomm INT -- ADO Command object
, @ADOcommprop INT -- ADO Command object properties pointer
, @ADOcommpropVal INT -- ADO Command object properties value pointer
, @ADOrs INT -- ADO RecordSet object
, @OLEreturn INT -- OLE return value
, @src varchar(255) -- OLE Error Source
, @desc varchar(255) -- OLE Error Description
, @PageSize INT -- variable for paging size Setting
, @StatusStr char(255) -- variable for current status message for verbose output

SET @PageSize = 1000 -- IF not SET LDAP query will return max of 1000 rows

--Create the ADO connection object
IF @Verbose=1
BEGIN
Set @StatusStr = 'Create ADO connection...'
Print @StatusStr
END
EXEC @OLEreturn = sp_OACreate 'ADODB.Connection', @ADOconn OUT
IF @OLEreturn <> 0
BEGIN -- Return OLE error
EXEC sp_OAGetErrorInfo @ADOconn , @src OUT, @desc OUT
SELECT Error=CONVERT(varbinary(4),@OLEreturn), Source=@src, Description=@desc
RETURN
END
IF @Verbose=1 Print Space(len(@StatusStr)) + 'done.'

--SET the provider property to ADsDSOObject to point to Active Directory
IF @Verbose=1
BEGIN
Set @StatusStr = 'Set ADO connection to use Active Directory driver...'
Print @StatusStr
END
EXEC @OLEreturn = sp_OASETProperty @ADOconn , 'Provider', 'ADsDSOObject'
IF @OLEreturn <> 0
BEGIN -- Return OLE error
EXEC sp_OAGetErrorInfo @ADOconn , @src OUT, @desc OUT
SELECT Error=CONVERT(varbinary(4),@OLEreturn), Source=@src, Description=@desc
RETURN
END
IF @Verbose=1 Print Space(len(@StatusStr)) + 'done.'

--Open the ADO connection
IF @Verbose=1
BEGIN
Set @StatusStr = 'Open the ADO connection...'
Print @StatusStr
END
EXEC @OLEreturn = sp_OAMethod @ADOconn , 'Open'
IF @OLEreturn <> 0
BEGIN -- Return OLE error
EXEC sp_OAGetErrorInfo @ADOconn , @src OUT, @desc OUT
SELECT Error=CONVERT(varbinary(4),@OLEreturn), Source=@src, Description=@desc
RETURN
END
IF @Verbose=1 Print Space(len(@StatusStr)) + 'done.'

--Create the ADO command object
IF @Verbose=1
BEGIN
Set @StatusStr = 'Create ADO command object...'
Print @StatusStr
END
EXEC @OLEreturn = sp_OACreate 'ADODB.Command', @ADOcomm OUT
IF @OLEreturn <> 0
BEGIN -- Return OLE error
EXEC sp_OAGetErrorInfo @ADOcomm , @src OUT, @desc OUT
SELECT Error=CONVERT(varbinary(4),@OLEreturn), Source=@src, Description=@desc
RETURN
END
IF @Verbose=1 Print Space(len(@StatusStr)) + 'done.'

--SET the ADO command object to use the connection object created first
IF @Verbose=1
BEGIN
Set @StatusStr = 'Set ADO command object to use Active Directory connection...'
Print @StatusStr
END
EXEC @OLEreturn = sp_OASETProperty @ADOcomm, 'ActiveConnection', 'Provider=''ADsDSOObject'''
IF @OLEreturn <> 0
BEGIN -- Return OLE error
EXEC sp_OAGetErrorInfo @ADOcomm , @src OUT, @desc OUT
SELECT Error=CONVERT(varbinary(4),@OLEreturn), Source=@src, Description=@desc
RETURN
END
IF @Verbose=1 Print Space(len(@StatusStr)) + 'done.'

--Get a pointer to the properties SET of the ADO Command Object
IF @Verbose=1
BEGIN
Set @StatusStr = 'Retrieve ADO command properties...'
Print @StatusStr
END
EXEC @OLEreturn = sp_OAGetProperty @ADOcomm, 'Properties', @ADOcommprop out
IF @OLEreturn <> 0
BEGIN -- Return OLE error
EXEC sp_OAGetErrorInfo @ADOcomm , @src OUT, @desc OUT
SELECT Error=CONVERT(varbinary(4),@OLEreturn), Source=@src, Description=@desc
RETURN
END
IF @Verbose=1 Print Space(len(@StatusStr)) + 'done.'

--SET the PageSize property
IF @Verbose=1
BEGIN
Set @StatusStr = 'Set ''PageSize'' property...'
Print @StatusStr
END
IF (@PageSize IS NOT null) -- If PageSize is SET then SET the value
BEGIN
EXEC @OLEreturn = sp_OAMethod @ADOcommprop, 'Item', @ADOcommpropVal out, 'Page Size'
IF @OLEreturn <> 0
BEGIN -- Return OLE error
EXEC sp_OAGetErrorInfo @ADOcommprop , @src OUT, @desc OUT
SELECT Error=CONVERT(varbinary(4),@OLEreturn), Source=@src, Description=@desc
RETURN
END
EXEC @OLEreturn = sp_OASETProperty @ADOcommpropVal, 'Value','1000'
IF @OLEreturn <> 0
BEGIN -- Return OLE error
EXEC sp_OAGetErrorInfo @ADOcommpropVal , @src OUT, @desc OUT
SELECT Error=CONVERT(varbinary(4),@OLEreturn), Source=@src, Description=@desc
RETURN
END
END
IF @Verbose=1 Print Space(len(@StatusStr)) + 'done.'

--SET the SearchScope property to ADS_SCOPE_SUBTREE to search the entire subtree
IF @Verbose=1
BEGIN
Set @StatusStr = 'Set ''SearchScope'' property...'
Print @StatusStr
END
BEGIN
EXEC @OLEreturn = sp_OAMethod @ADOcommprop, 'Item', @ADOcommpropVal out, 'SearchScope'
IF @OLEreturn <> 0
BEGIN -- Return OLE error
EXEC sp_OAGetErrorInfo @ADOcommprop , @src OUT, @desc OUT
SELECT Error=CONVERT(varbinary(4),@OLEreturn), Source=@src, Description=@desc
RETURN
END
EXEC @OLEreturn = sp_OASETProperty @ADOcommpropVal, 'Value','2' --ADS_SCOPE_SUBTREE
IF @OLEreturn <> 0
BEGIN -- Return OLE error
EXEC sp_OAGetErrorInfo @ADOcommpropVal , @src OUT, @desc OUT
SELECT Error=CONVERT(varbinary(4),@OLEreturn), Source=@src, Description=@desc
RETURN
END
END
IF @Verbose=1 Print Space(len(@StatusStr)) + 'done.'

--SET the Asynchronous property to True
IF @Verbose=1
BEGIN
Set @StatusStr = 'Set ''Asynchronous'' property...'
Print @StatusStr
END
BEGIN
EXEC @OLEreturn = sp_OAMethod @ADOcommprop, 'Item', @ADOcommpropVal out, 'Asynchronous'
IF @OLEreturn <> 0
BEGIN -- Return OLE error
EXEC sp_OAGetErrorInfo @ADOcommprop , @src OUT, @desc OUT
SELECT Error=CONVERT(varbinary(4),@OLEreturn), Source=@src, Description=@desc
RETURN
END
EXEC @OLEreturn = sp_OASETProperty @ADOcommpropVal, 'Value',True
IF @OLEreturn <> 0
BEGIN -- Return OLE error
EXEC sp_OAGetErrorInfo @ADOcommpropVal , @src OUT, @desc OUT
SELECT Error=CONVERT(varbinary(4),@OLEreturn), Source=@src, Description=@desc
RETURN
END
END
IF @Verbose=1 Print Space(len(@StatusStr)) + 'done.'

--Create the ADO Recordset to hold the results of the LDAP query
IF @Verbose=1
BEGIN
Set @StatusStr = 'Create the temporary ADO recordset for query output...'
Print @StatusStr
END
EXEC @OLEreturn = sp_OACreate 'ADODB.RecordSET',@ADOrs out
IF @OLEreturn <> 0
BEGIN -- Return OLE error
EXEC sp_OAGetErrorInfo @ADOrs , @src OUT, @desc OUT
SELECT Error=CONVERT(varbinary(4),@OLEreturn), Source=@src, Description=@desc
RETURN
END
IF @Verbose=1 Print Space(len(@StatusStr)) + 'done.'

--Pass the LDAP query to the ADO command object
IF @Verbose=1
BEGIN
Set @StatusStr = 'Input the LDAP query...'
Print @StatusStr
END
EXEC @OLEreturn = sp_OASETProperty @ADOcomm, 'CommandText', @LDAP_Query
IF @OLEreturn <> 0
BEGIN -- Return OLE error
EXEC sp_OAGetErrorInfo @ADOcomm , @src OUT, @desc OUT
SELECT Error=CONVERT(varbinary(4),@OLEreturn), Source=@src, Description=@desc
RETURN
END
IF @Verbose=1 Print Space(len(@StatusStr)) + 'done.'

--Run the LDAP query and output the results to the ADO Recordset
IF @Verbose=1
BEGIN
Set @StatusStr = 'Execute the LDAP query...'
Print @StatusStr
END
Exec @OLEreturn = sp_OAMethod @ADOcomm, 'Execute' ,@ADOrs OUT
IF @OLEreturn <> 0
BEGIN -- Return OLE error
EXEC sp_OAGetErrorInfo @ADOcomm , @src OUT, @desc OUT
SELECT Error=CONVERT(varbinary(4),@OLEreturn), Source=@src, Description=@desc
RETURN
END
IF @Verbose=1 Print Space(len(@StatusStr)) + 'done.'

--Return the rows found
IF @Verbose=1
BEGIN
Set @StatusStr = 'Retrieve the LDAP query results...'
Print @StatusStr
END
EXEC @OLEreturn = sp_OAgetproperty @ADOrs, 'getrows'
IF @OLEreturn <> 0
BEGIN -- Return OLE error
EXEC sp_OAGetErrorInfo @ADOrs , @src OUT, @desc OUT
SELECT Error=CONVERT(varbinary(4),@OLEreturn), Source=@src, Description=@desc
RETURN
END
IF @Verbose=1 Print Space(len(@StatusStr)) + 'done.'
go
 
Hi notjustageek,

I'm not really sql fluent and I wondering how integrate INSERT INTO statement into your script ?

I understand that 'EXEC @OLEreturn = sp_OAgetproperty @ADOrs, 'getrows'' contains and display the results, but how can we insert these data into another table, with specific columns ?

Anyway, thank you for this code, I never heard about COM objects and these sp before reading it, it's really interesting!
 
If you put an insert into line above that line with all the columns that are being returned you will be able to dump the data inta a table. The table will need to already exist, and will need to have the same columns that are being returned by the sp_OAgetproperty procedure.
Code:
...
insert into TableName
(ColumnList...)
EXEC @OLEreturn = sp_OAgetproperty @ADOrs, 'getrows'
...

Denny
MCSA (2003) / MCDBA (SQL 2000) / MCTS (SQL 2005) / MCITP Database Administrator (SQL 2005)

--Anything is possible. All it takes is a little research. (Me)
[noevil]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top