替换结果集中的占位符内容

时间:2017-10-23 00:28:15

标签: sql-server tsql replace

我把这张桌子作为一个简单的例子,带有食物:

Table: FoodItem
1 Burgers
2 French Fries
3 Pizzas

我还有另一张包含这些短语的表:

Table: Phrase
1 I want {1} and {2}!
2 I just want {3}.

我想创建一个sp来抓取短语表中的所有短语,并用食物表中的内容替换占位符部分,如下所示:

I want Burgers and French Fries!
I just want Pizzas.

我怎样才能做到这一点?我已经尝试了#34;喜欢"和" patindex",但我不确定这些是否适合这项任务。

2 个答案:

答案 0 :(得分:1)

对于少量替换和少量数据,您可以使用递归CTE(我在执行大量替换时看到了糟糕的性能)。像这样:

Declare @Phrase table (ID int,Phrase varchar(100))
Insert into @Phrase values 
 (1,'I want {1} and {2}!')
,(2,'I just want {3}.')
,(3,'i just don not like {1} and {3}');

Declare @FoodItem table (ID int, MapTo varchar(100))
Insert Into @FoodItem values 
 (1 ,'Burgers')
,(2 ,'French Fries')
,(3 ,'Pizza');

With DataSource AS
(
    SELECT ID
           ,Phrase
           ,1 as level
    FROM @Phrase
    UNION ALL
    SELECT DS.[ID]
          ,cast(REPLACE(ds.Phrase, '{'+ CAST(DS.[Level] AS VARCHAR(8)) +'}', FI.[MapTo])  as varchar(100))
          ,level + 1 as level
    FROM DataSource DS
    INNER JOIN @FoodItem FI
        ON DS.[level] = FI.[ID]
)
SELECT *
FROM DataSource
WHERE level = (SELECT max(id) from @FoodItem) + 1;

我相信这可以进一步改善。

如果您要处理大量数据,最好使用SQL CLR函数替换多个字符串并连接字符串。

所以,对于每一行,你都会有这样的东西:

 (1,'I want {1} and {2}!', '{1}|{2}','Burgers|French Fries')
,(2,'I just want {3}.', '{3}', 'Pizza')
,(3,'i just don not like {1} and {3}', '{1}|{3}','Burgers|Pizza');

然后你的函数接受三列并在内部执行替换。

答案 1 :(得分:0)

示例

Declare @Phrase table (ID int,Phrase varchar(100))
Insert into @Phrase values 
 (1,'I want {1} and {2}!')
,(2,'I just want {3}.')

Declare @FoodItem table (ID int, MapTo varchar(100))
Insert Into @FoodItem values 
 (1 ,'Burgers')
,(2 ,'French Fries')
,(3 ,'Pizza')


Select A.ID
      ,NewStr = replace(replace(B.S,' ||',''),'|| ','')
 From  @Phrase A
 Cross Apply (
                Select S = Stuff((Select ' ' +coalesce(MapTo,RetVal)
                  From (
                        Select RetSeq = Row_Number() over (Order By (Select null))
                              ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
                        From  (Select x = Cast('<x>' + replace((Select replace(replace(replace(A.Phrase,'{','|| {'),'}','} ||'),' ','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A 
                        Cross Apply x.nodes('x') AS B(i)
                       ) B1
                   Left Join @FoodItem B2 on B1.RetVal = concat('{',B2.ID,'}')
                  Order by RetSeq
                  For XML Path ('')),1,1,'') 
             ) B

<强>返回

ID  NewStr
1   I want Burgers and French Fries!
2   I just want Pizza.
  

编辑 - 创建一个类似于。的UDF可能更为合适   以下

Declare @S varchar(max) = 'I want {1} and {2}!'

Select @S = replace(@S,concat('{',ID,'}'),MapTo)
  From  FoodItem 

Select @S

<强>返回

I want Burgers and French Fries!