使用 SQL OPENXML 查找特定子元素
Posted
技术标签:
【中文标题】使用 SQL OPENXML 查找特定子元素【英文标题】:Finding Specific Child Element Using SQL OPENXML 【发布时间】:2021-12-05 15:49:35 【问题描述】:鉴于此 XML:
<ArrayOfCandidate>
<Candidate>
<Candidate_Serial>a4wwj48pypxg</Candidate_Serial>
<Job_Serial>a2wwj48c92qp</Job_Serial>
<Job_Name>Janitor</Job_Name>
<First_Name>Phillip</First_Name>
<Last_Name>Fry</Last_Name>
<Email>phillip_fry@yahoo.com</Email>
<Address_1>123 Main St</Address_1>
<Questionnaires>
<Questionnaire>
<Questionnaire_Name>Questionnaire 1</Questionnaire_Name>
<Questionnaire_Serial>a7wwj48rbcwx</Questionnaire_Serial>
<Submit_Date>04/29/2020 10:55 AM</Submit_Date>
<Submit_Date_Timestamp>1588175742</Submit_Date_Timestamp>
<Questions>
<QuestionObject>
<Question>Salary Requirements</Question>
<Value>36.00 per hour</Value>
</QuestionObject>
<QuestionObject>
<Question>Are you eligible to work in the US?</Question>
<Value>Yes</Value>
</QuestionObject>
</Questions>
</Questionnaire>
<Questionnaire>
<Questionnaire_Name>New Employee Information Sheet</Questionnaire_Name>
<Questionnaire_Serial>a7wwj488ril8</Questionnaire_Serial>
<Submit_Date>05/18/2020 11:52 AM</Submit_Date>
<Submit_Date_Timestamp>1589820723</Submit_Date_Timestamp>
<Questions>
<QuestionObject>
<Question>Zip Code</Question>
<Value>86327</Value>
</QuestionObject>
<QuestionObject>
<Question>Phone Number</Question>
<Value>252-915-1623</Value>
</QuestionObject>
<QuestionObject>
<Question>Social Security Number</Question>
<Value>414-62-7741</Value>
</QuestionObject>
</Questions>
</Questionnaire>
</Questionnaires>
</Candidate>
</ArrayOfCandidate>
我已经能够使用<Questionnaire>
和<QuestionObject>
的索引来查找值,但我不能保证索引始终相同。
exec sp_xml_preparedocument @idoc OUTPUT, @XMLData
select *
from openxml(@idoc,'/ArrayOfCandidate/Candidate', 1)
with (
Candidate_Serial nvarchar(max) 'Candidate_Serial'
, First_Name nvarchar(max) 'First_Name'
, Last_Name nvarchar(max) 'Last_Name'
, Email nvarchar(max) 'Email'
, Address_1 nvarchar(max) 'Address_1'
, SSN nvarchar(max) 'Questionnaires/Questionnaire[2]/Questions/QuestionObject[3]/Value'
) c;
是否可以用New Employee Information Sheet
的文本重写<Questionnaire_Name>
元素和<Question>
元素与Social Security Number
文本的查询匹配
【问题讨论】:
最好使用 XQuery 方法 .nodes() 和 .value() 而不是专有的 OPENXML。 @YitzhakKhabinsky 我尽量避免使用 XQuery,因为它对于需要处理大量元素的查询要慢得多,这里就是这种情况。 【参考方案1】:请尝试以下解决方案。
无论其顺序位置如何,它都会找到 SSN。
从 SQL Server 2005 开始,最好使用基于 w3c 标准的 XQuery 语言,同时处理 XML 数据类型。
保留 Microsoft 专有的 OPENXML
及其伙伴 sp_xml_preparedocument
和 sp_xml_removedocument
只是为了与过时的 SQL 向后兼容
Server 2000。它们的使用减少到极少数的边缘情况。
强烈建议重新编写 SQL 并将其切换到 XQuery。
SQL
DECLARE @xml XML =
N'<ArrayOfCandidate>
<Candidate>
<Candidate_Serial>a4wwj48pypxg</Candidate_Serial>
<Job_Serial>a2wwj48c92qp</Job_Serial>
<Job_Name>Janitor</Job_Name>
<First_Name>Phillip</First_Name>
<Last_Name>Fry</Last_Name>
<Email>phillip_fry@yahoo.com</Email>
<Address_1>123 Main St</Address_1>
<Questionnaires>
<Questionnaire>
<Questionnaire_Name>Questionnaire 1</Questionnaire_Name>
<Questionnaire_Serial>a7wwj48rbcwx</Questionnaire_Serial>
<Submit_Date>04/29/2020 10:55 AM</Submit_Date>
<Submit_Date_Timestamp>1588175742</Submit_Date_Timestamp>
<Questions>
<QuestionObject>
<Question>Salary Requirements</Question>
<Value>36.00 per hour</Value>
</QuestionObject>
<QuestionObject>
<Question>Are you eligible to work in the US?</Question>
<Value>Yes</Value>
</QuestionObject>
</Questions>
</Questionnaire>
<Questionnaire>
<Questionnaire_Name>New Employee Information Sheet</Questionnaire_Name>
<Questionnaire_Serial>a7wwj488ril8</Questionnaire_Serial>
<Submit_Date>05/18/2020 11:52 AM</Submit_Date>
<Submit_Date_Timestamp>1589820723</Submit_Date_Timestamp>
<Questions>
<QuestionObject>
<Question>Zip Code</Question>
<Value>86327</Value>
</QuestionObject>
<QuestionObject>
<Question>Phone Number</Question>
<Value>252-915-1623</Value>
</QuestionObject>
<QuestionObject>
<Question>Social Security Number</Question>
<Value>414-62-7741</Value>
</QuestionObject>
</Questions>
</Questionnaire>
</Questionnaires>
</Candidate>
</ArrayOfCandidate>';
SELECT c.value('(Candidate_Serial/text())[1]', 'varchar(50)') as Candidate_Serial
, c.value('(First_Name/text())[1]', 'varchar(50)') as First_Name
, c.value('(Last_Name/text())[1]', 'varchar(50)') as Last_Name
, c.value('(Email/text())[1]', 'varchar(500)') as Email
, c.value('(Address_1/text())[1]', 'varchar(500)') as Address_1
, c.value('(Questionnaires/Questionnaire/Questions/QuestionObject[Question/text()="Social Security Number"]/Value/text())[1]', 'CHAR(11)') as SSN
FROM @xml.nodes('/ArrayOfCandidate/Candidate') AS t(c);
输出
+------------------+------------+-----------+-----------------------+-------------+-------------+
| Candidate_Serial | First_Name | Last_Name | Email | Address_1 | SSN |
+------------------+------------+-----------+-----------------------+-------------+-------------+
| a4wwj48pypxg | Phillip | Fry | phillip_fry@yahoo.com | 123 Main St | 414-62-7741 |
+------------------+------------+-----------+-----------------------+-------------+-------------+
【讨论】:
以上是关于使用 SQL OPENXML 查找特定子元素的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 jQuery 从子元素中获取数据以在 xml api 中查找其他子元素?