Sql server ULL('+QUOTENAME(@column)+','') EXEC sp_executesql@sql 结束 感谢您的努力,我相信CLR解决方案是可能的。在我看来,必须为此创建XSLT和CLR比创建多个insert语句要多得多。尤其是因为这还没有成为一
ULL('+QUOTENAME(@column)+','') EXEC sp_executesql@sql 结束Sql server ULL('+QUOTENAME(@column)+','') EXEC sp_executesql@sql 结束 感谢您的努力,我相信CLR解决方案是可能的。在我看来,必须为此创建XSLT和CLR比创建多个insert语句要多得多。尤其是因为这还没有成为一,sql-server,xml,sql-server-2008,Sql Server,Xml,Sql Server 2008,ULL('+QUOTENAME(@column)+','') EXEC sp_executesql@sql 结束 感谢您的努力,我相信CLR解决方案是可能的。在我看来,必须为此创建XSLT和CLR比创建多个insert语句要多得多。尤其是因为这还没有成为一种通用的合并方法(不是我要求的,只是需要额外的努力才能将其提升到另一个层次)。部署、安装和管理SQL外部的额外文件对我来说是个问题。为此,我也考虑过使用replace语句,但我认为会有一个简单的xml查询解决方案来避免这些事情。在这里,它是在S
感谢您的努力,我相信CLR解决方案是可能的。在我看来,必须为此创建XSLT和CLR比创建多个insert语句要多得多。尤其是因为这还没有成为一种通用的合并方法(不是我要求的,只是需要额外的努力才能将其提升到另一个层次)。部署、安装和管理SQL外部的额外文件对我来说是个问题。为此,我也考虑过使用replace语句,但我认为会有一个简单的xml查询解决方案来避免这些事情。在这里,它是在SQL中,在您的答案上有几个注释,它已经接近工作了,但是else语句也需要替换“”,“…”,需要避免插入重复的语句,我认为它可以大大简化。有关我的简化,请参阅。@ScottC我将查询更改为更新查询,现在它将更新您的xmlCol;)。谢谢Brian,这至少会删除所有附加更新!您可能拥有最好的基于SQLXML的解决方案,但如果需要插入超过5层的内容,这将很快变得难以理解。对于这一点,需要“如果-然后-其他”似乎是一个很大的疏忽。我没有考虑过两个“如果-然后-其他”的问题,一个是插页,另一个是“如果”。好主意!这是您在SQL Fiddle中的代码,看起来Brian下面的答案与XML的答案差不多。i、 一次更新中有多个if语句-一次更新很好,但对更复杂的树这样做将是一场噩梦。我知道我说过我不会接受使用动态SQL的答案,但我想我可能会将Brian的答案转换为使用动态SQL消除重复的存储过程,并将其打开给其他树和列。仍然希望有人能提出一个更简单的XML语句:)
CREATE TABLE tableColors (id nvarchar(100), color nvarchar(100))
CREATE TABLE xmlTable (id nvarchar(100), xmlCol xml)`
UPDATE xmlTable
SET xmlCol.modify(' insert <color>{sql:column("color")}</color> as first into (/root/colors)[1] ')
FROM xmlTable
INNER JOIN tableColors ON xmlTable.id = tableColors.id
WHERE xmlCol.exist('/root/colors/color[(text()[1]) = sql:column("color")]') = 0
New Element XML before XML after
<color>blue</color> -blank- <root><colors><color>blue</color></colors></root>
<color>green</color> <root><vegitation>yes</vegitation></root> <root><vegitation>yes</vegitation><colors><color>green</color></colors></root>
<color>white</color> <root><colors><color>brown</color></colors></root> <root><colors><color>brown</color><color>white</color></colors></root>
update @xmlTable
set xmlCol = case
when cast(xmlCol as varchar(max)) = ''
then '<root><colors><color>' + color + '</color></colors></root>'
else {run xslt transformation, passing in @tableColors.color as XSLT parameter colorForUpdate}
end
from @xmlTable x
inner join @tableColors y on x.id = y.id
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:param name="colorForUpdate"/>
<xsl:template match="/root[not(colors)]">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<colors>
<color>
<xsl:value-of select="$colorForUpdate"/>
</color>
</colors>
</xsl:copy>
</xsl:template>
<xsl:template match="/root/colors">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<color>
<xsl:value-of select="$colorForUpdate"/>
</color>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
UPDATE xmlTable
SET xmlTable.xmlCol = (
SELECT
CAST(REPLACE(x.myXML, '&myColor;', c.color) AS XML)
FROM (
SELECT *,
CASE
WHEN xmlTable.xmlCol.exist('root') = 0 THEN
'<root><colors><color>&myColor;</color></colors></root>'
WHEN xmlTable.xmlCol.exist('root/colors') = 0 THEN
REPLACE(CONVERT(nvarchar(max), xmlTable.xmlCol), '<root>','<root><colors><color>&myColor;</color></colors>')
ELSE
CONVERT(nvarchar(max), xmlTable.xmlCol)
END AS myXML
FROM
xmlTable) x
JOIN
tableColors c
ON x.id = c.id
WHERE
xmlTable.id = x.id)
UPDATE #xmlTable
SET xmlCol.modify('
insert if (count(/root)=0) then <root><colors><color>{sql:column("color")}</color></colors></root>
else (if (count(/root/colors)=0) then <colors><color>{sql:column("color")}</color></colors>
else <color>{sql:column("color")}</color>) as first into
(if (count(/root)=0) then (/) else (if (count(/root/colors)=0) then (/root) else (/root/colors)))[1]')
FROM #xmlTable
INNER JOIN #tableColors
ON #xmlTable.id = #tableColors.id
WHERE xmlCol.exist('/root/colors/color[(text()[1])=sql:column("color")]') = 0
-- @xmlTree should be of the format '/root/colors/color', column is where to get the data from in the tableFacts table
CREATE PROCEDURE sp_insertXML(@xmlTree nvarchar(max), @column sysname)
AS
BEGIN
DECLARE @insert nvarchar(max), @if nvarchar(max), @val nvarchar(max), @into nvarchar(max)
DECLARE @xmlColumn nvarchar(max)='sql:column("' + @column +'")'
DECLARE @parentTree nvarchar(max)=@xmlTree
DECLARE @endTree nvarchar(max)
DECLARE @closeTags nvarchar(max)=''
DECLARE @thisTag nvarchar(max)
WHILE (LEN(@parentTree)>0)
BEGIN
-- Set each parameter
SET @thisTag = RIGHT(@parentTree,CHARINDEX('/',REVERSE(@parentTree))-1)
SET @endTree = @thisTag + COALESCE('/' + @endTree, '')
SET @closeTags = @closeTags + '</' + @thisTag + '>'
SET @parentTree = LEFT(@parentTree,LEN(@parentTree)-LEN(@thisTag)-1)
-- Set the insert and into statements
SET @if = 'if (count(' + @parentTree + '/' + @thisTag + ')=0) then '
SET @val = '<' + REPLACE(@endTree,'/','><') + '>{' + @xmlColumn + '}' + @closeTags
SET @insert = COALESCE(@if + @val + '
else ' + @insert, @val)
SET @into = CASE WHEN @into IS NULL THEN '' ELSE 'if (count(' + @parentTree + '/' + @thisTag + ')=0) then ' END + ' (' +
CASE @parentTree WHEN '' THEN '/' ELSE @parentTree END + ')' + COALESCE(' else ' + @into,'')
END
DECLARE @sql nvarchar(max) = 'UPDATE xmlTable
SET xmlCol.modify('' insert ' + @insert + ' into (' + @into + ')[1]'')
FROM xmlTable
INNER JOIN tableFacts
ON xmlTable.id = tableFacts.id
WHERE xmlCol.exist(''' + @xmlTree + '[(text()[1])=' + @xmlColumn + ']'') = 0
AND ISNULL(' + QUOTENAME(@column) + ','''') <> '''''
EXEC sp_executesql @sql
END