XQuery SQL Server NVARCHAR列

时间:2019-07-17 09:29:50

标签: xml tsql nvarchar xquery-sql

我有一个带有nvarchar列的表,该表存储XML。我正在尝试查找所有具有特定节点为空的行

这是表JOB的结构:

ID           NVARCAHR(64)
NAME         NVARCAHR(128) 
ExtraInfo    NVARCAHR(MAX)

这里是ExtraInfo列内容的样本,我在寻找:

<ModifyMetadata>
    <hostName t="ws">host2</hostName>
    <Name t="ws">myname</Name>
    <modifiedFields t="lt">
        <ExtraInfoAdditionalField>
            <FieldName t="ws">foo</FieldName>
            <Values t="lws">
                <s/>
            </Values>
            <FieldType t="ws">String</FieldType>
        </ExtraInfoAdditionalField>
        <ExtraInfoAdditionalField>
            <FieldName t="ws">bar</FieldName>
            <Values t="lws">
                <s/>
            </Values>
            <FieldType t="ws">String</FieldType>
        </ExtraInfoAdditionalField>
        </modifiedFields>
</ModifyMetadata>

基本上,通过此示例,我正在寻找节点ModifyMetadata的所有行以及节点ExtraInfoAdditionalField\Values为空的行(这是我对<s/>的理解)。

首先,我尝试使用简单的LIKE进行以下查询:

SELECT *  
FROM [JOB]
WHERE ExtraInfo LIKE '%\>\<\/s\>%' ESCAPE '\' 

但是此查询还返回行,其中节点ExtraInfoAdditionalField\Values具有一些内容。

XQuery方式:我尝试使用另一种方法将列CAST转换为XML,然后仅返回节点ExtraInfoAdditionalField\Values为空的行。

但是随后,我对于使用XQuery或任何其他可用方法查询此列的方法感到困惑。

我尝试直接在CASTSELECT

SELECT CAST(ExtraInfo AS XML)
FROM [JOB]
WHERE ExtraInfo.value('XQUERYHERE') IS NULL

但是SQL Server不知道ExtraInfo. value是什么。

我试图在变量中CAST

DECLARE @ExtraInfo XML
SET @ExtraInfo = CAST([MYDB].[dbo].[JOB].ExtraInfo AS XML)

SELECT ExtraInfo 
FROM [JOB]
WHERE @ExtraInfo.value('XQUERYHERE') IS NULL

但是SQL无法理解什么是[MYDB].[dbo].[JOB].ExtraInfo

我尝试直接在CASTSELECT并将其重命名:

SELECT CAST(ExtraInfo AS XML) as myinfo
FROM [JOB]
WHERE myinfo.value('XQUERYHERE') IS NULL

但是T-SQL不知道myinfo是什么。

因此,我显然缺乏对以哪种方式XML查询以NVARCHAR格式存储的列的可能性

我希望我已经足够清楚了,在此先感谢您的投入

2 个答案:

答案 0 :(得分:1)

您没有尝试过的是显而易见的解决方案-将ExtraInfo列强制转换为xml子句中的where

SELECT Id, [Name], ExtraInfo 
FROM [JOB]
WHERE CAST(ExtraInfo as xml).value('XQUERYHERE') IS NULL

答案 1 :(得分:0)

这个答案来得很晚,所以我不知道你是否仍然需要这个...

首先:将XML存储为VARCHAR(MAX)是一个坏主意。如果可以更改此设置,则应使用本机XML数据类型。

但是,重要的是要知道,XML不知道NULL(嗯,有xsi:nil,但这又是另一回事),但是它知道缺少元素 >(在T-SQL中已翻译NULL)和空元素,您可以使用empty(SomeXPathHere)进行查询,反之亦然-{ {1}}。

您没有说明预期的输出,因此我将提供几种方法,希望其中包括您需要的一种方法:

not(empty(SomeXPathHere))

-返回至少在DECLARE @YourTable TABLE(ID NVARCHAR(64), [NAME] NVARCHAR(128), ExtraInfo NVARCHAR(MAX)); INSERT INTO @YourTable VALUES ('id1','both without', N'<ModifyMetadata> <hostName t="ws">host2</hostName> <Name t="ws">myname</Name> <modifiedFields t="lt"> <ExtraInfoAdditionalField> <FieldName t="ws">foo</FieldName> <Values t="lws"> <s/> </Values> <FieldType t="ws">String</FieldType> </ExtraInfoAdditionalField> <ExtraInfoAdditionalField> <FieldName t="ws">bar</FieldName> <Values t="lws"> <s/> </Values> <FieldType t="ws">String</FieldType> </ExtraInfoAdditionalField> </modifiedFields> </ModifyMetadata>') ,('id2','one with and one without content', N'<ModifyMetadata> <hostName t="ws">host2</hostName> <Name t="ws">myname</Name> <modifiedFields t="lt"> <ExtraInfoAdditionalField> <FieldName t="ws">foo</FieldName> <Values t="lws"> <s>SomeValueHere</s> </Values> <FieldType t="ws">String</FieldType> </ExtraInfoAdditionalField> <ExtraInfoAdditionalField> <FieldName t="ws">bar</FieldName> <Values t="lws"> <s/> <!-- No value here --> </Values> <FieldType t="ws">String</FieldType> </ExtraInfoAdditionalField> </modifiedFields> </ModifyMetadata>') ,('id2','both with content', N'<ModifyMetadata> <hostName t="ws">host2</hostName> <Name t="ws">myname</Name> <modifiedFields t="lt"> <ExtraInfoAdditionalField> <FieldName t="ws">foo</FieldName> <Values t="lws"> <s>SomeValueHere</s> </Values> <FieldType t="ws">String</FieldType> </ExtraInfoAdditionalField> <ExtraInfoAdditionalField> <FieldName t="ws">bar</FieldName> <Values t="lws"> <s>And here too</s> </Values> <FieldType t="ws">String</FieldType> </ExtraInfoAdditionalField> </modifiedFields> </ModifyMetadata>'); 上为空的所有行

<s>

-如果SELECT t.ID ,t.[NAME] ,Casted FROM @YourTable t CROSS APPLY (SELECT CAST(t.ExtraInfo AS XML)) A(Casted) WHERE Casted.exist('/ModifyMetadata/modifiedFields/ExtraInfoAdditionalField[empty(Values/s/text())]')=1 为空,则返回所有字段的列表(每个字段作为单独的行)

<s>

-这将返回所有字段的列表(每个字段作为单独的行),并且如果SELECT t.ID ,t.[NAME] ,B.dt.value('(text())[1]','nvarchar(max)') FieldWithNonEmpty_s ,B.dt.query('.') TheNode FROM @YourTable t CROSS APPLY (SELECT CAST(t.ExtraInfo AS XML)) A(Casted) CROSS APPLY Casted.nodes('/ModifyMetadata/modifiedFields/ExtraInfoAdditionalField[empty(Values/s/text())]/FieldName') B(dt) 为空,则将携带NULL

<s>