错误:无法从OLE DB提供程序“ADsDSOObject”获取链接服务器“ADSI”的行

时间:2011-12-21 18:46:44

标签: sql sql-server sql-server-2008

当我尝试为用户查询AD时,收到以下错误:

无法从OLE DB提供程序“ADsDSOObject”获取链接服务器“ADSI”的行。

我认为问题是由于1000行限制(或SqlServer 2008中的901行)。我可以分页查询,但我正在寻找允许我一次检索超过1000个的解决方法。

如果有帮助,我使用的是SqlServer 2008 R2。 这是我的查询

SELECT  samaccountname AS Account, ISNULL(givenName, '''') AS givenName, ISNULL(SN, '''') AS SN, ISNULL(DisplayName, '''') as DisplayName, ISNULL(Title, '''') AS Title 
                        FROM OpenQuery(ADSI, 
                        'SELECT SamAccountName, givenName, SN, DisplayName, Title
                        FROM ''LDAP://corpdomain.corp'' 
                        WHERE objectClass = ''User'' and (SN = ''*'' or givenName = ''*'')')

有什么想法吗?

编辑 - 经过进一步检查,我意识到我无法正确地查询此查询。有没有人对解决方案有任何建议,允许我分页结果或一个允许我返回901以上的解决方法?

6 个答案:

答案 0 :(得分:3)

从您对我的评论的回复,这听起来像是一个SQL Agent工作解雇的SSIS包将是一个理想的方式。以下是您在SSIS中访问Active Directory的方法:

  1. 创建新的SSIS项目
  2. 将数据流任务添加到控制流。
  3. 单击“数据流”选项卡。
  4. 将ADO NET Source从工具箱拖到数据流。
  5. 双击ADO NET Source。
  6. 单击“OLE DB连接管理器”旁边的“新建”按钮。
  7. 单击“配置ADO.NET连接管理器”中的“新建”按钮 对话框。
  8. 点击“提供商”下拉列表中的向下箭头。
  9. 在列表中找到OleDb的.Net提供商,然后双击它。
  10. 在列表中查找Microsoft Directory Services的OLE DB提供程序  然后双击它。
  11. 单击“确定”按钮。
  12. 在服务器或文件名中输入ActiveDirectory。
  13. 在数据连接中突出显示ActiveDirectory。
  14. 单击“确定”按钮。
  15. 将数据访问模式更改为SQL命令。
  16. 在SQL命令文本框中输入  <LDAP://DC=domain,DC=tld>;(&(objectClass=User)(objectCategory=Person));distinguishedName,displayName,sn,givenName,middleName,mail,telephoneNumber;subtree
  17. 将域和tld更改为适合您的标识符  域并添加任何其他适当的LDAP路径元素。
  18. 将任何其他适当的ActiveDirectory属性添加到查询中。
  19. 单击“确定”按钮。
  20. 您将看到指示数据类型的错误消息  不支持“System.Object”。这些可以忽略。
  21. 单击警告对话框上的“确定”按钮。
  22. 右键单击ADO NET Source。
  23. 单击“属性”。
  24. 将ValidateExternalMetadata更改为False。
  25. 您可能还想执行以下步骤,但请注意,如果您执行此操作并且Active Directory属性的长度超过4000个字符,则会在数据流中截断它。

    1. 右键单击ADO NET Source。
    2. 单击“显示高级编辑器”。
    3. 转到“输入和输出属性”选项卡。
    4. 展开ADO NET源输出。
    5. 展开输出列。
    6. 对于每列,将DataType更改为Unicode字符串[DT_WSTR]和 将长度设置为4000。
    7. 单击“确定”按钮。
    8. 双击ADO NET Source转到错误输出。
    9. 选择Trunctation下的行的所有值。
    10. 列表项
    11. 在“将此值设置为选定的单元格”下,选择“忽略失败”。
    12. 单击“应用”按钮。
    13. 单击“确定”按钮。
    14. 请注意,此搜索格式也受支持:

      SELECT     distinguishedName, displayName, sn, givenName, middleName, mail, telephoneNumber
      FROM         'LDAP://DC=domain,DC=tld'
      WHERE     objectClass = 'User' AND objectCategory = 'Person'
      

      有关提供程序支持的查询格式的详细信息,请参阅MSDN文章Microsoft OLE DB Provider for Microsoft Active Directory Service

答案 1 :(得分:3)

问题

  

当我尝试为用户查询AD时,收到以下错误:

     

无法从OLE DB提供程序“ADsDSOObject”获取链接服务器“ADSI”的行。

     

我认为问题是由于1000行限制(或SqlServer 2008中的901行)。我可以查询查询&gt;但我正在寻找允许我一次检索超过1000个的解决方法。

     

如果有帮助,我使用的是SqlServer 2008 R2。这是我的疑问   &GT;

SELECT  samaccountname AS Account, ISNULL(givenName, '''') AS givenName, ISNULL(SN, '''') AS SN, ISNULL(DisplayName, '''') as DisplayName, ISNULL(Title, '''') AS Title 
                    FROM OpenQuery(ADSI, 
                    'SELECT SamAccountName, givenName, SN, DisplayName, Title
                    FROM ''LDAP://corpdomain.corp'' 
                    WHERE objectClass = ''User'' and (SN = ''*'' or givenName = ''*''
  

有什么想法吗?

     

编辑 - 经过进一步检查,我意识到我无法正确地查询此查询。是否&gt;任何人都有一个解决方案的任何提示,允许我分页结果或一个解决方法,将允许我返回超过901?

我的解决方法

我刚刚解决了我面临的同样问题,通过最佳应用分页(我成功地从AD中检索了大约50k登录,并且从AD域中获取单个登录帐户并不缺少):

您需要通过循环遍历属性的字符来解决ADSI查询限制。请在此处查看解决方案:http://www.sqlservercentral.com/Forums/Topic231658-54-1.aspx#bm1249991

错误已通过SELECT TOP 901 ...编写SELECT来解决。

是的,这个问题与使用SqlServer 2008 R2有关。从2005年到2008年将数据库迁移后,我遇到了这个问题,因为在SQL Server 2008中,SQL Server 2005中有901行的限制为1000(不同之处在于我们需要编写选择TOP 901,这不是在SQL Server 2005中需要,否则程序失败并出现错误)

答案 2 :(得分:3)

我也遇到了这个问题,并且不喜欢通过帐户名的第一个字母发送的常规解决方案。这将意味着对AD进行26次单独调用,并且还可能仍然可能失败,因为对于大型域,可能有超过901个帐户以相同的第一个字母开头 - 特别是如果您正在查看可能遵循某些系统的计算机帐户使用相同的第一个字母命名约定...

我做了一些游戏,我发现如果您通过uSNCreated订购openquery并在外部查询上放置一个TOP 901子句,它就不会爆炸。

因此,这是我的SQL,它将所有活动目录对象(计算机,域控制器,用户和联系人)提取到901条记录的临时表中,并为您提供有关每个对象的一些有用信息。

CREATE TABLE #ADData(
    Login           NVARCHAR(256)
    ,CommonName     NVARCHAR(256)
    ,GivenName      NVARCHAR(256)
    ,FamilyName     NVARCHAR(256)   
    ,DisplayName    NVARCHAR(256)
    ,Title          NVARCHAR(256)
    ,Department     NVARCHAR(256)
    ,Location       NVARCHAR(256)
    ,Info           NVARCHAR(256)
    ,LastLogin      BIGINT
    ,flags          INT
    ,Email          NVARCHAR(256)
    ,Phone          NVARCHAR(256)   
    ,Mobile         NVARCHAR(256)
    ,Quickdial      NVARCHAR(256)
    , usnCreated    INT
)

DECLARE @Query      VARCHAR (2000)
DECLARE @Filter     VARCHAR(200)
DECLARE @Rowcount   INT

select @Filter =''

WHILE ISNULL(@rowcount,901)  = 901 BEGIN

    SELECT @Query = '
    SELECT top 901
            Login           = SamAccountName
            , CommonName    = cn
            , GivenName
            , FamilyName    = sn    
            , DisplayName
            , Title
            , Department
            , Location      = physicalDeliveryOfficeName
            , Info
            , LastLogin     = CAST(LastLogon AS bigint)
            , flags         = CAST (UserAccountControl as int)
            , Email         = mail
            , Phone         = telephoneNumber
            , Mobile        = mobile
            , QuickDial     = Pager
            , usnCreated
        FROM OPENROWSET(''ADSDSOObject'', '''', ''
                SELECT cn, givenName, sn, userAccountControl, lastLogon, displayName, samaccountname, 
                title,  department, physicalDeliveryOfficeName, info, mail, telephoneNumber, mobile, pager, usncreated
            FROM ''''LDAP://[ldap-query-string]'''' 
            WHERE objectClass=''''Person''''
            AND objectClass = ''''User''''
            ' + @filter + '
            ORDER BY usnCreated'')'             
    INSERT INTO #ADData EXEC (@Query) 
    SELECT @Rowcount = @@ROWCOUNT
    SELECT @Filter = 'and usnCreated > '+ LTRIM(STR((SELECT MAX(usnCreated) FROM #ADData)))

END

SELECT LOGIN            
        , CommonName    
        , GivenName
        , FamilyName
        , DisplayName
        , Title         
        , Department
        , Location      
        , Email         
        , Phone         
        , QuickDial     
        , Mobile        
        , Info          
        , Disabled      = CASE WHEN CAST (flags AS INT) & 2 > 0 THEN 'Y' ELSE NULL END 
        , Locked        = CASE WHEN CAST (flags AS INT) & 16  > 0 THEN 'Y' ELSE NULL END 
        , NoPwdExpiry   = CASE WHEN CAST (flags AS INT) & 65536  > 0 THEN 'Y' ELSE NULL END 
        , LastLogin     = CASE WHEN ISNULL(CAST (LastLogin AS BIGINT),0) = 0 THEN NULL ELSE 
                            DATEADD(ms, (CAST (LastLogin AS BIGINT) / CAST(10000 AS BIGINT)) % 86400000,
                            DATEADD(day, CAST (LastLogin AS BIGINT) / CAST(864000000000 AS BIGINT) - 109207, 0)) END 
        , Type = CASE WHEN flags  & 512 = 512 THEN 'user' 
                    WHEN flags IS NULL THEN 'contact' 
                    WHEN flags & 4096 = 4096 THEN 'computer'
                    WHEN flags & 532480 = 532480 THEN 'computer (DC)' END
FROM #ADData
ORDER BY Login

DROP TABLE #ADData

答案 3 :(得分:0)

我使用Magnus Reuter的另一篇文章解决了这个问题 - 我认为我给了所有链接,因为它很简单巧妙!

他做了2个查询,使用UNION加入他们,但是对于第一个他选择了所有sAMAccountname m。当然,如果你发现你的中间不是字母&#34; m&#34;你可以相应地调整它,但一般来说,如果你有大约1000-2000条记录,它将是&#34; m&#34;。

Retrieve >901 rows from SQL Server 2008 linked server to Active Directory

答案 4 :(得分:0)

还有一个原因可能会导致此错误。如果您使用多个域,则可能需要更改此SQL Server的Active Directory属性。选择&#34;信任此计算机以便委派任何服务(仅限Kerberos)&#34;如果原因来自&#34; double hop&#34;在多域设置中。

Active Directory Server Properties

答案 5 :(得分:0)

当结果集中的行数少于1000时,也会发生完全相同的无法从OLE DB提供程序“ ADSDSOObject”获取行错误消息,但是其他原因会阻止SQL提取记录。最近,我们遇到了SQL Service帐户密码已过期的情况,这似乎是导致此错误的原因。在服务的登录详细信息中更新密码,然后重新启动SQL Server对其进行修复。

只是以为我会在这里回答这个问题,所以如果将来有人用谷歌搜索此错误消息,这也可能会有所帮助!