2017-08-12 67 views
1

我在优化SQL查询以执行一些数据清理方面存在问题。SQL Server更新语句的性能

事实上,我有一个表格,它是一个多重特殊字符和单词的引用。让我们把它ABNORMAL(ID,PATTERN)

我也有另一个表含,我想从它消除存在于表ABNORMAL所有字符来清洗柱(NAMEINDIVIDUALS

目前,我试图使用更新语句,但我不知道是否有更好的方法来做到这一点。

方法的一个

使用while循环来构建一个空白'一个替换包含所有字符从ABNORMALS和使用做一个更新内置REPLACE

DECLARE @REPLACE_EXPRESSION nvarchar(max) ='REPLACE(NAME,'''','''')' 
DECLARE @i int = 1 
DECLARE @nbr int = (SELECT COUNT(*) FROM ABNORMAL) 
-- CURRENT_CHARAC 
DECLARE @CURRENT_CHARAC nvarchar(max) 
-- NEW REPLACE EXPRESSION TO IMBRICATE INTO THE REPLACE EXPRESSION VARIABLE 
DECLARE @CURR_REP NVARCHAR(max) 
-- STRING TO BUILD AN SQL QUERY CONTAINING THE REPLACE EXPRESSION 
DECLARE @UPDATE_QUERY nvarchar(max) 
WHILE @i < @nbr 
BEGIN 
    SELECT @CURRENT_CHARAC=PATTERN FROM CLEANSING_STG_PRISM_FRA_REF_UNSIGNIFICANT_VALUES WHERE [email protected] ; 
    SET @REPLACE_EXPRESSION = REPLACE(@REPLACE_EXPRESSION ,'NAME','REPLACE(NAME,'+''''[email protected]_CHARAC+''''+','''')') 
    set @[email protected]+1 
END 
SET @UPDATE_QUERY = 'UPDATE INDIVIDUAL SET NAME ='+ @REPLACE_EXPRESSION 
EXEC sp_executesql @UPDATE_QUERY 

方法有两个

使用while循环选择异常中的每个字符并使用包含要删除字符的替换进行更新:

DECLARE @i int = 1 
DECLARE @nbr int = (SELECT COUNT(*) FROM ABNORMAL) 
-- CURRENT_CHARAC 
DECLARE @CURRENT_CHARAC nvarchar(max) 
-- STRING TO BUILD AN SQL QUERY CONTAINING THE REPLACE EXPRESSION 
DECLARE @UPDATE_QUERY nvarchar(max) 
WHILE @i < @nbr 
BEGIN 
    SELECT @CURRENT_CHARAC=PATTERN FROM CLEANSING_STG_PRISM_FRA_REF_UNSIGNIFICANT_VALUES WHERE [email protected] ; 
    UPDATE INDIVIDUAL 
    SET NAME = REPLACE(NAME,@CURRENT_CHARAC,'') 
    SET @[email protected]+1 
END 

我已经测试了两百万条记录的两种方法,并且我发现第一种方法比第二种方法更快。我会知道你是否已经做了一些类似和新的(更好的)想法来尝试。

回答

0

如果您正在使用SQL Server 2017你可以使用TRANSLATE,避免动态SQL:

SELECT i.* 
    , REPLACE(TRANSLATE(i.NAME, f, REPLICATE('!', s.l)), '!', '') AS cleansed 
FROM INDIVIDUALS i 
OUTER APPLY (SELECT STRING_AGG(PATTERN, '') AS f 
        ,LEN(STRING_AGG(PATTERN,'')) AS l 
      FROM ABNORMAL) AS s 

DBFiddle Demo


反正第一次的做法是更好的becasue你做一个UPDATE,用第二种方法你在一次删除字符一个字符(所以你将有多个UPDATE)。

我也会用两种方法跟踪事务日志的增长。

+0

你好,感谢您的反馈。不幸的是,我使用的是SQL Server 2016.但是,请您澄清一下“跟踪事务日志”是什么意思?以及如何优化我的查询? –

0

如果没有太多字符需要清理,那么这个技巧可能会奏效。

基本上,您将生成1个大的更新语句,并将表中的每个值替换为要删除的字符。

示例代码:

测试数据(使用临时表)

create table #ABNORMAL_CHARACTERS (id int identity(1,1), chr varchar(30)); 
insert into #ABNORMAL_CHARACTERS (chr) values ('!'),('&'),('#'); 

create table #INDIVIDUAL (id int identity(1,1), name varchar(30)); 
insert into #INDIVIDUAL (name) values ('test 1 &'),('test !&#2'),('test 3'); 

代码:

declare @FieldName varchar(30) = 'name'; 
declare @Replaces varchar(max) = @FieldName; 
declare @UpdateSQL varchar(max); 

select @Replaces = concat('replace('[email protected]+', ', ''''+chr+''','''')') from #ABNORMAL_CHARACTERS order by id; 

set @UpdateSQL = 'update #INDIVIDUAL 
set name = '[email protected] + ' 
where exists (select 1 from #ABNORMAL_CHARACTERS where charindex(chr,name)>0)'; 

exec (@UpdateSQL); 

select * from #INDIVIDUAL; 

测试here on rextester

如果你有一个可以做正则表达式替换的UDF。 例如here
然后@Replaces变量可以简化为只有1个RegexReplace函数和一个模式。