具有不同子项的 Sql XML 路径

2023-12-20

我已经完成了很多 XML PATH 语句,但这个语句我却忽略了,或者对于多个不同的子项来说甚至可能是不可能的。

最终结果应该是这样的

<Process>
<TaskList>
<SqlTask Name="Get Report Parameters">
    <StoredProcName>GetReportParameters</StoredProcName>
        <ConnectionName>Local</ConnectionName>
        <DataTableName>DistributionList</DataTableName>
        <Parameters>
              <Parameter>
            <Name>ReportName</Name>
            <Value>TheReprot</Value>
            <Type>String</Type>
              </Parameter>
        </Parameters>
  </SqlTask>
  <LoopTask Name="Loop Report Creation" ContainerKey="DistributionList">
  <TaskList>
        <ReportTask Name="Report In Loop">   
    </ReportTask>
</TaskList>
  </LoopTask>
  <SqlTask Name="Get Email Addresses">
    <StoredProcName>GetMailingAddress</StoredProcName>
        <ConnectionName>Local</ConnectionName>
        <DataTableName>EmailList</DataTableName>

  </SqlTask>
  <LoopTask Name="Loop Mail Creation" ContainerKey="EmailList">
<TaskList>
        <MailTask Name="Send Email In Loop">       
        </MailTask>
</TaskList>
  </LoopTask>
</TaskList>
</Process>

下面是我迄今为止拥有的一些测试表和数据。问题实际上是如何在同一根下显示不同的子节点。我可以从列值中派生标签名称吗?

CREATE TABLE #TASK (
    TaskId INT IDENTITY(1,1)
,    ProcessId INT
,    TaskType VARCHAR(255)
,    TaskName VARCHAR(255)
,    ContainerKey VARCHAR(255)
,    ParentTaskId INT
)

CREATE TABLE #TASK_PARAMETERS 

(
    TaskId INT
,    Name VARCHAR(255)
,    Value VARCHAR(MAX)
,    [Type] VARCHAR(128)
)

CREATE TABLE #TASK_DETAILS
(
    TaskId INT
,    DetailName VARCHAR(255)
,    DetailValue VARCHAR(MAX)
)

DECLARE @TaskId AS INT
DECLARE @ParentTaskId AS INT


INSERT INTO #TASK 
(
    ProcessId
,    TaskType
,    TaskName
,    ContainerKey
,    ParentTaskId
)
VALUES 
(
0
,    'SqlTask'
,    'Get Report Parameters'
,    NULL
,    NULL
)

SET @TaskId = @@IDENTITY

INSERT INTO #TASK_DETAILS
(
    TaskId
,    DetailName
,    DetailValue
)
VALUES 
(
    @TaskId
,    'StoredProceName'
,    'GetReportParamters'
)

INSERT INTO #TASK_DETAILS
(
    TaskId
,    DetailName
,    DetailValue
)
VALUES 
(
    @TaskId
,    'ConnectionName'
,    'Local'
)

INSERT INTO #TASK_DETAILS
(
    TaskId
,    DetailName
,    DetailValue
)
VALUES 
(
    @TaskId
,    'DataTableName'
,    'DistributionList'
)

INSERT INTO #TASK_PARAMETERS 

(
    TaskId
,    Name
,    Value
,    [Type]
)
VALUES 
(
    @TaskId
,    'ReportName'
,    'TheReprot'
,   'String'
)


INSERT INTO #TASK 
(
    ProcessId
,    TaskType
,    TaskName
,    ContainerKey
,    ParentTaskId
)
VALUES 
(
0
,    'LoopTask'
,    'Loop Report Creation'
,    'DistributionList'
,    NULL
)

SET @ParentTaskId = @@IDENTITY


INSERT INTO #TASK 
(
    ProcessId
,    TaskType
,    TaskName
,    ContainerKey
,    ParentTaskId
)
VALUES 
(
0
,    'ReportTask'
,    'Report In Loop'
,    NULL
,    @ParentTaskId
)


