从SQL中的列返回连接的子字符串

从SQL中的列返回连接的子字符串,sql,sql-server,xml,substring,string-concatenation,Sql,Sql Server,Xml,Substring,String Concatenation,我试图创建一个SQL视图,该视图将从表中的列中返回子字符串的连接值 在我的示例中,在名为“TrebuchetSettings”的表中有一个名为“DefDetails”的列,其中包含一个XML值列表,我需要将这些值连接在一起 DefDetails列将为每条记录保存一个如下所示的值: 934ec7a1701c451ce57f2c43bfbbe2e46fe4843f81 使用SQL语句,我需要查询TrebuchetSettings表,并返回上面XML中“FolderDef”节点内“Name”字段的

我试图创建一个SQL视图,该视图将从表中的列中返回子字符串的连接值

在我的示例中,在名为“TrebuchetSettings”的表中有一个名为“DefDetails”的列,其中包含一个XML值列表,我需要将这些值连接在一起

DefDetails列将为每条记录保存一个如下所示的值:


934ec7a1701c451ce57f2c43bfbbe2e46fe4843f81

使用SQL语句,我需要查询TrebuchetSettings表,并返回上面XML中“FolderDef”节点内“Name”字段的串联列表,以“/”字符分隔,其中FolderDef的ID与字符串开头列出的后续FolderDef的ParentID匹配,因此,连接的结构表示文件夹结构

由于此表中还有其他类型的记录,因此我的查询当前由以下内容组成,以确定需要从中提取这些子字符串的记录:

SELECT *
FROM TrebuchetSettings
WHERE DefType = 'FolderSetDef'
AND DefDetails LIKE '%(Folder ID)%'
在上面的示例SQL中,文件夹ID是一个42个字符的ID,它将与另一个表中的值进行比较,以匹配XML中某个文件夹定义的ID


不幸的是,我没有这方面的起始代码集,因为我没有在SQL中使用列的子字符串的经验,也不知道从哪里开始。

SQL并没有一种简单的方法来查找字符串中的多个值。。。但它确实具有将xml转换为可以正常查询的表的功能


尝试以下操作:

如果有大量数据,您尝试执行的操作可能会非常缓慢。。。在这种情况下,最好管理一个(触发的?)边表,在这个边表中,您可以将parentID与包含XML的行的键一起保存在索引列中。换句话说,这就像是一个自建索引

只是想说明一下:您有一个带有多个ID(长字符串)的表。然后,您必须在“/FolderDef”中找到包含此值的所有XML条目,该值为“ParentID”。如果找到一个,则希望将特定DefDetails的所有名称连接起来。这意味着:对于第二个表中的任何ID,您必须反复扫描所有详细信息。。。像
这样的
搜索在开始时使用
%
非常慢。XML方法
.exist()
应该更快

你可以试试这个:

我声明一个表变量,用两个条目模拟设置表:

DECLARE @TrebuchetSettings TABLE(DefDetails XML);
INSERT INTO @TrebuchetSettings VALUES
(N'<Trebuchet>
    <FolderSetDef ID="9365da81288308c9c57aba483f83d2469a5da9ecba" Name="ReportDef" Version="1.0" SubType="" Scope="Global" Culture="Invariant" View="(None)">
        <Alias />
        <Description />
        <Owner>934ec7a1701c451ce57f2c43bfbbe2e46fe4843f81</Owner>
        <FolderList>
            <FolderDef ID="93af31dc1b3238241be33549ba8f8239b377767680" Name="Yearly Reports" ParentID="93af31a36cf8232f44265b40f9a1cd14d1e7000813" Scope="Core" />
            <FolderDef ID="93af31a36cf8232f44265b40f9a1cd14d1e7000813" Name="CSM Management Reports" ParentID="Root" Scope="Core" />
        </FolderList>
    </FolderSetDef>
</Trebuchet>')
,(N'<Trebuchet>
    <FolderSetDef ID="SomeOther" Name="ReportDef" Version="1.0" SubType="" Scope="Global" Culture="Invariant" View="(None)">
        <Alias />
        <Description />
        <Owner>OtherOwner</Owner>
        <FolderList>
            <FolderDef ID="Other first ID" Name="Yearly Reports" ParentID="Other ParentID" Scope="Core" />
            <FolderDef ID="Other second ID" Name="CSM Management Reports" ParentID="Root" Scope="Core" />
        </FolderList>
    </FolderSetDef>
</Trebuchet>');
现在查找具有给定FolderDef ParentID的所有记录,并将所有名称属性列为分隔列表

SELECT ot.FolderID
      ,concatenated.Names
FROM @YourOtherTable AS ot
CROSS JOIN @TrebuchetSettings AS s
CROSS APPLY
(
    SELECT STUFF(
    (
    SELECT '/' + A.NameAttr.value('@Name','varchar(max)')
    FROM DefDetails.nodes('/Trebuchet/FolderSetDef/FolderList/FolderDef') AS A(NameAttr)
    FOR XML PATH('')
    ),1,1,'')
) AS concatenated(Names)
WHERE s.DefDetails.exist('/Trebuchet/FolderSetDef/FolderList/FolderDef[@ParentID=sql:column("ot.FolderID")]')=1
其结果是:

93af31a36cf8232f44265b40f9a1cd14d1e7000813  Yearly Reports/CSM Management Reports

我建议将
Name
value移动/复制到一个单独的列中,并为
DefDetails(如“%”(文件夹ID)%”的行设置一个标志列。
。否则它的运行速度会非常慢。SQL不是处理XML的最佳工具。
93af31a36cf8232f44265b40f9a1cd14d1e7000813  Yearly Reports/CSM Management Reports