如果可以在Server (2012)中的现有xml实例中动态插入xml节点,我无法找到任何文档。我知道您可以插入或替换一个条件值,但是如果可以根据某些条件动态地完成插入位置,则似乎没有任何文档。例如,假设我有这个XML调用:
SET @xml.modify('insert <SecondaryContact><Name>{ sql:variable("@contactName") }</Name>
<Phone>{ sql:variable("@contactPhone") }</Phone>
<Email>{ sql:variable("@contactEmail") }</Email></SecondaryContact>
after (/Project/PrimaryContact)[1]');如果after关键字后面列出的节点是有条件的,那么修改是否是有效的语法?以下是我所指的例子:
SET @xml.modify('insert <TechnicalContact><Name>{ sql:variable("@contactName") }</Name>
<Phone>{ sql:variable("@contactPhone") }</Phone>
<Email>{ sql:variable("@contactEmail") }</Email></TechnicalContact>
after (
if(count(/Project/SecondaryContact) = 0)
then (/Project/PrimaryContact)[1]
else (/Project/SecondaryContact)(1)
)');是动态选择在XML语句之外使用IF..ELSE语句的位置的唯一方法,还是我的示例XML有效?
编辑示例XML:
<root>
...
<PrimaryContact Id="1234">
<Name>John Doe</Name>
<Phone>555-555-5555</Phone>
<Email>somewhere@test.com</Email>
</PrimaryContact>
<SecondaryContact Id="1236"> <--OPTIONAL
<Name>John Doe1</Name>
<Phone>555-555-5556</Phone>
<Email>somewhere1@test.com</Email>
</SecondaryContact>
<TechnicalContact Id="2234"> <--OPTIONAL
<Name>John Doe2</Name>
<Phone>555-555-5255</Phone>
<Email>somewhere3@test.com</Email>
</TechnicalContact>
...
</root>我知道这个结构不太理想。它应该是<Contacts><Contact Type="PRIMARY" Id="1234">...</Contact>...</Contacts>,但是想知道动态插入位置在DML语句中是否可行。对于这个问题,光标的使用是可以的,就像一次更新一样。
发布于 2016-11-04 15:12:23
这个建议并不完全相同,因为它将在文档后面的任何一个后面插入,而不是在SecondaryContact之后插入,但我怀疑在您的例子中,这是相同的事情:
SET @xml.modify('insert
<TechnicalContact><Name>{ sql:variable("@contactName") }</Name>
<Phone>{ sql:variable("@contactPhone") }</Phone>
<Email>{ sql:variable("@contactEmail") }</Email></TechnicalContact>
after (/Project/*[
local-name(.) = "SecondaryContact"
or local-name(.) = "PrimaryContact"
])[last()]
');或者:
if @xml.value('count(/Project/SecondaryContact)', 'int') = 0
begin
SET @xml.modify('insert <TechnicalContact><Name>{ sql:variable("@contactName") }</Name>
<Phone>{ sql:variable("@contactPhone") }</Phone>
<Email>{ sql:variable("@contactEmail") }</Email></TechnicalContact>
after (/Project/PrimaryContact)[1]
');
end else begin
SET @xml.modify('insert <TechnicalContact><Name>{ sql:variable("@contactName") }</Name>
<Phone>{ sql:variable("@contactPhone") }</Phone>
<Email>{ sql:variable("@contactEmail") }</Email></TechnicalContact>
after (/Project/SecondaryContact)[1]
');
end发布于 2016-11-04 15:04:45
在您提供更多的示例(请参阅我的注释)之前,我认为最好的方法是创建节点以插入外部,并将其作为最后一个插入。
但是-相当肯定-有更好的方法.
DECLARE @contactName NVARCHAR(100)='TestName';
DECLARE @contactPhone NVARCHAR(100)='TestPhone';
DECLARE @contactEmail NVARCHAR(100)='TestEmail';
DECLARE @tbl TABLE(ID INT IDENTITY,Descr VARCHAR(100),XmlColumn XML);
INSERT INTO @tbl VALUES
('With secondary'
,N'<Project>
<PrimaryContact>test Primary</PrimaryContact>
<SecondaryContact>test Secondary</SecondaryContact>
</Project>')
,('Only primary'
,N'<Project>
<PrimaryContact id="prim">test Primary</PrimaryContact>
</Project>');
UPDATE @tbl SET XmlColumn.modify
(
N'insert sql:column("x.NodeToInsert") as last into (/Project)[1]'
)
FROM @tbl
CROSS APPLY
(
SELECT
(
SELECT(
SELECT @contactName AS [Name]
,@contactPhone AS [Phone]
,@contactEmail AS [Email]
WHERE XmlColumn.exist('/Project/SecondaryContact')=0
FOR XML PATH('SecondaryContact'),TYPE
) AS [node()]
,(
SELECT @contactName AS [Name]
,@contactPhone AS [Phone]
,@contactEmail AS [Email]
WHERE XmlColumn.exist('/Project/SecondaryContact')=1
FOR XML PATH('TechnicalContact'),TYPE
) AS [node()]
FOR XML PATH(''),TYPE
) AS NodeToInsert
) AS x
SELECT * FROM @tbl更新
另一种方法是:使用CTE分解XML,使用.query()获取所有未受影响的节点,使用.value()提取受影响的值。然后用一个简单的选择..。对于XML PATH()语句,以需要的方式重新构建XML .
发布于 2016-11-04 18:43:15
您可以按照这个顺序添加构造序列 of SecondaryContact和PrimaryContact,并在第一次出现后添加节点。
insert
<TechnicalContact>
<Name>{ sql:variable("@contactName") }</Name>
<Phone>{ sql:variable("@contactPhone") }</Phone>
<Email>{ sql:variable("@contactEmail") }</Email>
</TechnicalContact>
after (
/Project/SecondaryContact,
/Project/PrimaryContact
)[1]https://stackoverflow.com/questions/40423748
复制相似问题