从 SQL Server 查询 LDAP - 最佳实践
我想知道当前用于更新用户 (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...至少这是我最初的想法在它上面。
从 SQL Server 2005 查询 Active Directory
提前感谢大家!!!
<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>
I'm wondering if the current process I'm using to update a table of user's (tblUsers) Windows ID's (NTID) is a good method. I'm wondering because LDAP will only return 1000 rows I believe, so that prevents me from just doing it all in one query.
tlbUsers has about 160,000 rows. I'm querying LDAP to update the NTID of each record in tblUsers. I'm using a linked server to ADSI to view LDAP data. My process uses two stored procedures, one for getting a WindowsID from LDAP (LdapPackage.GetUserNTID), another for updating the rows in tblUsers (LdapPackage.UpdateUserNTID).
The code below works for updating the table, however, it's pretty slow. It would seem to me this isn't the best way of doing it, that if I wanted to do a batch update like this from LDAP, there should be a simpler way than updating a record at a time.
This previous post gave an interesting example using UNION's to get around the 1000 record limit, but it only works if each query returns less than 1000 records, which at a large company would probably require lots of UNIONS... at least that's my initial take on it.
Querying Active Directory from SQL Server 2005
Thanks in advance guys!!!
<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>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我的解决方案是让系统管理员增加链接服务器对 LDAP 的记录限制。我更希望能够确定某种 SQL Server 接口,例如 Oracle 所具有的接口……所以也许我将来会实现这一点。
my solution here was to have my that linked servers record limit to LDAP increased by the system admin. I would have preferred to have identified some sort of SQL Server interface like Oracle appears to have... so maybe I'll get to that in the future.