Sql server 从sql列中的xml提取值和属性

Sql server 从sql列中的xml提取值和属性,sql-server,xml,Sql Server,Xml,我正在处理一个Microsoft SQL Server表,该表包含多个数据类型,包括一个xml列。例如: CREATE TABLE [sites] ( [site_id] [int] NOT NULL, [organization_id] [int] NULL, [site_creationDate] [datetime] NULL, [site_active] [bit] NULL, [site_activatedBy] [varchar](20) NU

我正在处理一个Microsoft SQL Server表,该表包含多个数据类型,包括一个xml列。例如:

CREATE TABLE [sites]
(
    [site_id] [int] NOT NULL,
    [organization_id] [int] NULL,
    [site_creationDate] [datetime] NULL,
    [site_active] [bit] NULL,
    [site_activatedBy] [varchar](20) NULL,
    [contentModel_id] [int] NULL,
    [site_settings] [xml] NULL
);
以下是
[site\u settings]
列中XML的外观:

例1:

<settings>
  <s key="hasinventorynotifier" value="0" type="BIT" />
  <s key="displayinstocknotifier" value="1" type="BIT" />
  <s key="usesimplequoteform" type="BIT" value="1" />
</settings>
我在下面的这些查询中尝试了几种通过选择列的值进行提取的方法,但是结果返回NULL或空白

SELECT 
    [site_settings].value('usesimplequoteform[1]','bit') AS Test1,
    [site_settings].value('settings[1]','varchar(10)') AS Test2,
    [site_settings].value('(s[@key="usesimplequoteform"]/@value)[1]','int') AS Test3
FROM
    [sites]
或者,我的一位同事建议使用以下案例陈述,这确实有效,但我想知道是否有更好的方法。下面的例子:

SELECT 
    CASE WHEN CHARINDEX('usesimplequoteform" type="Bit" value="1"',CONVERT(VARCHAR(MAX),site_settings),1) > 0 THEN 1 
            WHEN CHARINDEX('usesimplequoteform" value="1" type="Bit"',CONVERT(VARCHAR(MAX),site_settings),1) > 0 THEN 1
            ELSE 0 
       END AS useSimpleQuoteForm
FROM [sites]
但是有谁有更好的方法吗?上面的示例仅适用于位变量,其中一些类型为string(varchar)。任何帮助都将不胜感激


输出澄清

基本上,输出将是一个视图,其中包含表[sites]中的所有当前列以及[sites].[site_settings]列中每个键的附加列

[site_id]   [organization_id]   [site_creationDate] [site_active]   [site_activatedBy]  [contentModel_id]   [hasinventorynotifier]  [displayinstocknotifier]    [usesimplequoteform]    [the keys etc in xml]
5036            4886            2016-01-04 10:16:01.860     1           system              8                       1                           0                           1               (value)
5037            2386            2015-01-05 11:29:23.880     1           system              2                       0                           0                           1               (value)

这是一种按原样获取所有值的方法:

您的XML文件:

DECLARE @xml XML=
'<settings>
  <s key="isvisionimpaired" type="Bit" value="0" />
  <s key="insurancerequesturl" type="String" value="" />
  <s key="haswheelstudio" type="Bit" value="0" />
</settings>'

SELECT a.b.value('@key','varchar(max)') AS s_key
      ,a.b.value('@type','varchar(max)') AS s_type
      ,a.b.value('@value','varchar(max)') AS s_value
FROM @xml.nodes('settings/s') AS a(b);
在这种情况下,缺少的值将返回空值

优点:您可以指定正确的数据类型并使用“说话”列名称(在您的情况下,可能是键的名称)

第三种方法可能是动态SQL,您可以使用XML中的所有信息生成语句,以生成与我上面所做的完全相同的语句。这样可以动态指定列名和数据类型

最后,您需要一个
EXEC
,这样就不可能在视图等特殊查询中集成这种方法

编辑:这应该是您需要的: 根据你的评论

SELECT *
      ,[site_settings].value('(/settings/s[@key="isvisionimpaired"]/@value)[1]','bit') AS isvisionimpaired
      ,[site_settings].value('(/settings/s[@key="insurancerequesturl"]/@value)[1]','varchar(max)') AS insurancerequesturl
      ,[site_settings].value('(/settings/s[@key="haswheelstudio"]/@value)[1]','bit') AS haswheelstudio
      --all possible data here
FROM [sites]

您好,请说明您期望的输出…我添加了一个输出示例。。。基本上,返回所有普通列,但也返回从xml列提取的键值。不过我还是要看看你最近的答案,谢谢!Thx用于输出示例。由于需要将所有列并排放在一行中,因此必须使用我作为第二行使用的方法。看到我编辑的答案了吗?非常感谢!您的第二个代码块示例就是我正在寻找的代码块!我想我真的很接近我的“测试3”专栏的例子,但你为我找到了答案。谢谢@很高兴读到这篇文章!如果您需要关于解码JSON部分的帮助,请提出另一个问题并将链接发到此处。快乐编码@Namkce,是的,你的“测试3”非常接近。只有“/settings/”丢失。。。
DECLARE @xml XML=
'<settings>
  <s key="isvisionimpaired" type="Bit" value="0" />
  <s key="insurancerequesturl" type="String" value="" />
  <s key="haswheelstudio" type="Bit" value="0" />
</settings>'

SELECT a.b.value('@key','varchar(max)') AS s_key
      ,a.b.value('@type','varchar(max)') AS s_type
      ,a.b.value('@value','varchar(max)') AS s_value
FROM @xml.nodes('settings/s') AS a(b);
SELECT @xml.value('(/settings/s[@key="isvisionimpaired"]/@value)[1]','bit') AS isvisionimpaired
      ,@xml.value('(/settings/s[@key="insurancerequesturl"]/@value)[1]','varchar(max)') AS insurancerequesturl
      ,@xml.value('(/settings/s[@key="haswheelstudio"]/@value)[1]','bit') AS haswheelstudio
      --all possible data here
SELECT *
      ,[site_settings].value('(/settings/s[@key="isvisionimpaired"]/@value)[1]','bit') AS isvisionimpaired
      ,[site_settings].value('(/settings/s[@key="insurancerequesturl"]/@value)[1]','varchar(max)') AS insurancerequesturl
      ,[site_settings].value('(/settings/s[@key="haswheelstudio"]/@value)[1]','bit') AS haswheelstudio
      --all possible data here
FROM [sites]