INSERT INTO #TASK 
(
    ProcessId
,    TaskType
,    TaskName
,    ContainerKey
,    ParentTaskId
)
VALUES 
(
0
,    'SqlTask'
,    'Get Email Addresses'
,    NULL
,    NULL
)

SET @TaskId = @@IDENTITY

INSERT INTO #TASK_DETAILS
(
    TaskId
,    DetailName
,    DetailValue
)
VALUES 
(
    @TaskId
,    'StoredProceName'
,    'GetMailingAddress'
)

INSERT INTO #TASK_DETAILS
(
    TaskId
,    DetailName
,    DetailValue
)
VALUES 
(
    @TaskId
,    'ConnectionName'
,    'Local'
)

INSERT INTO #TASK_DETAILS
(
    TaskId
,    DetailName
,    DetailValue
)
VALUES 
(
    @TaskId
,    'DataTableName'
,    'EmailList'
)


INSERT INTO #TASK 
(
    ProcessId
,    TaskType
,    TaskName
,    ContainerKey
,    ParentTaskId
)
VALUES 
(
0
,    'LoopTask'
,    'Loop Mail Creation'
,    'EmailList'
,    NULL
)

SET @ParentTaskId = @@IDENTITY

INSERT INTO #TASK 
(
    ProcessId
,    TaskType
,    TaskName
,    ContainerKey
,    ParentTaskId
)
VALUES 
(
0
,    'MailTask'
,    'Send Email In Loop'
,    NULL
,    @ParentTaskId
)


SELECT *
FROM #TASK

SELECT *
FROM #TASK_PARAMETERS 

SELECT *
FROM  #TASK_DETAILS

是的,您的样品有很多问题需要克服!

首先,我会给你答案,但请注意,为了正确地进行分层处理,它必须是一个递归函数,因此你提供的测试数据必须在永久表中创建,而不是临时表(更简单) 然后我会指出一些我在解决问题时使用的有用技术。

ALTER FUNCTION GetTasks (@ParentId varchar(255)= NULL) 
RETURNS
XML
BEGIN
DECLARE @ReturnXML XML

SELECT @ReturnXML = 
(
    SELECT
    (
        SELECT 
            CONVERT(XML,
                --Main task start tag
                '<'+master_t.TaskType+' Name="'+master_t.TaskName+'">'+ 
                    CONVERT(VARCHAR(MAX),
                        (

                            SELECT
                            dbo.GetTasks(master_t.TaskId),
                            (
                                SELECT 
                                    CONVERT(XML,'<'+DetailName+'>'+DetailValue+'</'+DetailName+'>')
                                FROM
                                    TASK_DETAILS t 
                                WHERE
                                    TaskId = master_t.TaskId
                                FOR XML PATH(''),Type
                            ),
                            (
                                SELECT Name,Value,Type FROM TASK_PARAMETERS t 
                                WHERE TaskId=master_t.TaskId
                                FOR XML PATH('Parameter'),Type
                            ) 'Parameters'
                            FOR XML PATH(''),Type 
                        )
                    )
                    +
                --Main task end tag
                '</'+master_t.TaskType+'>'
            )
        FROM 
            TASK master_t
        WHERE 
            --Effectively ignore the parentId field if it is not passed.
            ISNULL(ParentTaskId,'') = CASE WHEN @ParentId IS NULL THEN '' ELSE @ParentId END


        FOR XML PATH(''),Type
    ) 'TaskList'  FOR XML PATH(''),Type
) 

RETURN @ReturnXML
END
GO

像这样调用这个函数:

SELECT dbo.GetTasks(NULL)

我认为值得注意的技术是:

a) 您可以通过简单地从字符串构建 xml 节点来手动创建它们 - 如果节点名称在表中,这非常有用。您唯一需要注意的是,要在块周围放置开始和结束标记,您可能必须先将块转换为字符串,附加标记,然后将整个内容转换为 xml(零碎)不会工作,因为转换为 xml 函数希望您提供格式良好的 XML。

