我有一个带有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或任何其他可用方法查询此列的方法感到困惑。
我尝试直接在CAST
中SELECT
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
我尝试直接在CAST
中SELECT
并将其重命名:
SELECT CAST(ExtraInfo AS XML) as myinfo
FROM [JOB]
WHERE myinfo.value('XQUERYHERE') IS NULL
但是T-SQL不知道myinfo
是什么。
因此,我显然缺乏对以哪种方式XML查询以NVARCHAR
格式存储的列的可能性
我希望我已经足够清楚了,在此先感谢您的投入
答案 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>