使用SQL Server中的OpenXML从XML中提取数据

时间:2012-03-06 14:13:09

标签: sql sql-server tsql openxml xml-nil

我有一个xml,我希望它在SQL Server中使用OpenXML提取

以下是XML示例

<row>
  <student_token>7</student_token>
  <student_ssn>552</student_ssn>
  <alternate_id>20</alternate_id>
  <old_ssn xsi:nil="true" />
  <alien_num xsi:nil="true" />
  <last_name>A</last_name>
  <first_name>B</first_name>
  <middle_init xsi:nil="true" />
  <drivers_license_num xsi:nil="true" />
  <gpa_highschool xsi:nil="true" />
  <created_dt>2006-07-13T11:15:08.320</created_dt>
  <created_how>4</created_how>
  <modified_dt>2008-02-14T00:00:00</modified_dt>
  <modified_by>4</modified_by>
  <primary_street2 xsi:nil="true" />
  <primary_street3 xsi:nil="true" />
  <primary_country xsi:nil="true" />
  <email_address xsi:nil="true" />
  <address_start_dt xsi:nil="true" />
  <address_end_dt xsi:nil="true" />
  <entrance_iv_dt xsi:nil="true" />
  <entrance_iv_by xsi:nil="true" />
  <exit_iv_dt>2006-11-02T00:00:00</exit_iv_dt>
  <exit_iv_by>156</exit_iv_by>
  <foreign_address_indicator>N</foreign_address_indicator>
  <foreign_postal_code xsi:nil="true" />
  <pin>J27841</pin>
  <web_id>J08614   </web_id>
  <prior_name xsi:nil="true" />
  <orig_eps xsi:nil="true" />
  <web_role>STU1</web_role>
  <heal_limit_flag>N</heal_limit_flag>
  <email_address_2>test@test.com</email_address_2>
  <cellular_telephone>415</cellular_telephone>
  <alt_loan_debt xsi:nil="true" />
  <web_last_login xsi:nil="true" />
  <foreign_country_code xsi:nil="true" />
  <entrance_iv_dt_grad_plus xsi:nil="true" />
  <entrance_iv_by_grad_plus xsi:nil="true" />
  <failed_logins>0</failed_logins>
  <hispanic xsi:nil="true" />
  <race xsi:nil="true" />
  <primary_phone_number_intl xsi:nil="true" />
  <security_version>0</security_version>
  <failed_challenge_response>0</failed_challenge_response>
  <require_pin_reset xsi:nil="true" />
</row>

查询应提取为每行3个字段

  1. FieldName
  2. fieldValue方法
  3. ISNULL
  4. 例如,第一行应为

    • FieldName = student_token - 节点名称为字段名称
    • FieldValue = 7
    • IsNull = false - IsNull基于属性xsi:nil =“true”

    我该怎么做?任何帮助将不胜感激。

    由于

3 个答案:

答案 0 :(得分:8)

添加了命名空间的示例数据。

declare @xml xml 
set @xml = 
'<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <student_token>7</student_token>
  <student_ssn>552</student_ssn>
  <alternate_id>20</alternate_id>
  <old_ssn xsi:nil="true" />
  <alien_num xsi:nil="true" />
  <last_name>A</last_name>
  <first_name>B</first_name>
  <middle_init xsi:nil="true" />
  <drivers_license_num xsi:nil="true" />
  <gpa_highschool xsi:nil="true" />
  <created_dt>2006-07-13T11:15:08.320</created_dt>
  <created_how>4</created_how>
  <modified_dt>2008-02-14T00:00:00</modified_dt>
  <modified_by>4</modified_by>
  <primary_street2 xsi:nil="true" />
  <primary_street3 xsi:nil="true" />
  <primary_country xsi:nil="true" />
  <email_address xsi:nil="true" />
  <address_start_dt xsi:nil="true" />
  <address_end_dt xsi:nil="true" />
  <entrance_iv_dt xsi:nil="true" />
  <entrance_iv_by xsi:nil="true" />
  <exit_iv_dt>2006-11-02T00:00:00</exit_iv_dt>
  <exit_iv_by>156</exit_iv_by>
  <foreign_address_indicator>N</foreign_address_indicator>
  <foreign_postal_code xsi:nil="true" />
  <pin>J27841</pin>
  <web_id>J08614   </web_id>
  <prior_name xsi:nil="true" />
  <orig_eps xsi:nil="true" />
  <web_role>STU1</web_role>
  <heal_limit_flag>N</heal_limit_flag>
  <email_address_2>test@test.com</email_address_2>
  <cellular_telephone>415</cellular_telephone>
  <alt_loan_debt xsi:nil="true" />
  <web_last_login xsi:nil="true" />
  <foreign_country_code xsi:nil="true" />
  <entrance_iv_dt_grad_plus xsi:nil="true" />
  <entrance_iv_by_grad_plus xsi:nil="true" />
  <failed_logins>0</failed_logins>
  <hispanic xsi:nil="true" />
  <race xsi:nil="true" />
  <primary_phone_number_intl xsi:nil="true" />
  <security_version>0</security_version>
  <failed_challenge_response>0</failed_challenge_response>
  <require_pin_reset xsi:nil="true" />
</row>'

使用openxml

declare @idoc int
exec sp_xml_preparedocument @idoc out, @xml, '<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>'

select FieldName, 
       FieldValue,
       isnull([IsNull], 0)
from openxml(@idoc, '/row/*',1) 
  with (
         FieldName  varchar(50) '@mp:localname',
         FieldValue varchar(50) '.',
         [IsNull]   bit         '@xsi:nil'
       )

exec sp_xml_removedocument @idoc

使用XML数据类型:

;with xmlnamespaces('http://www.w3.org/2001/XMLSchema-instance' as ns)
select T.N.value('local-name(.)', 'varchar(50)') as FieldName,
       T.N.value('.', 'varchar(50)') as FieldValue,
       isnull(T.N.value('@ns:nil', 'bit'), 0) as [IsNull]
from @xml.nodes('/row/*') as T(N)

答案 1 :(得分:3)

不确定您是将XML作为SQL变量还是在表中 - 问题非常不清楚.....

如果你把它作为一个SQL变量,那么尝试这样的事情(注意:你必须以某种方式声明xsi前缀 - 否则SQL Server的XML处理器不会甚至查看您的XML文档):

DECLARE @input XML = '<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <student_token>7</student_token>
  <student_ssn>552</student_ssn>
  <alternate_id>20</alternate_id>
  <old_ssn xsi:nil="true" />
  .........
</row>'

;WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema-instance' as xsi)
SELECT
FieldName = T.C.value('local-name(.)', 'varchar(50)'),
FieldValue = T.C.value('(.)[1]', 'varchar(500)'),
IsNIL = ISNULL(T.C.value('(@xsi:nil)[1]', 'bit'), 0)
FROM
@Input.nodes('/row/*') AS T(C)

这给了我一个类似的输出:

FieldName      FieldValue  IsNIL
student_token    7          0
student_ssn      552        0
alternate_id     20         0
old_ssn                     1
.....

当然,现在varchar(500)列中的所有输出都属于FieldValue类型....

根据Mikael Eriksson的回答更新了我的答案,也包括IsNIL处理。感谢Mikael的灵感!你应该得到点头和接受投票!

答案 2 :(得分:0)

您可以将xml文件转换为json,然后使用OPENJSON。看看openjson : SELECT star,如何使用OPENJSON而不用列出列名。

要将xml文件转换为json,可以使用sp_execute_external_scriptxmltodict python模块。 看一下Importing Python Libraries to SQL Server,以导入python模块并处理YAPI(还需要另一个Python安装)问题。