【发布时间】:2011-10-29 01:22:08
【问题描述】:
我想知道我用来更新用户 (tblUsers) Windows ID (NTID) 表的当前进程是否是一个好方法。我想知道,因为我相信 LDAP 只会返回 1000 行,所以这阻止了我在一个查询中完成所有操作。
tlbUsers 有大约 160,000 行。我正在查询 LDAP 以更新 tblUsers 中每条记录的 NTID。我正在使用连接到 ADSI 的服务器来查看 LDAP 数据。我的进程使用两个存储过程,一个用于从 LDAP 获取 WindowsID (LdapPackage.GetUserNTID),另一个用于更新 tblUsers 中的行 (LdapPackage.UpdateUserNTID)。
下面的代码用于更新表格,但是速度很慢。在我看来,这不是最好的方法,如果我想从 LDAP 进行这样的批量更新,应该有比一次更新记录更简单的方法。
上一篇文章给出了一个使用 UNION 来绕过 1000 条记录限制的有趣示例,但它仅在每个查询返回少于 1000 条记录时才有效,这在大公司可能需要大量 UNION... 至少这是我最初的看法。
Querying Active Directory from SQL Server 2005
提前谢谢大家!!!
<code>
CREATE PROCEDURE LdapPackage.GetUserNTID
(
@EmployeeID INT,
@OutNTID VARCHAR(20) OUTPUT
)
AS
BEGIN
DECLARE @SQLString NVARCHAR(MAX)
DECLARE @ParmDefinition NVARCHAR(MAX)
DECLARE @LdapFilter NVARCHAR(100)
--DECLARE @NTID VARCHAR(20)
SET @LdapFilter = 'employeeNumber = ' + CAST(@EmployeeID AS NVARCHAR(20))
SET @SQLString = 'SELECT DISTINCT @pNTID = samAccountName
FROM OPENQUERY(LDAP,
''select samAccountName, Mail
from ''''GC://domain.company.com''''
where objectClass=''''user'''' AND objectCategory=''''person'''' and ' + @LdapFilter + ''')
WHERE Mail IS NOT NULL'
SET @ParmDefinition = N'@pNTID varchar(20) OUTPUT'
EXECUTE sp_executesql
@SQLString,
@ParmDefinition,
@pNTID=@OutNTID OUTPUT
--SELECT NTID = @OutNTID
END
</code>
<code>
CREATE PROCEDURE LdapPackage.UpdateUserNTID
AS
BEGIN
DECLARE @EmployeeID AS INT
DECLARE @NTID AS VARCHAR(20)
DECLARE @RowCount AS INT
DECLARE @SQLString AS NVARCHAR(MAX)
DECLARE @ParmDefinition AS NVARCHAR(200)
SET @RowCount = 1
DECLARE Persons CURSOR
FOR SELECT DISTINCT EmployeeID FROM tblUsers
OPEN Persons
FETCH NEXT FROM Persons INTO @EmployeeID
WHILE @@FETCH_STATUS = 0
BEGIN
--GET NTID
SET @SQLString =N'EXEC LdapPackage.GetUserNTID @pEmployeeID, @pNTID OUTPUT'
SET @ParmDefinition =N'@pEmployeeID INT, @pNTID VARCHAR(20) OUTPUT'
EXECUTE sp_executesql
@SQLString,
@ParmDefinition,
@pEmployeeID=@EmployeeID,
@pNTID=@NTID OUTPUT
--UPDATE NTID
/*PRINT 'RowCount = ' + CAST(@RowCount AS VARCHAR(10))
PRINT 'EmployeeID = ' + CAST(@EmployeeID AS VARCHAR(20))
PRINT 'NTID = ' + @NTID
PRINT '-----------------------------'*/
UPDATE tblUsers
SET NTID = @NTID
WHERE EmployeeID = @EmployeeID
SET @RowCount = @RowCount + 1
FETCH NEXT FROM Persons INTO @EmployeeID
END
CLOSE Persons
DEALLOCATE Persons
END
</code>
【问题讨论】:
-
另一种方法是创建一个包含您要更新的所有条目的 LDIF 文件。然后一次更新它们。这可能会更好,尤其是在更新目录中的所有条目并且目录包含大量条目时。请参阅我的博客条目"Using ldapmodify"。
-
可以将其创建为 SQL Server 中的包还是我需要在其他地方创建的东西?
-
在完整的 Microsoft 使用中,可能有一个解决方案 Deploying CLR Database Objects。在里面你可以使用 DirectorySearcher,它允许你使用分页搜索。
-
您好 JPBlanc,虽然我希望能够在 SQL Server 中使用 CLR 功能,但我的实例所在的服务器不允许这样做。我没有CLR!我的 DBA 说该政策是出于安全问题。我不确定这是不是真的,不管怎样,它完全消除了我可以使用的一些很棒的功能。
标签: sql-server sql-server-2008 tsql active-directory ldap