b) 有时您必须将内容嵌套在括号中才能实现所有子标签周围的标签... 一个例子可以让这一点更清楚:

 SELECT 
    TaskName
    FROM TASK t
    FOR XML PATH('SomeRoot')

会产生:

<SomeRoot>
  <TaskName>Get Report Parameters</TaskName>
</SomeRoot>
<SomeRoot>
  <TaskName>Loop Report Creation</TaskName>
</SomeRoot>
<SomeRoot>
  <TaskName>Report In Loop</TaskName>
</SomeRoot>
<SomeRoot>
  <TaskName>Get Email Addresses</TaskName>
</SomeRoot>
<SomeRoot>
  <TaskName>Loop Mail Creation</TaskName>
</SomeRoot>
<SomeRoot>
  <TaskName>Send Email In Loop</TaskName>
</SomeRoot>

要让“SomeRoot”出现在它周围,您可以这样做:

SELECT 
(
    SELECT 
        TaskName
    FROM TASK t
    FOR XML PATH(''),Type
) 
FOR XML PATH('SomeRoot')

如果节点名称是静态的(注意 XML PATH(''),Type,这基本上确保 XML 路径返回 XML 类型数据以供进一步处理并且不会转义它)

如果节点名称不是静态的,您就会遇到这样的问题,需要在字符串之间进行转换才能使其工作。

SELECT 
    CONVERT(XML,
        '<'+DynamicName+'>' + 
        CONVERT(VARCHAR(MAX),
                (
                    SELECT 
                        TaskName
                    FROM TASK t
                    FOR XML PATH(''),Type
                )
            ) +
            '</'+DynamicName+'>'  
    )
FROM
    (SELECT 'Test' as DynamicName) a

c)关于让不同的子标签出现在同一级别上的问题,这是非常微不足道的,您只需记住多层选择的常见问题不再是 xml 的问题,因为 xml select 只是返回一个单个 xml 对象。然后,您也可以使用 XML PATH 将这些结果合并到树中。

e.g.

SELECT 
    (SELECT top 1 * FROM TASK FOR XML PATH(''),Type),
    (SELECT top 1 * FROM TASK_DETAILS FOR XML PATH(''),Type)

将返回包含两列的单行,但如果您随后将 XML PATH('') 应用到整体,则您已将它们组合在同一级别上

SELECT 
    (SELECT top 1 * FROM TASK FOR XML PATH(''),Type),
    (SELECT top 1 * FROM TASK_DETAILS FOR XML PATH(''),Type)
FOR XML PATH('Root')    

d) 如果通过 XML PATH,列名将转换为节点。属性非常简单,您只需为列指定一个别名,该别名是适当的 xsl 路径 例如'MyNodeName\@MyAttributeName' 显然这排除了动态命名的属性。为此,在本例中,我只是再次从字符串构建了 xml。顺便说一句,这就是为什么动态节点名称是一个坏主意——您基本上允许例程通过表中的数据创建新的属性名称和节点名称...这意味着您无法为例程创建一个像样的模式,因为您事先不知道表中可能有哪些数据......

继续 :)

因此,考虑到这些构建块,最简单的事情就是从最深层开始工作,逐块构建它,然后像上面那样组合。

我为你的查询做了这个,最终意识到,为了让它按层次结构(即n个嵌套级别)工作,我必须编写一个返回XML的函数,这被称为将父节点传递给它(以便该函数知道要做什么)将结果集过滤为)。如果你的等级制度结构不正确并且是循环的,那么这将是一个可怕的死亡。

