2013-05-28 45 views
0

我有一個表variable包含變量名和它們的值,例如:SQL Server查詢與值替換變量遞歸

  • VAR1 =值1
  • VAR2 =值2
  • VAR3 =值3

另一張表expression包含表達式:

  • 「另一個與#VAR3#和#VAR4#甚至#VAR1#」

,我想,以取代目前在變量 「使用#VAR1#和#VAR2#字符串」表variable通過他們的價值觀,所以結果應該是:

  • 「用value1和value2一個字符串」
  • 「另一個與值3和#VAR4#乃至值1」

有沒有辦法與CTE做到這一點?

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

+0

爲什麼你想遞歸地做到這一點? – RBarryYoung

+0

因爲如果你不遞歸地做它,我不認爲有一種方法可以在同一行中替換多個變量。 – psadac

+0

是否有原因不希望將表達式拆分爲具有序列號的部分?然後,您可以像這樣重新組裝零件:http://sqlfiddle.com/#!3/e0f21/6 – JAQFrost

回答

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-query-cte-name