我需要一些帮助来尝试导入以下XML文档
<ROOT>
<MeasuresList>
<Measure ID="164">
<Names>
<Name ID="1072687" langid="33"/>
<Name ID="1017672" langid="13">miljoner skär</Name>
</Names>
</Measure>
<Measure ID="362">
<Names>
<Name ID="1072687" langid="33"/>
<Name ID="1017672" langid="13">miljoner skär</Name>
<Name ID="4068857" langid="19">hyller</Name>
<Name ID="3330057" langid="18">ράφια</Name>
<Name ID="3291105" langid="20">raflar</Name>
<Name ID="2813622" langid="10"/>
</Names>
</Measure>
<Measure ID="162">
<Names>
<Name ID="1072687" langid="33"/>
<Name ID="1017672" langid="13">miljoner skär</Name>
<Name ID="1072427" langid="36"/>
<Name ID="438237" langid="20">sayfa başına geçen dakika</Name>
</Names>
</Measure>
</MeasuresList>
进入dbo.table(ID int PRIMARY KEY,langid int FK,Value NVARCHAR(MAX)) 我正在使用
ALTER PROCEDURE [dbo].[AddNewMeasuresList]
(
@XmlData XML
)
AS
DECLARE @doc int;
EXEC sp_xml_preparedocument @doc OUTPUT, @XmlData
BEGIN TRANSACTION T1
Insert Measure_Name
SELECT *
FROM OPENXML(@doc,'//ROOT/MeasuresList/Measure/Names/Name') WITH Measure_Name AS mes
WHERE NOT EXISTS
(
SELECT 1 FROM dbo.Measure_Name WHERE ID=mes.ID
)
COMMIT TRANSACTION T1
EXEC sp_xml_removedocument @doc
但是我的c#应用程序中出现异常
System.Data.SqlClient.SqlException (0x80131904):
Violation of PRIMARY KEY constraint 'PK_Measure_Name'.
Cannot insert duplicate key in object 'dbo.Measure_Name'. The duplicate key value is (1072687)
dbo.Measure_Name表为空,但其他Measure XML节点中的重复条目具有相同的名称ID。
由于我的SELECT语句返回导致重复PRIMARY KEYS的所有“Name”,如何更改select语句以返回所有值,但只有DISTINCT / UNIQUE ID?
答案 0 :(得分:1)
您自己的解决方案可能有效,但这可以做得更好......
FROM OPENXML
与SP一起准备和删除文档已经过时,不应再使用了。而是使用native XML support。
尝试并根据您的需求进行调整:
您的XML
DECLARE @xml XML=
N'<ROOT>
<MeasuresList>
<Measure ID="164">
<Names>
<Name ID="1072687" langid="33" />
<Name ID="1017672" langid="13">miljoner skär</Name>
</Names>
</Measure>
<Measure ID="362">
<Names>
<Name ID="1072687" langid="33" />
<Name ID="1017672" langid="13">miljoner skär</Name>
<Name ID="4068857" langid="19">hyller</Name>
<Name ID="3330057" langid="18">ράφια</Name>
<Name ID="3291105" langid="20">raflar</Name>
<Name ID="2813622" langid="10" />
</Names>
</Measure>
<Measure ID="162">
<Names>
<Name ID="1072687" langid="33" />
<Name ID="1017672" langid="13">miljoner skär</Name>
<Name ID="1072427" langid="36" />
<Name ID="438237" langid="20">sayfa başına geçen dakika</Name>
</Names>
</Measure>
</MeasuresList>
</ROOT>';
- 我的目标表将包含@ID
中的<Measure>
,不知道您是否需要此内容...
DECLARE @target TABLE(MeasureID int, NameID int, [langid] int, [Value] NVARCHAR(MAX))
- 数据将使用表格@target
作为登台表
- 查询使用.nodes()
,APPLY
和.value
来读取XML中的值
INSERT INTO @target(MeasureID,NameID,[langid],[Value])
SELECT m.value(N'@ID',N'int') AS MeasureID
,n.value(N'@ID',N'int') AS NameID
,n.value(N'@langid',N'int') AS [langid]
,n.value(N'text()[1]',N'nvarchar(max)') AS [Value]
FROM @xml.nodes(N'/ROOT/MeasuresList/Measure') AS A(m)
OUTER APPLY A.m.nodes(N'Names/Name') AS B(n);
- 返回完整(非规范化)内容
SELECT * FROM @target;
在此之后,您可以使用任何类型的GROUP BY
聚合,无论您需要什么,都可以将其转移到目标表中。
我建议一个至少有两个相关表格的结构,反映你的1:n相关的度量/名称关系。
使用FROM @xml.nodes(N'/ROOT/MeasuresList/Measure') AS A(m)
将生成所有(重复)<Measure>
元素的派生表。这个&#34;表&#34;被称为A
,而#34;列被称为#34}。被称为m
(对于&#34;衡量&#34;)。此列是一个XML片段,表示每行一个<Measure>
。
使用OUTER APPLY A.m.nodes(N'Names/Name') AS B(n)
我使用此派生表A,再使用其列m .nodes()
来深入查看(重复的)<Name>
元素。
实际值是.value()
。此方法首先采用XPath/XQuery
,第二种采用目标类型。
希望现在很清楚...... :-D
答案 1 :(得分:0)
发布我找到的答案,我添加了一个新的WHERE子句,它将当前ID与DISTINCT ID的列表/数组/表进行比较
ALTER PROCEDURE [dbo].[AddNewMeasuresList]
(
@XmlData XML
)
AS
DECLARE @doc int;
EXEC sp_xml_preparedocument @doc OUTPUT, @XmlData
BEGIN TRANSACTION T1
Insert Measure_Name
SELECT *
FROM OPENXML(@doc,'//ROOT/MeasuresList/Measure/Names/Name')
WITH
(
ID int,
langid int,
Value nvarchar(MAX) 'text()'
) AS mn
WHERE
(
mn.ID in (SELECT DISTINCT ID FROM OPENXML(@doc,'////ROOT/MeasuresList/Measure/Names/Name'))
)
AND NOT EXISTS
(
SELECT 1 FROM dbo.Measure_Name WHERE ID=mn.ID
)
COMMIT TRANSACTION T1
EXEC sp_xml_removedocument @doc