2016-11-06 43 views
1

我試圖從我的表中刪除多個空格,其中包含40個列以及其中的字符串值和約150K行。在字符串中遞歸地刪除空間

使用CURSOR,我想出了以下解決方案(作爲我的存儲過程的一部分填充我的表),但是這並不能刪除單次運行中的空白。如果我多次手動運行更新語句,空格將被完全刪除。有關如何在單次運行中清理數據的想法?

Declare @col nvarchar(128) 
Declare StringCol CUSRSOR for 
    SELECT COLUMN_NAME 
    FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE TABLE_NAME = 'TableName' 
    AND DATA_TYPE = 'varchar' 
OPEN StringCol 
FETCH NEXT FROM StringCol into @col; 
WHILE @@FETCH_STATUS = 0   
    BEGIN 
    UPDATE TableName 
    SET  @col = LTRIM(RTRIM(REPLACE(@col, ' ', ' '))) 
    WHERE @col LIKE '% %' 

    FETCH NEXT FROM StringCol into @col 
END 

CLOSE StringCol 
Deallocate StringCol 

END 
+0

您是否試圖將雙空格轉換爲單個空格,或者完全刪除所有空格? –

回答

0

如果您有SQL Server 2016,則可以使用STRING_Split或其他版本的類似UDF函數。關鍵是轉換詞成列,採取非空間,把他們帶回一個價值

Declare @col nvarchar(128) 
Declare StringCol CUSRSOR for 
    SELECT COLUMN_NAME 
    FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE TABLE_NAME = 'TableName' 
    AND DATA_TYPE = 'varchar' 
OPEN StringCol 
FETCH NEXT FROM StringCol into @col; 
WHILE @@FETCH_STATUS = 0   
    BEGIN 
    UPDATE TableName 
    SET  @col = CONVERT(VARCHAR(MAX), 
       (
       select Value + ' ' 
        from STRING_SPLIT (@col, ' ') 
       where value <>'' for xml path('') 
       ) 
      ) 
    WHERE @col LIKE '% %' 

    FETCH NEXT FROM StringCol into @col 
END 

CLOSE StringCol 
Deallocate StringCol 

END 

如果使用-SQL預服務器2016年,那麼這一個UDF STRING_SPLIT功能:

CREATE FUNCTION [dbo].[STRING_SPLIT] 
(
    @String nvarchar(max),  -- String to be parsed 
    @Delm nchar(1)=',' 
) 
returns @Table TABLE (/*ID int identity(1,1), */ value nvarchar(max)) 
Begin 
    INSERT @Table(value) 
    SELECT ltrim(t.val.value('.', 'VARCHAR(100)')) AS value 
    FROM(
      SELECT Convert(XML, '<M>' + REPLACE(@String, @Delm, '</M><M>') + '</M>') AS x 
     ) AS A CROSS APPLY x.nodes ('/M') AS t(val) 
    Return 
End 
0

嘗試

-- code #1 
CREATE FUNCTION [dbo].[AllTrim] (@Texto varchar(8000)) 
returns table as 
return 
with xTrim as (
SELECT Rep= 1, 
     Trimmed= Replace(Ltrim(Rtrim(@Texto)), space(2), space(1)) 

union all 

SELECT Charindex(space(2), Trimmed), 
     Replace(Trimmed, space(2), space(1)) 
    from xTrim 
    where Rep > 0 
) 
SELECT Trimmed 
    from xTrim 
    where Rep = 0; 
go 

演示使用方法:

-- code #2 
declare @TableName table (col1 varchar(200), col2 varchar(800)); 

INSERT into @TableName values 
    (' aa  aaa aaaa  a ', 'b b '); 

SELECT T1.col1, T2.Trimmed as [col1 trimmed], 
     T1.col2, T3.Trimmed as [col2 trimmed] 
    from @TableName as T1 
     outer apply dbo.AllTrim(T1.col1) as T2 
     outer apply dbo.AllTrim(T1.col2) as T3; 

演示更新:

-- code #3 
declare @TableName table (ID int identity, 
          col1 varchar(200), col2 varchar(800)); 

INSERT into @TableName (col1, col2) values 
    (' aa  aaa aaaa  a ', 'b b '), 
    ('xxx  xx xx xxxxx', NULL); 

with tbTrimmed as (
SELECT T1.ID, 
     T2.Trimmed as [col1 trimmed], 
     T3.Trimmed as [col2 trimmed] 
    from @TableName as T1 
     outer apply dbo.AllTrim(T1.col1) as T2 
     outer apply dbo.AllTrim(T1.col2) as T3 
)  
UPDATE TN 
    set col1= [col1 trimmed], 
     col2= [col2 trimmed] 
    from @TableName as TN 
     inner join tbTrimmed as Tr on TN.ID = Tr.ID; 
0

使用CLR函數,你可以做到這一點使用正則表達式:

Declare cnvarchar(max) 
Declare @col nvarchar(128) 
Declare StringCol CUSRSOR for 
    SELECT COLUMN_NAME 
    FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE TABLE_NAME = 'TableName' 
    AND DATA_TYPE = 'varchar' 
OPEN StringCol 
FETCH NEXT FROM StringCol into @col; 
WHILE @@FETCH_STATUS = 0   
    BEGIN 

    --{ this is the key bit 
    set @sql =' 
    UPDATE TableName 
    SET  ' + quotename(@col) + ' = dbo.RegexReplace(ltrim(rtrim(' + quotename(@col) + ')), ''\s\s+'', ' ' 
    WHERE ' + quotename(@col) + ' LIKE ''% %'' 
    or  ' + quotename(@col) + ' LIKE '' %'' 
    or  ' + quotename(@col) + ' LIKE ''% '' 

    ' 
    --} this is the key bit 

    --print @sql --for debugging 
    exec @sql 

    FETCH NEXT FROM StringCol into @col 

END 

CLOSE StringCol 
Deallocate StringCol 

END 

相關CLR代碼見https://msdn.microsoft.com/en-us/library/ff878119.aspx