I’m having some trouble configuring a SQL statement to perform an openquery on LDAP from SQL Server. I followed the instructions as laid out here: Querying Active Directory from SQL Server 2005 but I’m having some trouble putting the final pieces together.
Firstly, I didn’t know where my LDAP server was. So I did a nslookup
and found the default server as:
abc.domain.popo.local
I configured my OPENQUERY
as
SELECT * FROM OPENQUERY( ADSI, 'SELECT * FROM ''LDAP://DC=abc,DC=domain,DC=popo,DC=local'' WHERE
objectCategory = ''User''')
However, I get an error saying that
An error occurred while preparing the query «SELECT * FROM ‘LDAP://DC=abc,DC=domain,DC=popo,DC=local’ WHERE objectCategory = ‘User'» for execution against OLE DB provider «ADSDSOObject» for linked server «ADSI».
What is the likely issue here? Am I setting up the DC
incorrectly (because I don’t even know what DC means)? Or is it more likely that I just have the wrong server altogether for LDAP?
- Remove From My Forums
-
Question
-
Hello I am trying to run a query via tsql against ad. Below is the error I am getting. I have read the http://msdn2.microsoft.com/en-US/library/ms190803.aspx and changed the domain but still having issues. Any help would be appreciated.
EXEC sp_addlinkedserver ‘ADSI’, ‘Active Directory Service Interfaces’,
‘ADSDSOObject’, ‘adsdatasource’
GO
SELECT *
FROM OPENQUERY( ADSI,
‘SELECT Name, SN, ST
FROM »LDAP://ADSISrv/ OU=Users,DC=XXXXX,DC=LOCAL»
WHERE objectCategory = »Person» AND
objectClass = »user»’)
Msg 7321, Level 16, State 2, Line 1
An error occurred while preparing the query «SELECT Name, SN, ST
FROM ‘LDAP://ADSISrv/ OU=Users,DC=XXXXX,DC=LOCAL’
WHERE objectCategory = ‘Person’ AND
objectClass = ‘user'» for execution against OLE DB provider «ADSDSOObject» for linked server «ADSI».
Answers
-
I had the same issue like you, if you run in your personal computer is probably that you not experiment the same error but if you move to any other server that need the right permission to any user into the Active Directory.
first execute your query:
EXEC sp_addlinkedserver
‘ADSI’,
‘Active Directory Service Interfaces’,
‘ADSDSOObject’
,
‘adsdatasource’GO
Like daw21 explain before follow the detail steps:
Second step go to the SqlServer management Studio and edit manually the Linkserver name ADSI:
go to Server Objects/Linked Servers/ and right click on ADSI select the option Properties and then go to Security.
Select the option : Be made using this security context:
and there fill the user and Password about the valid user with permission into Active Directory, not forget before the domainuser.
-
Proposed as answer by
Monday, August 8, 2011 9:18 PM
-
Marked as answer by
Kalman Toth
Tuesday, August 16, 2011 10:54 AM
-
Proposed as answer by
-
Took me forever to get this working …
First you have to make sure that Ad Hoc Distributed Queries is enabled …
sp_configure 'Ad Hoc Distributed Queries', 1
reconfigure
Second you have to make sure that you specify a security context that has access to AD INCLUDING the DOMAIN
Third you should put a row limit (e.g. SELECT TOP 100) in to avoid the issue where you hit the 1000 row limit so
SELECT
TOP 100
*FROM
OpenQuery(ADSI,
'SELECT sAMAccountName FROM ''LDAP://DC=core,DC=acllab,DC=net'' WHERE objectCategory=''user'' ')-
Marked as answer by
Kalman Toth
Tuesday, August 16, 2011 10:54 AM
-
Marked as answer by
I have been trying to configure a linked server to AD and have found plenty of write ups on how to do it, but have had zero luck with getting it to work. I also read that the ability was removed after SQL 2008; is that correct? I am running 2014
and am seeing the following error trying to expand the tree:
TITLE: Microsoft SQL Server Management Studio
——————————
Failed to retrieve data for this request. (Microsoft.SqlServer.Management.Sdk.Sfc)
For help, click: http://go.microsoft.com/fwlink?ProdName=Microsoft%20SQL%20Server&LinkId=20476
——————————
ADDITIONAL INFORMATION:
An exception occurred while executing a Transact-SQL statement or batch. (Microsoft.SqlServer.ConnectionInfo)
——————————
Cannot obtain the required interface («IID_IDBSchemaRowset») from OLE DB provider «ADSDSOObject» for linked server «ADSI». (Microsoft SQL Server, Error: 7301)
For help, click: http://go.microsoft.com/fwlink?ProdName=Microsoft%20SQL%20Server&ProdVer=12.00.4100&EvtSrc=MSSQLServer&EvtID=7301&LinkId=20476
Then the following error when trying to query:
SELECT * FROM OpenQuery(ADSI, ‘SELECT displayName FROM »LDAP://<DOMAIN>/DC=DOMAIN,DC=<DOMAIN>» WHERE objectCategory=»User» ‘)
Msg 7321, Level 16, State 2, Line 1
An error occurred while preparing the query «SELECT displayName FROM ‘LDAP://—-/DC=—-,DC=—-‘ WHERE objectCategory=’User’ » for execution against OLE DB provider «ADSDSOObject» for linked server «ADSI».
The linked server is set for ‘Be made by the login’s current security context’ and local to remote is configured SA to a domain account we use for lookups.
It does not seem to matter if I am logged in to the server with SQL or Windows credentials. Thank you in advance for any guidance!
-Drew
When I run this query:
SELECT *
FROM OPENQUERY([XXX], 'SELECT *
FROM Database.Table
WHERE (MBCONO=650) AND MBCUNO LIKE a%' )
I get the error:
OLE DB provider «DB2OLEDB» for linked server «XXX» returned message
«Token %ŸFOR SKIP WITH FETCH ORDER UNION EXCEPT OPTIMIZE SQLSTATE:
42601, SQLCODE: -104».Msg 7321, Level 16, State 2, Line 1 An error
occurred while preparing the query «SELECT * FROM Database.Table WHERE
(MBCONO=650) AND MBCUNO LIKE a%'» for execution against OLE DB
provider «DB2OLEDB» for linked server «LAWSON».
I can run the same query without AND MBCUNO LIKE a%
successfully.
asked Apr 10, 2013 at 9:12
1
I would suggest you change your original SQL Statement as follows:
SELECT *
FROM OPENQUERY([XXX], 'SELECT * FROM database.table where left(MBCUNO, 1) = ''a'' and (MBCONO=650) ' )
This has the two variable swopped around, and the like %
exchanged for a left(mbcuno,1)
.
Ensure that all your table & column references are correct
answered Apr 10, 2013 at 12:27
RoKaRoKa
1,61411 silver badges16 bronze badges
Время на прочтение
5 мин
Количество просмотров 33K
Доброго дня. Решил что опыт обработки данных AD посредством SQL будет полезен не только мне, тем более внятного мануала на русском я так и не нашел.
За стиль изложения прошу сильно не бить, старался объяснить как можно доступнее, как сам хотел увидеть когда искал инфу.
Собственно задача: «А сделайте нам отчет по всем пользователям компании, да так чтобы и группы его выводились». Не знаю насколько это реально какими то нативными средствами администрирования AD, но первая идея пришедшая в голову написать запрос к AD и вытянуть с него всю инфу которую только можно в какую нить табличку и дальше уже обрабатывать чем душе угодно, будь то reporting service или что нить в духе crystal reports. Как же достучаться до AD?
Оказывается у MSSQL есть нативный OLE DB провайдер для подключения AD. Добавляем наш linked server в server objects:
EXEC master.dbo.sp_addlinkedserver @server = N'ADSI'
, @srvproduct=N'Active Directory Service Interfaces'
, @provider=N'ADSDSOObject'
, @datasrc=N'adsdatasource'
Сразу хотел бы отметить что код, используемый в топике, уже не раз опробован за последние несколько дней на разных серверах (2008/2008 R2/2012) и приводится генерируемый sql скрипт.
Как через gui это сделать не скажу, ибо не знаю
После того как мы создали сервер необходимо добавить к нему логин:
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'ADSI'
,@useself=N'False'
,@locallogin=NULL
,@rmtuser=N'Domainuser'
,@rmtpassword='password'
Хочу заметить, что в настройках самого сервера мы явно не указываем интересующее нас конкретное ldap подключение.
Настройки генерируемые sql-сервером:
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'collation compatible', @optvalue=N'false'
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'data access', @optvalue=N'true'
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'dist', @optvalue=N'false'
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'pub', @optvalue=N'false'
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'rpc', @optvalue=N'false'
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'rpc out', @optvalue=N'false'
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'sub', @optvalue=N'false'
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'connect timeout', @optvalue=N'0'
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'collation name', @optvalue=null
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'lazy schema validation', @optvalue=N'false'
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'query timeout', @optvalue=N'0'
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'use remote collation', @optvalue=N'true'
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'remote proc transaction promotion', @optvalue=N'true'
Все, сервер у нас есть. Теперь нужен запрос. Для запросов можно использовать два диалекта:
- 1) SQL подобный синтаксис — его и использовал.
- 2) LDAP подобный синтаксис — на мой взгляд более логично выглядящий, но узнал я о нем уже когда все сделал.
Запросы выполняются через OPENQUERY к интересующему нас серверу. В запрос в FROM пишем ссылку ввида LDAP://dc=maindomain,dc=rootfolder, заворачиваем её в апосторофы и пишем селект лист. Ссылку эту можно получить либо у админов, либо самому поискать по ad нужную нам ветку любым удобным браузером ldap.
Запрос:
SELECT * FROM OPENQUERY(ADSI,'SELECT cn,sAMAccountName FROM ''LDAP://dc=maindomain,dc=rootfolder''')
Жмем f5. Ура запрос работает. Радость недолгая, спустя строк 900 (меньше секунды) вываливается
Cannot fetch a row from OLE DB provider «ADSDSOObject» for linked server «ADSI».
Сразу скажу что это настраиваемое ограничение самого AD, а не драйвера, или провайдера, или еще чего нибудь. Ну если он только не 2000, в 2000 это не настраивается. Как это настраивается можем посмотреть здесь.
Можем пойти двумя путями: попросить админов перенастроить или обойти это ограничение. Конечная цель получить всех пользователей.
Сузим круг поиска:
SELECT * FROM OPENQUERY(ADSI,'SELECT cn,sAMAccountName FROM ''LDAP://dc=maindomain,dc=rootfolder'' WHERE AND objectClass=''person'' AND objectClass<>''computer'' ')
Опять много? Ну что ж, значит нужно хитрить. Можно искать конкретного пользователя например. Но нам нужно тогда знать логины всех пользователей тоже не хорошо. Ну найдем хотя бы тех у которых логин начинается на abc. Искать будем по полю sAMAccountName — это поле которое во всех схемах AD вроде как есть, ну если вы не экстремально уникальную схему используете. Если все же экстремальную, тогда обращайтесь к админам пускай найдут её (схему) для вас. Думаю с полем определились. Теперь пошли отличия диалекта от ansi sql:
SELECT * FROM OPENQUERY(ADSI,'SELECT cn,sAMAccountName FROM ''LDAP://dc=maindomain,dc=rootfolder'' WHERE sAMAccountName =''abc*'' AND objectClass=''person'' AND objectClass<>''computer'' ')
Если есть пользователи начинающиеся на abc, то он вам что нибудь вернет:
sAMAccountName cn
abceeeee abceeeee dfdf eee
Да, в обратном порядке. Нет, не знаю почему. Ладно к примеру мы придумаем вложенный цикл с перебором комбинаций букв от a до z и поиск типа sAMAccountName=aa*, потом sAMAccountName=ab*, опустим динамический запрос. К примеру пользователей получили. Теперь нужно группы получить.
Просим:
SELECT * FROM OPENQUERY(ADSI,'SELECT memberOf,cn,sAMAccountName FROM ''LDAP://dc=maindomain,dc=rootfolder'' WHERE sAMAccountName =''abc*'' AND objectClass=''person'' AND objectClass<>''computer'' ')
Получаем:
Cannot get the data of the row from the OLE DB provider «ADSDSOObject» for linked server «ADSI». Could not convert the data value due to reasons other than sign mismatch or overflow.
memberOf может быть несколько, ну логично в принципе. Попросим не группы пользователя, а группы в которых есть пользователь и приджойним всю эту конструкцию. Чтобы получить все группы, ищем группу у которой в member прописан dn нашего искомого пользователя
SELECT * FROM OPENQUERY(ADSI,'SELECT name FROM ''LDAP://dc=maindomain,dc=rootfolder'' WHERE objectCategory = ''Group'' AND member=''CN=username,OU=Departments,dc=maindomain,dc=rootfolder'' ')
Группы получили, что еще вытянуть из них лучше посмотреть в схеме.
Теперь попробуем пользователя «umi(юми китайский департамент)». Ну странный пользователь, не спорю. Но английское имя, а в скобках русское, вполне себе нормально. Ладно, не суть.
Запрос:
SELECT * FROM OPENQUERY(ADSI,'SELECT name FROM ''LDAP://dc=maindomain,dc=rootfolder'' WHERE objectCategory = ''Group'' AND member=''CN=umi(юми китайский департамент),OU=Departments,dc=maindomain,dc=rootfolder'' ')
Ответ тоже получим, если у этого пользователя есть какие нибудь группы. Но если мы экспортируем пользователя откуда нибудь где у нас пользователь зовется какой нибудь русской длинной абракадаброй, тогда строка у нас будет
umi(юми китайский департамент, должность не помню как искать долго, ну просто так)
А на cn у нас ограничение в 64 символа, итого получаем:
umi(юми китайский департамент, должность не помню как искать дол
С точки зрения запроса все нормально, sql ругаться не будет на кривой запрос, но ldap провйдер ругнется и скажет что
An error occurred while preparing the query «тут наш запрос» for execution against OLE DB provider «ADSDSOObject» for linked server «ADSI».
Да, скобки искать нельзя. Сначала я думал что экранировать можно через кавычки, потом думал что через слеш, потом через амперсанд, много думал. Не получается. Ответ пришелся сам по себе: я этого же пользователя попробовал найти в ldap браузере (любого можете взять, думаю все равно пригодится). И при конструировании запроса когда я ввел слеш он сам мне подсказал какие символы можно экранировать.
Список вот:
( - 28
) - 29
* - 2A
- 5C
Carriage Return - D
Line Feed - 0A
NUL - 0
Отдельно стоит отметить апостороф, как видете в списке экранирований апострофа нет. С точки хрения AD все нормально, запрос работает, вываливается ошибка именно на обработке запроса провайдером.Экранировать его можно только через sql
Наш dn выглядит так: CN=Luk'yanova Inna (Лукьянова Инна Инновна),OU=Departments,dc=maindomain,dc=rootfolder
.
Мы его присвоили каким то образом в @dn. Чтоб не пришлось вам лишний раз сидеть ковырять сколько апострофов поставить вот:
SET @dn = REPLACE(@dn,'''','''''''''')
Ну а дальше, а дальше либо в процедурину, либо просто куда надо запихиваете этот запрос(запросы) и работаете уже с sql-таблицами как вам угодно.
P.S. об ошибках в топике прошу оповещать меня в личку, а не через комментарии.