0

我有一个variable包含变量名称及其值的表,例如:

  • var1 = 值 1
  • var2 = 值 2
  • var3 = 值 3

另一个表expression包含表达式:

  • “使用 #var1# 和 #var2# 的字符串”
  • “另一个有 #var3# 和 #var4# 甚至 #var1#”

我想variable用它们的值替换表中存在的变量,所以结果应该是:

  • “使用 value1 和 value2 的字符串”
  • “另一个具有 value3 和 #var4# 甚至 value1 的人”

有没有办法用 CTE 做到这一点?

http://sqlfiddle.com/#!3/c1e1e/2/0

4

1 回答 1

3

这是一个很好的脑筋急转弯。这是一个递归 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-名称

于 2013-05-29T18:26:39.587 回答