在SQL Server 2008中截取文本字符串

47

我在一个SQL Server 2008数据库中有一张表。这张表有一个名为“Name”的nvarchar(256)列。不幸的是,该字段中的值包含额外的空格。例如,名称“Bill”实际上在表中存储为“Bill ”。

我想要一次性更新该表中的所有记录,以删除多余的空格。然而,令人惊讶的是,SQL没有TRIM函数。

如何一次性更新所有记录以删除额外的空格?

谢谢!

7个回答

102

你有一个RTRIM和一个LTRIM函数。你可以将它们组合起来获取所需的修剪函数。

UPDATE Table
SET Name = RTRIM(LTRIM(Name))

16

您可以使用RTrim函数从右侧删除所有空白字符。使用LTrim从左侧删除所有空白字符。例如:

UPDATE Table SET Name = RTrim(Name)

同时去除左右两侧的空格

UPDATE Table SET Name = LTrim(RTrim(Name))

这个答案应该被接受,因为 LTRIM(RTRIM(Name)) 可能比 RTRIM(LTRIM(Name)) 更有效率。 - mark
3
这取决于内部实现语言。如果是C/C++,则LTRIM必须将字符串字符向左移动,而RTRIM只需在正确的位置写入终止符'\0'。因此,在RTRIM之后进行LTRIM需要移动较少的字符。当然,在整体上并不重要,但仍然更加高效,而交换LTRIM和RTRIM的成本绝对为0。 - mark

4

SQL Server没有TRIM函数,但它有两个函数。一个专门从字符串“前面”修剪空格(LTRIM),另一个专门从字符串“末尾”修剪空格(RTRIM)。

以下类似的代码将更新表中的每条记录,修剪varchar/nvarchar字段中所有多余的空格(无论是在前面还是在后面):

UPDATE 
   [YourTableName]
SET
   [YourFieldName] = LTRIM(RTRIM([YourFieldName]))

奇怪的是,SSIS(SQL Server Integration Services)确实有一个单一的TRIM函数!


2
我会尝试这样实现一个Trim函数,它考虑了Unicode标准定义的所有空白字符(LTRIM和RTRIM甚至不修剪换行符!):

IF OBJECT_ID(N'dbo.IsWhiteSpace', N'FN') IS NOT NULL
    DROP FUNCTION dbo.IsWhiteSpace;
GO

-- Determines whether a single character is white-space or not (according to the UNICODE standard).
CREATE FUNCTION dbo.IsWhiteSpace(@c NCHAR(1)) RETURNS BIT
BEGIN
 IF (@c IS NULL) RETURN NULL;
 DECLARE @WHITESPACE NCHAR(31);
 SELECT @WHITESPACE = ' ' + NCHAR(13) + NCHAR(10) + NCHAR(9) + NCHAR(11) + NCHAR(12) + NCHAR(133) + NCHAR(160) + NCHAR(5760) + NCHAR(8192) + NCHAR(8193) + NCHAR(8194) + NCHAR(8195) + NCHAR(8196) + NCHAR(8197) + NCHAR(8198) + NCHAR(8199) + NCHAR(8200) + NCHAR(8201) + NCHAR(8202) + NCHAR(8232) + NCHAR(8233) + NCHAR(8239) + NCHAR(8287) + NCHAR(12288) + NCHAR(6158) + NCHAR(8203) + NCHAR(8204) + NCHAR(8205) + NCHAR(8288) + NCHAR(65279);
 IF (CHARINDEX(@c, @WHITESPACE) = 0) RETURN 0;
 RETURN 1;
END
GO

IF OBJECT_ID(N'dbo.Trim', N'FN') IS NOT NULL
    DROP FUNCTION dbo.Trim;
GO

