用于 SQL 帮助的 XQUERY()

XQUERY() for SQL Assistance

提问人:Mandy 提问时间:10/14/2023 最后编辑:Yitzhak KhabinskyMandy 更新时间:10/18/2023 访问量:54

问:

我有一个以XML格式存储数据的表。我需要从两个节点获取数据。

示例脚本:

select MARKUP_MESSAGE  
from TABLE_NAME 
where row_uno = 6599064

示例结果:

<PrebillMarkup xmlns="clr-namespace:Aderant.Query.ViewModels;assembly=Aderant.Query" 
               xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">    
    <PrebillMarkup.NewValues>      
        <x:String x:Key="Narrative" xml:space="preserve">Review of policies against previous policies</x:String>    
    </PrebillMarkup.NewValues>    
    <PrebillMarkup.OriginalValues>      
        <x:String x:Key="Narrative" xml:space="preserve">Review of policies against previous policies sdffddgsgfdfdg</x:String>    
    </PrebillMarkup.OriginalValues>  
</PrebillMarkup>

我有两个节点和.<PrebillMarkup.NewValues><PrebillMarkup.OriginalValues>

我希望能够从“查看附加策略 - 测试”中取出“查看其他策略 - 测试”x:String<PrebillMarkup.NewValues>

因此,当我运行语句时:

select MARKUP_MESSAGE  
from TABLE_NAME 
where row_uno = 6599064

结果将是“审查其他策略 - 测试”

或者,如果我执行另一个查询以提取

<x:String x:Key="Narrative" xml:space="preserve">

关于如何做到这一点的任何想法,因为每次我尝试时,我都会获得更多的XML数据,但我只需要纯文本。

谢谢大家

SQL版本:

Microsoft SQL Server 2019 - 15.0.4280.7 (X64)   
Standard Edition (64-bit) on Windows Server 2019 Standard 10.0 <X64>
sql sql-server xml xquery

评论

1赞 Thom A 10/14/2023
这些尝试是什么?你忘了包括它们。似乎您只需要声明您的命名空间,就可以使用 和 方法获取数据。nodesvalue
0赞 Yitzhak Khabinsky 10/15/2023
在提出问题时,您需要提供一个最小的可重现示例:(1) DDL 和示例数据填充,即 CREATE 表和 INSERT T-SQL 语句。(2) 需要执行的操作,即逻辑和代码尝试在 T-SQL 中实现它。(3) 期望的输出,基于上面 #1 中的示例数据。(4) 您的 SQL Server 版本 (SELECT @@version;)。

答:

0赞 marc_s 10/14/2023 #1

不确定我是否完全理解您想做什么 - 但这里有一种可能的方法:

-- define table - here, for simplicity's sake, just a table variable
DECLARE @table_name TABLE 
                    (
                        ID INT NOT NULL,
                        Markup_Message XML
                    )

-- insert data into table
INSERT INTO @table_name (ID, Markup_Message)
VALUES (1, '<PrebillMarkup xmlns="clr-namespace:Aderant.Query.ViewModels;assembly=Aderant.Query" 
               xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">    
    <PrebillMarkup.NewValues>      
        <x:String x:Key="Narrative" xml:space="preserve">Review of policies against previous policies</x:String>    
    </PrebillMarkup.NewValues>    
    <PrebillMarkup.OriginalValues>      
        <x:String x:Key="Narrative" xml:space="preserve">Review of policies against previous policies sdffddgsgfdfdg</x:String>    
    </PrebillMarkup.OriginalValues>  
</PrebillMarkup>');

-- query the data, using XQuery, to extract the "x:String" 
-- from the <PrebillMarkup.NewValues> node
--
-- IMPORTANT: you need to respect and include the XML Namespaces
-- defined in your XML document into your query!
--
WITH XMLNAMESPACES(DEFAULT 'clr-namespace:Aderant.Query.ViewModels;assembly=Aderant.Query',
                   'http://schemas.microsoft.com/winfx/2006/xaml' AS x)
SELECT
    Markup_Message.value('(/PrebillMarkup/PrebillMarkup.NewValues/x:String/text())[1]', 'varchar(500)')
FROM
    @table_name
WHERE
    ID = 1;

运行这个,我得到的结果:

(no column name)
----------------------------------------------
Review of policies against previous policies

评论

0赞 Mandy 10/18/2023
谢谢marc_s,这也是一个不错的选择。
1赞 Yitzhak Khabinsky 10/15/2023 #2

没有提供最小的可重现示例。所以,我从臀部射击。

正如@ThomA已经指出的那样,您需要声明和使用命名空间。

XQuery 和方法负责将 XML 粉碎为矩形/关系格式。.nodes().value()

SQL算法

-- DDL and sample data population, start
DECLARE @tbl TABLE (row_uno INT IDENTITY PRIMARY KEY, Markup_Message XML);
INSERT @tbl (Markup_Message) VALUES
(N'<PrebillMarkup xmlns="clr-namespace:Aderant.Query.ViewModels;assembly=Aderant.Query"
               xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <PrebillMarkup.NewValues>
        <x:String x:Key="Narrative" xml:space="preserve">Review of policies against previous policies</x:String>
    </PrebillMarkup.NewValues>
    <PrebillMarkup.OriginalValues>
        <x:String x:Key="Narrative" xml:space="preserve">Review of policies against previous policies sdffddgsgfdfdg</x:String>
    </PrebillMarkup.OriginalValues>
</PrebillMarkup>');
-- DDL and sample data population, end

WITH XMLNAMESPACES(DEFAULT 'clr-namespace:Aderant.Query.ViewModels;assembly=Aderant.Query',
                   'http://schemas.microsoft.com/winfx/2006/xaml' AS x)
SELECT t.row_uno
    , c.value('local-name(.)', 'VARCHAR(128)') AS element_name
    , c.value('(x:String/@x:Key)[1]', 'VARCHAR(128)') AS attribute_key
    , c.value('(x:String/text())[1]', 'VARCHAR(128)') AS string_value
FROM @tbl AS t
CROSS APPLY Markup_Message.nodes('/PrebillMarkup/*') AS t1(c)
WHERE row_uno = 1;

输出

row_uno element_name attribute_key string_value
1 PrebillMarkup.NewValues 叙事 根据以前的政策审查政策
1 PrebillMarkup.OriginalValues 叙事 根据以前的政策审查政策 sdffddgsgfdfdg

评论

0赞 Mandy 10/18/2023
这正是我要找的。通常,我会为一个账单号拉出这个,可能有 30 多行markup_message行。我现在已经设法添加了其余的编辑,将其弹出到存储过程中,然后将字符串拉到税务发票上。非常感谢,你为我节省了很多时间。