这是一个很好的脑筋急转弯。这是一个递归 CTE 方法:
--using recursive CTE
with
subq (original, corrected, PassNum) as
(
select expression.expression as corrected, expression.expression as original, 1 as PassNum from expression
union all
select subq.original, cast(replace(subq.corrected, '#' + variable.name + '#', variable.value) as varchar(100)),
PassNum+1 as PassNum from subq, variable where subq.corrected like '%#' + variable.name + '#%'
)
update expression set expression.expression=subq.corrected from expression inner join subq on
expression.expression=subq.original where subq.passnum=(select max(passnum) from subq)
它有一些烦恼,例如您必须转换更正的值以使其与列大小匹配(有关此内容的更多信息,请参见下文)和PassNum
变量,这是我能找到的唯一方法来指示哪个更新是最终的一。
普通的游标方法可能更容易调试,因为它更简单:
--using cursor
DECLARE @name VARCHAR(50)
DECLARE @value VARCHAR(50)
DECLARE loopCursor CURSOR FOR
SELECT name, value from variable
OPEN loopCursor
FETCH NEXT FROM loopCursor INTO @name, @value
WHILE @@FETCH_STATUS = 0
BEGIN
update expression set expression.expression=replace(expression, '#' + @name + '#', @value)
FETCH NEXT FROM loopCursor INTO @name, @value
END
CLOSE loopCursor
DEALLOCATE loopCursor
这是我在使用递归 CTE 时找到的关于强制转换的引用:
您看到的行为是设计使然。虽然我们可以对列进行类型推导和/或强制转换为通用类型,但对于递归 CTE,我们选择保持推导严格。还有一些极端情况,类型推导将无法达到正确的精度/比例/长度。这可能会导致错误。因此,正如您所观察到的,我们的建议是使用 CAST 显式键入任何表达式。-Umachandar,SQL 可编程团队 [1]
[1]
http://connect.microsoft.com/SQLServer/feedback/details/668872/types-dont-match-between-the-anchor-and-the-recursive-part-in-column-columnname-of-recursive -查询-cte-名称