Sql-Server

TSQL 從文本值中刪除字元

  • July 10, 2018

我一直在使用 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

引用自:https://dba.stackexchange.com/questions/211764