2011-04-28 58 views
2

这就是所谓的表中的数据域称为对象的字段中的值:SQL或C#:遍历一个字段的值,并插入到另一个

<data><styleid>287634</styleid><c1001>S</c1001><c1002>S</c1002><c1004>S</c1004></data> 

我需要这样做:

Select into objectsindex (product, typeid, classid, objectid, FieldName, FieldValue) 

Values 

select 
product, 
typeid, 
classid, 
objectid, 
FieldName = 'c1001', 
FieldValue = CONVERT(xml, DataFields).value('(/data/c1001/node())[1]', 'nvarchar(1)') 
from objects where typeid = 45 

在该领域(除了<data></data><styleid></styleid>和节点)的每个XML节点和对象表,其中typeid的= 45。

在“C1001”和/ C1001 /值的每个记录变量需要从DataFields字段中提取。

我在标题中放了c#,因为我认为很多人会告诉我这不仅仅是SQL的工作。但我知道有一些真正的SQL Geniuses,所以我希望有一个SQL解决方案。

+0

尝试重新标记XQuery。由于节点名称是可变的,因此可能会有解决方案使用可以将其全部保留在T-SQL中的解决方案。 – Yuck 2011-04-28 12:27:30

回答

2

XQuery来拯救!试试这个 -

DECLARE @X XML = '<data><styleid>287634</styleid><c1001>S</c1001><c1002>S</c1002><c1004>S</c1004></data>'; 

WITH T AS (
    SELECT CONVERT(VarChar(100), X.query('local-name(.)')) NodeName, 
     X.value('.', 'VarChar(100)') NodeValue 
    FROM @X.nodes('//*') F(X) 
) 
SELECT * 
FROM T 
WHERE NodeName LIKE 'C%'; 

这将让您的数据,并从那里我觉得INSERT应该是微不足道的。 =)

+0

忘了提及,我正在使用SQL 2K8,所以如果您至少没有使用该版本,内联变量分配将不起作用。并且// *并不是获得您要查找的节点的非常有效的方法。随着XML文档的更好的了解,您可以更加选择性地使用所需的节点。 – Yuck 2011-04-28 12:38:54

0
declare @XML xml = 
'<data> 
    <styleid>287634</styleid> 
    <c1001>S</c1001> 
    <c1002>S</c1002> 
    <c1004>S</c1004> 
</data>' 

declare @T table (TypeID int, XMLCol xml) 
insert into @T values (45, @XML) 
insert into @T values (46, @XML) 

select 
    T.TypeID, 
    C.Name, 
    D.Item.value('.', 'varchar(max)') as Value 
from @T as T 
    cross apply T.XMLCol.nodes('/data/*') as D(Item) 
    cross apply (select D.Item.value('local-name(.)', 'varchar(max)')) as C(Name) 
where 
    C.Name <> 'styleid' and 
    T.TypeID = 45 

结果

TypeID Name Value 
45  c1001 S 
45  c1002 S 
45  c1004 S 

另一个版本

select 
    T.TypeID, 
    D.Item.value('local-name(.)', 'varchar(max)') as Name, 
    D.Item.value('.', 'varchar(max)') as Value 
from @T as T 
    cross apply T.XMLCol.nodes('/data/*[local-name(.)!="styleid"]') as D(Item) 
where 
    T.TypeID = 45 
1

..和因为你提到C#,这里是你将如何使用LINQ片段做到这一点。

你可以拿起LINQPad(免费在http://www.linqpad.net)并直接运行它,而不需要为它创建一个全新的项目。

var objects45 = Objects.Where(obj=>obj.Typeid=="45"); 
foreach(var obj in objects45) { 
    var xml = XElement.Parse(obj.Datafields); 
    var fields = xml.Elements().Where(e=>e.Name != "styleid"); 
    var newRecords = from fieldTag in xml.Elements() 
        where fieldTag.Name != "styleid" 
        select new ObjectsIndex() { 
         Product = obj.Product, 
         Typeid = obj.Typeid, 
         Classid = obj.Classid, 
         Objectid = obj.Objectid, 
         Fieldname = fieldTag.Name.LocalName, 
         Fieldvalue = fieldTag.Value 
        }; 
    newRecords.Dump("These records will be inserted:"); 
    // Uncomment to actually insert 
    // ObjectsIndexes.InsertAllOnSubmit(newRecords); 
} 
// Uncomment to actually insert 
// ObjectsIndexes.Context.SubmitChanges(); 
相关问题