【问题标题】:Query XML with dynamic number of elements or attributes?使用动态数量的元素或属性查询 XML?
【发布时间】:2016-07-21 17:32:29
【问题描述】:

我在 sql 数据库中有一个员工表,它有一些固定的属性,比如employee_id、employee_name 和employee_age,我允许用户在 UI 中添加他选择的 n 个属性。我想编写一个存储过程来存储用户为固定属性提供的数据以及他创建的属性。

我认为的解决方案是将 xml 作为参数传递给具有以下结构的存储过程。如果没有提供employee_age,则存储其默认值。

<employee>
  <employee_id>1<employee_id>
  <employee_name>XYZ<employee_name>
  <dynamic_attrib1>2.34</dynamic_attrib1>
  <dynamic_attrib2>abcd</dynamic_attrib2>
<employee>

我面临的问题是当我不知道用户预先设置的属性名称时如何解析这个xml?我可以这样做吗?我还有其他方法可以做到吗?提前谢谢.. :)

【问题讨论】:

  • 嗨,这个问题还没有解决吗?您需要进一步的帮助吗?

标签: xml sql-server-2008 stored-procedures


【解决方案1】:

首先:您给定的 XML 无效...

您正在尝试做的是一种称为 Key-Value-Pair (或 Attribute-Value-PairEntity-Attribute-Value) 并且总是非常麻烦...在数据库方面,我们最好了解结果集的结构,否则您需要(丑陋的)技巧。

您可以将给定的 XML 转换为经典的键值对,如下所示:

DECLARE @xml XML=
'<employee>
  <employee_id>1</employee_id>
  <employee_name>XYZ</employee_name>
  <dynamic_attrib1>2.34</dynamic_attrib1>
  <dynamic_attrib2>abcd</dynamic_attrib2>
</employee>';

SELECT Nd.value('local-name(.)','varchar(max)') AS NodeName
      ,Nd.value('.','varchar(max)')
FROM @xml.nodes('employee/*') AS A(Nd);

如果有相应的条目,您可以使用帮助表更改节点名称:

DECLARE @dynAttribs TABLE (AttribName VARCHAR(100),name VARCHAR(100));
INSERT INTO @dynAttribs VALUES
 ('dynamic_attrib1','Whatever can be 2.34')
,('dynamic_attrib2','Whatever can be "abcd"');

SELECT ISNULL(da.name, Nd.value('local-name(.)','varchar(max)')) AS NodeName
      ,Nd.value('.','varchar(max)')
FROM @xml.nodes('employee/*') AS A(Nd)
LEFT JOIN @dynAttribs AS da ON Nd.value('local-name(.)','varchar(max)')=da.AttribName;

您甚至可以在帮助表中包含数据类型,但这会强制您使用动态创建的语句和EXEC

比你的 XML 更好的是这样的:

DECLARE @xml XML=
'<employee>
  <employee_id>1</employee_id>
  <employee_name>XYZ</employee_name>
  <DynamicAttributes>
      <attribute name="testname1">2.34</attribute>
      <attribute name="testname2">abcd</attribute>
  </DynamicAttributes>
</employee>';

SELECT e.value('employee_id[1]','int') AS Employee_Id
      ,e.value('employee_name[1]','varchar(max)') AS Employee_Name
      ,da.value('@name','varchar(max)') AS NodeName
      ,da.value('.','varchar(max)')
FROM @xml.nodes('employee') AS A(e)
OUTER APPLY e.nodes('DynamicAttributes/*') AS B(da);

但是你的问题没有提供足够的细节:你打算用这个做什么?结构(可能稍后!)是否更复杂(内部嵌套元素,如地址、电话号码)?定义一组确定的属性并允许客户定义哪些属性不使用要好得多。也许允许他们给出个人名称(别名)。但我不建议你提供一个完全开放的自己动手数据库。你会陷入深深的麻烦中...​​...

【讨论】:

    猜你喜欢
    • 2012-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-31
    相关资源
    最近更新 更多