首先:您给定的 XML 无效...
您正在尝试做的是一种称为 Key-Value-Pair (或 Attribute-Value-Pair 或 Entity-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);
但是你的问题没有提供足够的细节:你打算用这个做什么?结构(可能稍后!)是否更复杂(内部嵌套元素,如地址、电话号码)?定义一组确定的属性并允许客户定义哪些属性不使用要好得多。也许允许他们给出个人名称(别名)。但我不建议你提供一个完全开放的自己动手数据库。你会陷入深深的麻烦中......