【发布时间】:2022-05-06 10:02:53
【问题描述】:
我想知道是否有更简单的方法可以在 SQL 中反转 Active Directory 规范名称。我找到了一种方法来做到这一点,但它只适用于一定数量的 OU,我希望它适用于任意数量的 OU。
例如:我想使用规范名称为“domain.org/company/users/department/john smith”的一行并反转字符串顺序,使其显示“John Smith/department/users/company /domain.org"
为此,我使用了从其他帖子中找到的几种不同的 XML 方法。下面的代码将字符串转换为 XML 并计算值中的节点数。然后它使用 case 语句将字符串以相反的顺序连接在一起。
正如您在 case 语句中看到的那样,我必须将所有可能数量的节点都放入 case 语句中,以便当前可以正常工作。如果可能的话,我想计算节点计数并通过节点倒计时向后循环,但我不确定如何使用 SQL 来实现这一点,或者是否有更好的方法来完成我正在尝试做的事情。
SELECT *
,CASE
WHEN NodeCount = 4
THEN CONCAT('"',MyXML.value('/root[1]/i[4]','varchar(100)'),'/',MyXML.value('/root[1]/i[3]','varchar(100)'),'/',MyXML.value('/root[1]/i[2]','varchar(100)'),'/',MyXML.value('/root[1]/i[1]','varchar(100)'),'"')
WHEN NodeCount = 5
THEN CONCAT('"',MyXML.value('/root[1]/i[5]','varchar(100)'),'/',MyXML.value('/root[1]/i[4]','varchar(100)'),'/',MyXML.value('/root[1]/i[3]','varchar(100)'),'/',MyXML.value('/root[1]/i[2]','varchar(100)'),'/',MyXML.value('/root[1]/i[1]','varchar(100)'),'"')
WHEN NodeCount = 6
THEN CONCAT('"',MyXML.value('/root[1]/i[6]','varchar(100)'),MyXML.value('/root[1]/i[5]','varchar(100)'),'/',MyXML.value('/root[1]/i[4]','varchar(100)'),'/',MyXML.value('/root[1]/i[3]','varchar(100)'),'/',MyXML.value('/root[1]/i[2]','varchar(100)'),'/',MyXML.value('/root[1]/i[1]','varchar(100)'),'"')
END AS ReversedPath
FROM (
SELECT CanonicalName
,(CONVERT(XML, '<root><i>' + REPLACE(CanonicalName , '/', '</i><i>') + '</i></root>').query('.')) MyXML
,(CONVERT(XML, '<root><i>' + REPLACE(CanonicalName , '/', '</i><i>') + '</i></root>').value('count(/root/i)', 'INT')) NodeCount
FROM dbo.[GetActiveDirectoryUsers]
WHERE AccountIsEnabled = 'True') T
如果有人对解决此问题的其他方法有一些想法,我们将不胜感激。
供参考:我使用这些脚本用我的 AD 用户信息填充 SQL 表。 https://www.sqlservercentral.com/articles/powershell-to-get-active-directory-users-and-groups-into-sql
编辑:按照 Kevin 的建议,使用下面的代码创建了一个缩放器值函数。
ALTER FUNCTION [dbo].[fnReverseString] (@string varchar(500),@splitChar varchar(1))
RETURNS varchar(500)
AS
BEGIN
DECLARE @rev varchar(500);
with cte as
(
select 1 pos_from, charindex(@splitChar, @string) + 1 pos_to
union all
select pos_to, charindex(@splitChar, @string + @splitChar, pos_to) + 1
from cte
where pos_to <= len(@string)
)
select @rev = coalesce( @rev + @splitChar, '') + substring(@string, pos_from, pos_to - pos_from - 1)
from cte
order by pos_to desc
return @rev
END
现在我可以从我的查询中调用它并为供应商创建请求的输出。再次感谢!
WITH CTE1 AS (
SELECT dbo.fnReverseString(CanonicalName,'/') ReversedPath
FROM dbo.[GetActiveDirectoryUsers]
WHERE AccountIsEnabled = 'True'
)
SELECT '[' + STUFF((SELECT ',' + CONCAT('"',ReversedPath,'"') AS [text()] FROM CTE1 FOR XML PATH ('')), 1, 1, '') + ']' FinalResult
输出
["John Smith/department/users/company/domain.org","Jane Smith/department/users/company/domain.org"]
【问题讨论】:
-
您可以使用循环或 cte 来完成,我认为这两种方式都是更简单/更好的方式。
标签: sql-server