【问题标题】:How can I parse XML from database field?如何从数据库字段解析 XML?
【发布时间】:2021-05-07 04:15:17
【问题描述】:

使用以下 XML。

<TEMPLATE>
<TEMPLATE_FIELD prompt="TEST_ONE" data_type="8" tag="TEST_ONE" required="0" is_radio="0" default_value="" SQL="SELECT * FROM DBO.SOME_NEW_TEST" />
<TEMPLATE_FIELD prompt="TEST_TWO" data_type="8" tag="TEST_TWO" required="0" is_radio="0" default_value="" SQL="SELECT * FROM DBO.SOME_NEW_TEST" />
<TEMPLATE_FIELD prompt="TEST_THREE" data_type="8" tag="TEST_THREE" required="0" is_radio="0" default_value="" SQL="SELECT * FROM DBO.SOME_NEW_TEST" />

我正在尝试获取以下内容 - 或类似的内容,以便我可以有效地阅读这些字段。

我尝试了其他几个问题,发现这个问题的第三个答案很有希望https://stackoverflow.com/a/15349737/8715626 --因为我希望能够在 SQL 中进行解析,而不是使用外部语言或创建文件。如果创建文件更容易,请随时分享。我已经尝试了下面代码的几种变体,我得到的是“空白”或 NULL。

declare @xml as xml
set @xml = (SELECT xml_field from fooXMLtable)

select @xml

;with cte as (    
  select @xml xmlstring
)
SELECT 
xmlstring.value('(/TEMPLATE//TEMPLATE_FIELD/prompt/node())[3]','VARCHAR(max)')
as prompt

【问题讨论】:

  • 在提出问题时,您需要提供一个可重现的最小示例。请参考以下链接:stackoverflow.com/help/minimal-reproducible-example 请提供以下内容: (1) DDL 和样本数据填充,即 CREATE table(s) 加上 INSERT T-SQL 语句。 (2) 你需要做什么,即逻辑和你的代码尝试在 T-SQL 中实现它。 (3) 期望的输出,基于上面#1 中的样本数据。 (4) 你的 SQL Server 版本 (SELECT @@version;)
  • Nahuatl_C137,您显然没有阅读您接受为答案的解决方案的评论。

标签: sql sql-server xml xquery


【解决方案1】:

请尝试以下解决方案。

这是一个最小的可重现示例。您可以将其原样复制到 SSMS、运行它并探索它的作用。

它正在使用 XQuery 及其方法:.nodes().value()

无需使用临时 T-SQL 变量 @xml 作为 XML 数据占位符。

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, xmldata XML);
INSERT INTO @tbl (xmldata) VALUES
(N'<TEMPLATE>
    <TEMPLATE_FIELD prompt="TEST_ONE" data_type="8" tag="TEST_ONE" required="0"
                    is_radio="0" default_value=""
                    SQL="SELECT * FROM DBO.SOME_NEW_TEST"/>
    <TEMPLATE_FIELD prompt="TEST_TWO" data_type="8" tag="TEST_TWO" required="0"
                    is_radio="0" default_value=""
                    SQL="SELECT * FROM DBO.SOME_NEW_TEST"/>
    <TEMPLATE_FIELD prompt="TEST_THREE" data_type="8" tag="TEST_THREE"
                    required="0" is_radio="0" default_value=""
                    SQL="SELECT * FROM DBO.SOME_NEW_TEST"/>
</TEMPLATE>');
-- DDL and sample data population, end

SELECT ID 
    , c.value('@prompt', 'VARCHAR(30)') AS prompt
    , c.value('@data_type', 'INT') AS data_type
    , c.value('@tag', 'VARCHAR(30)') AS tag
    , c.value('@required', 'INT') AS [required]
    , c.value('@is_radio', 'INT') AS [is_radio]
    , c.value('@default_value', 'VARCHAR(30)') AS default_value
    , c.value('@SQL', 'VARCHAR(MAX)') AS [SQL]
FROM @tbl CROSS APPLY xmldata.nodes('/TEMPLATE/TEMPLATE_FIELD') AS t(c);

输出

+----+------------+-----------+------------+----------+----------+---------------+---------------------------------+
| ID |   prompt   | data_type |    tag     | required | is_radio | default_value |               SQL               |
+----+------------+-----------+------------+----------+----------+---------------+---------------------------------+
|  1 | TEST_ONE   |         8 | TEST_ONE   |        0 |        0 |               | SELECT * FROM DBO.SOME_NEW_TEST |
|  1 | TEST_TWO   |         8 | TEST_TWO   |        0 |        0 |               | SELECT * FROM DBO.SOME_NEW_TEST |
|  1 | TEST_THREE |         8 | TEST_THREE |        0 |        0 |               | SELECT * FROM DBO.SOME_NEW_TEST |
+----+------------+-----------+------------+----------+----------+---------------+---------------------------------+

【讨论】:

    【解决方案2】:

    如果您使用的是 MSSQL,这应该可以:

    DECLARE @xml XML = '<TEMPLATE>
    <TEMPLATE_FIELD prompt="TEST_ONE" data_type="8" tag="TEST_ONE" required="0" is_radio="0" default_value="" SQL="SELECT * FROM DBO.SOME_NEW_TEST" />
    <TEMPLATE_FIELD prompt="TEST_TWO" data_type="8" tag="TEST_TWO" required="0" is_radio="0" default_value="" SQL="SELECT * FROM DBO.SOME_NEW_TEST" />
    <TEMPLATE_FIELD prompt="TEST_THREE" data_type="8" tag="TEST_THREE" required="0" is_radio="0" default_value="" SQL="SELECT * FROM DBO.SOME_NEW_TEST" />
    </TEMPLATE>'
    
    SELECT 
        T.C.value('./@prompt', 'nvarchar(50)') as Prompt,
        T.C.value('./@data_type', 'int') as DataType,
        T.C.value('./@tag', 'nvarchar(50)') as Tag,
        T.C.value('./@required', 'bit') as Required,
        T.C.value('./@is_radio', 'bit') as IsRadio,
        T.C.value('./@default_value', 'nvarchar(max)') as DefaultValue,
        T.C.value('./@SQL', 'nvarchar(max)') as Query
    FROM   @xml.nodes('/TEMPLATE/TEMPLATE_FIELD') T(C)  
    

    【讨论】:

    • (1) 在.nodes() 方法XPath 表达式中使用// 效率低下。它导致遍历整个 XML。 (2) OP XML在DB表中,不在变量中。
    • 你的答案更好:-)
    【解决方案3】:

    首先nodes()TEMPLATE_FIELD 元素放在一个表中,然后使用value() 从该表中进行选择以从属性中获取值。

    SELECT tf.value('@prompt', 'varchar(MAX)') prompt,
           tf.value('@data_type', 'integer') data_type,
           ...
           FROM @xml.nodes('/TEMPLATE/TEMPLATE_FIELD') tf
                                                       (tf);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-25
      • 2020-06-03
      • 2017-12-15
      相关资源
      最近更新 更多