好的——希望里面有你可以使用的东西。这纯粹是面向 XML PATH() 的解决方案 - 有其他 XML 方法在不同情况下很有用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有不同子项的 Sql XML 路径 的相关文章

  • PostgreSQL WHERE 计数条件

    我在 PostgreSQL 中有以下查询 SELECT COUNT a log id AS overall count FROM Log as a License as b WHERE a license id 7 AND a licens
  • Postgres 按查询分组

    我正在尝试在 postgres 的查询中使用 group by 我无法让它按照我想要的方式工作 以便根据需要对结果进行分组 这是另一个堆栈问题的扩展我刚刚回答过的递归查询 https stackoverflow com questions
  • 如何重置 SQL Server 中表的 IDENTITY 列? [复制]

    这个问题在这里已经有答案了 我怎样才能重置我的IDENTITY我已经填充的表中的列 我尝试过类似的方法 但它不起作用 WITH TBL AS SELECT ROW NUMBER OVER ORDER BY profile id AS RN
  • 如何统计订单总价?

    我有这些表 Orders id status user id address id 1 await 1 1 products id name price quantity 1 test1 100 5 2 test2 50 5 order p
  • 获取 SQL 表上的某些百分位值

    假设我有一个表 其中存储用户 他们拥有的红球数量 球总数 蓝色 黄色 其他颜色等 以及红球与球总数的比率 架构如下所示 user id ratio red balls total balls 1 2 2 10 2 3 6 20 我想根据排序
  • 如何获取 GROUP_BY 子句中的值列表?

    如果我的表中有这样的数据 id data 1 1 1 2 1 3 2 4 2 5 3 6 3 4 如何在查询 在 sybase 服务器上 中获得这样的结果 id data 1 1 2 3 2 4 5 3 6 4 在mysql中 使用 SEL
  • 这个 SQL 语句在 Linq 中的等价物是什么?

    我需要将此 SQL 语句移植到 LINQ SELECT f ID as IdFlight Tarif 1 as Tarif f Time f TimeOfArrival sl Name as FromLoc sl Country as Fr
  • Mysql UUID_SHORT() 与 UUID() 相当吗

    如果您愿意的话 请快速提出问题或意见 我需要为数据库表生成一些 UUID 自动递增密钥不会减少它 因为我还需要密钥在数据库和系统中保持唯一 UUID 工作正常 但其输出对于行将导出到的某些系统来说太长 UUID SHORT 做得很好 我已经
  • 使用 C# 和 ADO.NET SET NOCOUNT ON 并读取消息

    SET NOCOUNT ON 会阻止显示受 Transact SQL 语句或存储过程影响的行数的消息作为结果集的一部分返回 a 如何使用 C 和 ADO NET 读取这些消息 我假设读取这些消息的 C 代码是相同的 无论 T SQL 语句是
  • 在sql server中生成下一个序列号

    我需要生成一个序列号用作主键 在遗留系统中 我想知道以下解决方案在竞争条件下是否会遇到并发问题 CREATE TABLE SequenceGenerator Sequence INT INSERT INTO SequenceGenerato
  • SQLAlchemy:检查给定值是否在列表中

    问题 在 PostgreSQL 中 检查某个字段是否在给定列表中是使用IN操作员 SELECT FROM stars WHERE star type IN Nova Planet SQLAlchemy 的等价物是什么INSQL查询 我尝试过
  • 如何在oracle中预测和转义单引号'

    假设我有一个列值aaa gh它会在 oracle 中抛出错误 提示 sql 命令未正确结束 我的问题是如果我不知道有多少 在我的价值范围内 我如何才能安全地逃脱它们 最好的方法是使用引用字符串文字技术 http lalitkumarb wo
  • 是否值得为 SqlServer 查找表使用tinyint 而不是 int 呢?

    在 SqlServer 2005 中设计查找表 枚举 时 如果您知道条目数永远不会变得很高 是否应该使用tinyint 而不是 int 我最关心的是性能 尤其是索引的效率 假设您有这些代表性表格 Person PersonId int PK
  • 为什么没有主键的表是一个坏主意?

    我对数据建模非常陌生 根据微软的实体框架 不允许使用没有主键的表 这显然是一个坏主意 我试图找出为什么这是一个坏主意 以及如何修复我的模型 这样我就不会出现这个漏洞 我当前的模型中有 4 个表 User City HelloCity 和 R
  • 将查询结果作为 CSV 文件从 Docker PostgreSQL 容器导出到本地计算机

    我不确定这是否可能 或者我是否做错了什么 因为我对 Docker 还很陌生 基本上 我想将 PostgreSQL docker 容器内的查询结果作为 csv 文件导出到本地计算机 这就是我到目前为止所得到的 首先 我使用以下命令运行 Pos
  • 如何在嵌套集中查找特定 level2 节点的特定子节点

    我有一个标准的嵌套集模型 每个节点都有 name lft 和 rgt 属性 我可以使用以下方法找到特定员工的上级 SELECT P2 FROM Personnel AS P1 Personnel AS P2 WHERE P1 lft BET
  • 将数据类型 varchar 转换为 int 时出错

    我试图使用基于 varchar 类型的 Name 列的输入值的存储过程返回 item 表的 ItemId 列值 但是每当我将任何值传递给存储过程时 它都会返回一个错误 将数据类型 varchar 转换为 int 时出错 create pro
  • 两个表中两个字段的总和

    我的数据库中有四个表 如下所示 表格发票 invcid customerid invoicedate tblInvc详细信息 ID invcid item itemprice itemquantity tblPay payid invcid
  • 如何使用JSqlParser向sql添加where条件?

    我想用JSqlParser向sql添加where条件 例如 Before select from test table where a 1 group by c After select from test table where a 1
  • SQL - 每个级别都有记录的递归树层次结构

    尝试使用 SAS 据我所知 不支持WITH RECURSIVE 在 SQL 中创建经典的层次结构树 这是现有表中的简化数据结构 USER ID SUPERVISOR ID 因此 要构建层次结构 您只需递归连接 x 次即可获取您要查找的数据

