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;
我有一大块文本字符串 @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;