T-SQL 同时替换字符串中的两个值

T-SQL replace two values in a string simultaneously

我有一大块文本字符串 @originalCommand,我想在其中替换值 $tablelist@dms:

目前我设法低于工作但有些行是重复动作。

SET @originalCommand    = '$tablelist='table_1', $dms='dms_1''

PRINT '*** Original command text:';
PRINT @originalCommand;

--replace variables' values in ps script
SET @replaceStart       = PATINDEX('%$tablelist=''%', @originalCommand) + LEN('$tablelist=''');
SET @replaceLength      = PATINDEX('%''%', SUBSTRING(@originalCommand, @replaceStart, LEN(@originalCommand)));
IF @tableList = ''
    SET @replaceString = CONCAT(@schemaName, '.', @tableName)
ELSE
    SET @replaceString = @tableList;

SET @newCommand         = REPLACE(@originalCommand, SUBSTRING(@originalCommand, @replaceStart, @replaceLength - 1), @replaceString);


SET @replaceStart       = PATINDEX('%$dms=''%', @newCommand) + LEN('$dms=''');
SET @replaceLength      = PATINDEX('%''%', SUBSTRING(@newCommand, @replaceStart, LEN(@newCommand)));
SET @replaceString = @dms;
SET @newCommand         = REPLACE(@newCommand, SUBSTRING(@newCommand, @replaceStart, @replaceLength - 1), @replaceString);

PRINT '';
PRINT '*** New command text:';
PRINT @newCommand;

预期结果有效,但我试图在不重复 replace 代码行的情况下实现它:

SET @dms = 'dms_new';
SET @tableName      = 'table_new';
'$tablelist='table_new', $dms='dms_new''

您可以利用 SQL 服务器的特性,它允许您在涉及多行的 select 语句中设置变量值时对变量进行多项更改。

使用此方法,您可以通过向 marker“值 table”添加条目来进行任意数量的替换。

原始命令文本中的标记可以任意顺序出现,但每个标记只能出现一次。

declare @sqlCommand nvarchar(100) = '$tablelist=''table_1'', $dms=''dms_1'''
       ,@tableList  nvarchar(100) = 'table_new'
       ,@schemaName nvarchar(100) = 'fu'
       ,@tableName  nvarchar(100) = 'bar'
       ,@dms        nvarchar(100) = 'dms_new'
;

-- Compile a table holding all the info necessary to make the substitutions
declare @swap table (pos int, numChars int, newVal nvarchar(100));

insert into @swap
    select pos.beg,pos.numChars,marker.newVal
    from (values
         ('$tablelist=''',coalesce(nullif(@tableList,''),concat(@schemaName,'.',@tableName)))
        ,(      '$dms=''',@dms)
        -- add more rows here if necessary
         ) marker(token,newVal)
         cross apply (
        select pos.beg
              ,charindex('''',@sqlCommand,pos.beg+1) - pos.beg
        from (values (charindex(marker.token,@sqlCommand) + len(marker.token))) pos(beg)
         ) pos(beg,numChars)
;

/*
   Here's where the magic happens.
   The variable will be updated once for each row in the table.
   Note that we do them from the back of the string to the front,
   so that the string positions remain valid after each substitution.

   And use stuff() rather than replace() to guarantee
   that we make exactly the substitutions we want and no more.
*/
select @sqlCommand = stuff(@sqlCommand,pos,numChars,newVal)
from @swap
order by pos desc
;

print @sqlCommand;