随机推荐

  • Nuxt:仅在服务器端获取数据

    我使用 Github 的 API 来获取固定存储库的列表 并将调用放入 AsyncData 方法中 以便在第一次渲染时获得该列表 但我刚刚了解到 AsyncData 在服务器端调用一次 然后每次在客户端加载页面时调用 这意味着客户端不再拥有
  • X.509 证书中的专有名称长度限制

    在通用名称字段中 如 OID 2 5 4 3 的 ASN 1 表示法中所定义 限制最多为 64 个字符 如果我们想要一个超过 64 个字符的通用名 有什么办法吗 即使你可以哄骗你的证书生成代码拥有更长的 CN 它也是clients这需要改变
  • 根据字符串生成UUID

    如何在 C 中生成确定性 GUID UUID v3 v5 将命名空间和名称都作为字符串 根据 RFC4122 您需要提供命名空间作为 GUID 名称作为字符串 提供给函数 所以我想提供两个字符串而不是 guid对于命名空间和名称字符串 并且
  • 升级到 Notes 11 - Apache POI java 库的问题

    我们在 Domino 9 服务器上运行的多个 Xpages 应用程序中使用 Apache POI 库 现在 当将 HCL Notes Designer 升级到 R11 时 我们可以看到 Apache POI 在版本 4 1 1 的 jvm
  • Parent Last Classloader 解决Java类路径地狱?

    我有一个项目使用两个版本的 bouncyCastle jars bcprov jdk15 和 bcprov jdk16 jvm 加载旧版本 但我编写的一个功能需要更新版本才能运行 我尝试使用自定义类加载器来解决这个类路径地狱 经过一番谷歌搜
  • 从 OpenAPI 3 生成 Java Spring API

    我尝试从 OpenAPI v3 YAML 文件生成 Spring REST 接口 构建 说 Successfully generated code to property class java lang String property cl
  • 无法在 Beta 5 中将 Swift 字典写入 NSUserDefaults

    我一直在开发一个应用程序 在该应用程序中我使用 NSUserDefaults 来保存字典以在程序的其他地方使用 自 Beta 1 以来 此功能一直运行良好 现在 随着最新的更新 beta 5 此功能不再有效 看来他们已经消除了以这种方式保存
  • 仍然是 Python 2.6 与 Python 3 吗?

    G day 我想在一段时间没有使用Python后回到Python 我看到了这个问题 适合新手的 Python 版本 https stackoverflow com questions 345255 python version for a
  • 如何使用 Spring security 更新过滤器的标头参数?

    我正在使用 Spring security 开发一个过滤器extends of OncePerRequestFilter类 它必须更新 REST 服务中的参数 参数由带有注释的标头输入 RequestHeader 我尝试使用以下类更新过滤器
  • 在 python3 中绘图(直方图)

    我正在尝试根据一系列成绩创建直方图 所有等级均为可能的 7 级 3 0 2 4 7 10 12 之一 我使用下面的代码来生成绘图 但是我无法找到一种方法将 x 轴标签放在条形图的中间 删除绘图中间的空间 或者在条形图之间放置一个小空间 im
  • 我可以让 Heroku Logs 仅返回概述错误的行吗?

    Heroku 日志是一个很好的资源 可以在出现问题时检查应用程序发生了什么情况 不幸的是 它们还记录了大量信息 有什么方法可以过滤日志以仅查找错误消息吗 尝试这个 heroku logs t grep error 获取错误发生时的运行列表
  • 我有 30 个注释,并且还在不断增加。正在寻找一种更简单的方法来编码吗?

    我正在将多个注释编码到一个项目中 目前我有 30 个注释 并且还在不断增加 我想知道是否有一种更简单的方法必须为每个注释创建 annotation h 和 annotation m 类 目前在我的地图视图控制器中 我创建注释对象并将它们放置
  • 如何使用 matlab 查找矩阵中唯一(不重复)的值

    每个人 假设我有以下 3x3 矩阵 A 0 1 3 0 0 3 0 0 0 我的问题是如何使用matlab找出该矩阵中的唯一值 在这种情况下 结果应该是 1 我尝试过使用 value unique A 但它返回的向量 0 1 3 不是我想要
  • CKAN 中的修订历史

    CKAN 是否提供数据集的修订历史记录 我看到一个表和一个 API 调用 但在修改数据集或元数据字段时 我在 UI 和 或数据库中看不到任何内容 编辑数据集的标题 您将看到包含添加到 package revision 表中的新值的行 然而
  • ASP.NET / iPad Safari 缓存问题?

    我们有一个使用 ASP NET Ajax 的 ASP NET Web 应用程序 我们从 iPad 上的 Safari 中打开它 效果很好 我们将其作为单独的图标保存到主屏幕上 我们添加了元标记 使其能够全屏加载 无需 Safari 的导航栏
  • C中不完整类型和对象类型的定义是什么?

    的定义是什么不完整型 and 对象类型在C语言中 另外 您能否提供一些例子 ANSI C99 在不同的地方提到了这两种类型类别 尽管我发现很难理解它们的确切含义 没有段落 句子明确定义它们是什么 让我们去在线 C 标准 草案 n1256 h
  • 如何查找 iPhone 应用程序 CPU 使用率 100% 的原因

    我在一个应用程序中诊断出一个奇怪的行为 大约 10 分钟后 CPU 使用率达到 100 应用程序中没有泄漏 并且它发生在应用程序不执行任何操作时 我可以使用 时间分析器 通过仪器对此进行分析 但是有没有办法找到实际原因是什么 使用 Inst
  • 如何在类路径中运行带有 jar 的 java 类?

    所以 我可以很好地做到这一点 java mypackage MyClass if mypackage MyClass class存在 我也可以愉快地这样做 java cp myjar jar mypackage MyClass 类文件是否存
  • NSMutableArray 和 NSPredicate 过滤

    我正在尝试使用对象中的两个实体来过滤我的数组 就像我有一个 Person 对象 其中有姓名 地 址 号码 电子邮件等 我正在尝试仅使用名称和号码来过滤我的对象数组列表 如何使用 NSPredicate 来实现这一点 创建谓词 以下假设您的P
  • 具有不同子项的 Sql XML 路径

    我已经完成了很多 XML PATH 语句 但这个语句我却忽略了 或者对于多个不同的子项来说甚至可能是不可能的 最终结果应该是这样的