在字符串

时间:2016-11-06 04:50:04

标签: sql-server

我正在尝试从我的表中删除多个空格,其中包含40多个包含字符串值且大约150K行的列。

使用CURSOR,我提出了以下解决方案(作为填充我的表的存储过程的一部分),但是这不会在单次运行中删除空格。如果我多次手动单独运行update语句,则会完全删除空格。关于如何在单次运行中清理数据的任何想法?

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

3 个答案:

答案 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

如果您使用pre-SQL Server 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

答案 1 :(得分: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;

答案 2 :(得分: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