これは良い頭の体操でした。再帰的な 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
どの更新が最終であったかを示すために私が見つけた唯一の方法であった変数など、いくつかの煩わしさがあります1。
ありふれたカーソル アプローチは、より簡単なので、おそらくデバッグが容易です。
--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