sql server查询以递归方式替换值

时间:2013-05-28 14:16:50

标签: sql sql-server sql-server-2008

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

  • var1 = value1
  • var2 = value2
  • var3 = value3

另一个表expression包含表达式:

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

我希望用它们的值替换表variable中的变量,因此结果应为:

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

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

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

1 个答案:

答案 0 :(得分: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我们选择严格保持推导。还有一个角落   类型派生无法到达的情况   正确的精度/比例/长度。这可能会导致错误。   所以我们的建议就是明确键入any   表达式使用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-query-cte-name