Sql-Server
TSQL 從文本值中刪除字元
我一直在使用 REPLACE 函式從表中的文本值中刪除字元。它隨著時間的推移而增長,現在查詢非常混亂。
我能做些什麼來提高效率?是否有我可以實施的正則表達式範例?
詢問:
SELECT REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE(dbo.[RemoveNumericCharacters](Filename), '.xlsx', '') , '.xls', '') ,'csv', '') ,'---_pdf', '') ,'.', '') ,'-Jun-', '') ,'-Jul-', '') ,'Jul', '') ,'__', '_') as 'ConvertedFilename' FROM @Files
功能:
ALTER Function [dbo].[RemoveNumericCharacters](@Temp nvarchar(1000)) Returns nvarchar(1000) AS Begin Declare @NumRange as varchar(50) = '%[0-9]%' While PatIndex(@NumRange, @Temp) > 0 Set @Temp = Stuff(@Temp, PatIndex(@NumRange, @Temp), 1, '') Return @Temp End
我認為您最好創建一個過濾表,在其中放置替換字元串對,然後您可以創建一個函式來使用您的過濾表刪除源字元串。
這是範例
use tempdb -- filter table create table dbo.Filter (id int identity, src varchar(100), tgt varchar(100)); -- populate a few filtering pairs insert into dbo.Filter (src, tgt) values ('.xlsx', '') , ('csv', '') , ('__', '_') , ('-Jun-', ''); -- your source table create table #s (mycol varchar(1000)) -- populate source column insert into #s (mycol) values ('this .xlsx file is not __ created in -Jun- but in June') , ('this csv file should be removed -Jun-') go -- filtering function create function dbo.funcReplace (@s varchar(1000)) returns varchar(1000) as begin declare @src varchar(100), @tgt varchar(100); declare @curS cursor; set @curS = cursor for select src, tgt from dbo.Filter open @curS fetch next from @curS into @src, @tgt; while @@fetch_status = 0 begin set @s=replace(@s, @src, @tgt); fetch next from @curS into @src, @tgt; end return @s; end go -- before replacement select bfr_replacement = mycol from #s -- after replacement select after_replacment=dbo.funcReplace(mycol) from #s
將來,如果您需要更多替換,只需將它們添加到表中
dbo.Filter
,您無需在其他地方更改任何內容。
@jyao 發布了一個很好的優雅解決方案。但是,如果您對在 SQL Server 中使用游標不感興趣…這裡您有一個替代解決方案,只需使用分隔符拆分文本(因為您正在使用 file_name 字元串,所以一個好的分隔符可能是“:”).. . 這並不優雅,但我會測試這兩種解決方案,看看哪一種對於大量數據更快。不幸的是,我無法在我的電腦上安裝 SQL Server,所以我在 Oracle 中完成了所有操作,然後將程式碼翻譯為 MsSQL…如果您發現任何語法問題,請正確修復它。
CREATE FUNCTION [dbo].[ReplaceUndesiredText](@EvaluatedText nvarchar(1000)) Returns nvarchar(1000) AS Begin Declare @old_list varchar(500)='__:.xlsx:.xls:csv:---_pdf:.:-Jun-:-Jul-:', @new_list varchar(500)='_::::::::', @separator char(1)=':' @old_val varchar(50), @new_val varchar(50), @final_pos_old int=1, @found_pos_old int=1, @begin_pos_old int, @final_pos_new int=1, @found_pos_new int=1, @begin_pos_new int While @found_pos_old > 0 BEGIN select @begin_pos_old = @final_pos_old, @begin_pos_new = @final_pos_new select @found_pos_old = ISNULL(CHARINDEX(@separator,@old_list,@begin_pos_old),0), @found_pos_new = ISNULL(CHARINDEX(@separator,@new_list,@begin_pos_new),0) if (@found_pos_old>0) then select @old_val = SUBSTRING(@old_list,@begin_pos_old,@found_pos_old - @begin_pos_old), @new_val = SUBSTRING(@new_list,@begin_pos_new,@found_pos_new - @begin_pos_new) set @evaluated_text = REPLACE(@evaluated_text,@old_val,@new_val) end if select @final_pos_new = @found_pos_new + 1, @final_pos_old = @found_pos_old + 1 END Return @EvaluatedText End