-- Removes all leading and tailing white-space characters. NULL is converted to an empty string.
CREATE FUNCTION dbo.Trim(@TEXT NVARCHAR(MAX)) RETURNS NVARCHAR(MAX)
BEGIN
 -- Check tiny strings (NULL, 0 or 1 chars)
 IF @TEXT IS NULL RETURN N'';
 DECLARE @TEXTLENGTH INT = LEN(@TEXT);
 IF @TEXTLENGTH < 2 BEGIN
  IF (@TEXTLENGTH = 0) RETURN @TEXT;
  IF (dbo.IsWhiteSpace(SUBSTRING(@TEXT, 1, 1)) = 1) RETURN '';
  RETURN @TEXT;
 END
 -- Check whether we have to LTRIM/RTRIM
 DECLARE @SKIPSTART INT;
 SELECT @SKIPSTART = dbo.IsWhiteSpace(SUBSTRING(@TEXT, 1, 1));
 DECLARE @SKIPEND INT;
 SELECT @SKIPEND = dbo.IsWhiteSpace(SUBSTRING(@TEXT, @TEXTLENGTH, 1));
 DECLARE @INDEX INT;
 IF (@SKIPSTART = 1) BEGIN
  IF (@SKIPEND = 1) BEGIN
   -- FULLTRIM
   -- Determine start white-space length
   SELECT @INDEX = 2;
   WHILE (@INDEX < @TEXTLENGTH) BEGIN -- Hint: The last character is already checked
    -- Stop loop if no white-space
    IF (dbo.IsWhiteSpace(SUBSTRING(@TEXT, @INDEX, 1)) = 0) BREAK;
    -- Otherwise assign index as @SKIPSTART
    SELECT @SKIPSTART = @INDEX;
    -- Increase character index
    SELECT @INDEX = (@INDEX + 1);
   END
   -- Return '' if the whole string is white-space
   IF (@SKIPSTART = (@TEXTLENGTH - 1)) RETURN ''; 
   -- Determine end white-space length
   SELECT @INDEX = (@TEXTLENGTH - 1);
   WHILE (@INDEX > 1) BEGIN 
    -- Stop loop if no white-space
    IF (dbo.IsWhiteSpace(SUBSTRING(@TEXT, @INDEX, 1)) = 0) BREAK;
    -- Otherwise increase @SKIPEND
    SELECT @SKIPEND = (@SKIPEND + 1);
    -- Decrease character index
    SELECT @INDEX = (@INDEX - 1);
   END
   -- Return trimmed string
   RETURN SUBSTRING(@TEXT, @SKIPSTART + 1, @TEXTLENGTH - @SKIPSTART - @SKIPEND);
  END 
  -- LTRIM
  -- Determine start white-space length
  SELECT @INDEX = 2;
  WHILE (@INDEX < @TEXTLENGTH) BEGIN -- Hint: The last character is already checked
   -- Stop loop if no white-space
   IF (dbo.IsWhiteSpace(SUBSTRING(@TEXT, @INDEX, 1)) = 0) BREAK;
   -- Otherwise assign index as @SKIPSTART
   SELECT @SKIPSTART = @INDEX;
   -- Increase character index
   SELECT @INDEX = (@INDEX + 1);
  END
  -- Return trimmed string
  RETURN SUBSTRING(@TEXT, @SKIPSTART + 1, @TEXTLENGTH - @SKIPSTART);
 END ELSE BEGIN
  -- RTRIM
  IF (@SKIPEND = 1) BEGIN
   -- Determine end white-space length
   SELECT @INDEX = (@TEXTLENGTH - 1);
   WHILE (@INDEX > 1) BEGIN 
    -- Stop loop if no white-space
    IF (dbo.IsWhiteSpace(SUBSTRING(@TEXT, @INDEX, 1)) = 0) BREAK;
    -- Otherwise increase @SKIPEND
    SELECT @SKIPEND = (@SKIPEND + 1);
    -- Decrease character index
    SELECT @INDEX = (@INDEX - 1);
   END
   -- Return trimmed string
   RETURN SUBSTRING(@TEXT, 1, @TEXTLENGTH - @SKIPEND);
  END 
 END
 -- NO TRIM
 RETURN @TEXT;
END
GO


1

我知道这是一个老问题,但我刚刚找到了一种解决方法,它使用LTRIM和RTRIM创建用户定义函数。它不能处理字符串中间的双空格。

然而,解决方案很简单:

用户定义的Trim函数


0

这个函数可以从左右两侧修剪字符串。同时,它还会从字符串中删除回车符,而 LTRIM 和 RTRIM 不会执行此操作。

IF OBJECT_ID(N'dbo.TRIM', N'FN') IS NOT NULL
    DROP FUNCTION dbo.TRIM;
GO
CREATE FUNCTION dbo.TRIM (@STR NVARCHAR(MAX)) RETURNS NVARCHAR(MAX)
BEGIN
    RETURN(LTRIM(RTRIM(REPLACE(REPLACE(@STR ,CHAR(10),''),CHAR(13),''))))
END;
GO

你的函数存在问题,它没有修剪回车换行符(CRLFs),这些符号也会在字符串内被替换,这可能是不想要的。 - Christoph

0

没有一个答案是正确的

正确的答案是将列编辑为NVARCHAR,然后你会自动发现执行时会修剪。但是这段代码 UPDATE Table SET Name = RTRIM(LTRIM(Name)) 只能用于Nvarchar,如果用于CHAR或NCHAR,则无法正常工作。


你期望什么?使用CHAR和NCHAR,字符串具有固定长度。如果你从一个CHAR(30)中去掉最后的10个空字符,并再次赋值给一个CHAR(30),那么该字符串将再次填充到30个字符,使用空格。 - Christoph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接