Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2008 Forums
 Transact-SQL (2008)
 Recursively replace tokens from table lookup

Author  Topic 

soaphope
Starting Member

13 Posts

Posted - 2011-02-12 : 15:37:44
I am replacing tokens in a block of text with values that are looked up in a table. I have two issues that I hope others can help with. I've used a CTE to demonstrate, but in the real version the replacements will be pulled from a table.
----------------------

declare @template varchar(8000)
declare @context varchar(255)

set @template = 'dear %name%, this automated email about %topic% was created by %writer%'
set @context = 'hr'

;
WITH Replacements as (
SELECT 'employeename' AS lside, 'john' AS rside UNION
SELECT 'customername', 'mary' UNION
SELECT 'vendorname', 'bob' UNION
SELECT 'topic','your raise' UNION
SELECT 'writer','the HR department' UNION
SELECT 'name', CASE @context
WHEN 'hr' THEN '%employeename%'
WHEN 'sales' THEN '%customername%'
WHEN 'purchasing' THEN '%vendorname%'
END
)

SELECT @template = replace(@template,'%' + lside + '%',rside)
FROM Replacements R

SELECT @template



Run once to get: dear %employeename%, this automated email about your raise was created by the HR department
Run again to get: dear john, this automated email about your raise was created by the HR department


First issue: I need to recursively apply the replacements. You'll see in the example that %name% is replaced with %employeename% in the first pass. If I run it again, %employeename% will be replaced with 'john'. I have tried writing a recursive CTE but can't get it right. It needs to do something like this pseudosql:

if exists(select * from Replacements where (patindex('%' + lside + '%',@template) > 0)), do the replacement again.

Second issue: this approach looks at every item in the replacements table and searches for it in the template string. It would be faster if I looked for each token in the replacement string, replacing the token with its replacement value from the Replacements table - doing this over and over until there are no more tokens in the template. I think there is some way to use coalesce to do this, i just can't quite get there.

Any help is appreciated!

Salah Boukadoum
Founder, Soap Hope
Where 100% of profits go to lift women from poverty - http://soaphope.com

malpashaa
Constraint Violating Yak Guru

264 Posts

Posted - 2011-02-12 : 19:15:28
Try this:

DECLARE @template VARCHAR(8000) = 'dear %name%, this automated email about %topic% was created by %writer%';
DECLARE @context VARCHAR(255) = 'hr';

WITH Replacements(lside, rside) AS
(
SELECT 'employeename', 'john' UNION
SELECT 'customername', 'mary' UNION
SELECT 'vendorname', 'bob' UNION
SELECT 'topic','your raise' UNION
SELECT 'writer','the HR department' UNION
SELECT 'name', CASE @context
WHEN 'hr' THEN '%employeename%'
WHEN 'sales' THEN '%customername%'
WHEN 'purchasing' THEN '%vendorname%'
END
)
, TemplateCTE AS
(
SELECT TOP (1)
REPLACE(@template, '%' + R.lside + '%', R.rside) AS template,
CAST(1 AS BIGINT) AS num,
1 AS sequence
FROM Replacements AS R
WHERE @template <> REPLACE(@template, '%' + R.lside + '%', R.rside)

UNION ALL

SELECT REPLACE(T.template, '%' + R.lside + '%', R.rside),
ROW_NUMBER() OVER(ORDER BY (SELECT NULL)),
T.sequence + 1
FROM Replacements AS R
CROSS JOIN
TemplateCTE AS T
WHERE T.template <> REPLACE(T.template, '%' + R.lside + '%', R.rside)
AND T.num = 1
)
SELECT T.template
FROM (SELECT T.template, ROW_NUMBER() OVER(ORDER BY T.sequence DESC) AS row_num
FROM TemplateCTE AS T) AS T
WHERE T.row_num = 1
OPTION(MAXRECURSION 0);
Go to Top of Page

soaphope
Starting Member

13 Posts

Posted - 2011-02-12 : 19:45:08
It works perfectly. Honestly, I don't understand it and will have to spend some time studying how you accomplished it. Thank you very much for helping, I wouldn't have been able to create this myself. I'm kind of in awe!

Go to Top of Page

malpashaa
Constraint Violating Yak Guru

264 Posts

Posted - 2011-02-12 : 20:43:56
You are welcome.
Go to Top of Page
   

- Advertisement -