【问题标题】:How to remove trailing spaces like characters in SQL Server如何删除 SQL Server 中的字符等尾随空格
【发布时间】:2018-11-16 00:50:48
【问题描述】:

我编写了一个简单的选择查询,使用名为“名称”的字段从表中选择一行。名称是连续的,显示为“RM001”、“RM002”、“RM003”……。这个问题是它没有通过以下查询获取“RM004”

-- Trim Name Field
UPDATE [dbo].[RoutineMaintenanceTask] SET  = LTRIM(RTRIM([dbo].[RoutineMaintenanceTask].Name));

-- Select the record
SELECT   *
FROM     [dbo].[RoutineMaintenanceTask]
WHERE    Name = 'RM004'

当我使用以下查询检查值的长度时,它显示长度为 7

-- Check the length
select (Name), len(Name) AS TextLength
from [dbo].[RoutineMaintenanceTask]
where Name = 'RM004'

很明显这个名字前后有一些字符,但不是空格。

不仅如此,我还通过 Visual Studio 调试器检查了该值,并没有发现任何异常。

然而,当我从 SQL 结果窗格中复制“名称”的值并将其复制到记事本++,并打开特殊字符时,我能够看到这一点。

最终,我能够通过在 select 语句之前添加以下代码来解决此问题

-- Remove the tail
UPDATE [dbo].[RoutineMaintenanceTask] SET Name = substring(Name,1,5);

我只需要知道我如何知道在这种情况下隐藏的字符是什么,以及如何在不使用子字符串的情况下消除它(因为在这种情况下,这很容易,因为我知道长度)。

PS- 我知道使用“名称”关键字作为表格的字段不是一个好习惯,但在这种情况下,与此无关。

【问题讨论】:

  • 特殊字符只有在您不期望它们时才是特殊的。这实际上只是放置控件和约束以控制插入的数据的问题。如果该列中的所有值都恰好是 5 个字符,为什么不将其定义为 CHAR(5)?如果 I 字母 [A-Z] 和数字 [0-9] 是唯一有效的字符,那么应该使用 CHECK 约束和/或“代替”触发器来强制执行。
  • 就检测已经存在的内容而言... WHERE t.Name NOT LIKE '%[^0-9a-Z]%'
  • 也许你应该使用ASCII() 来检查它是什么特殊字符,然后再使用substring() 它。如果没记错的话,notepad++ 有一个插件可以显示 ascii 字符
  • @JasonA.Long,松鼠,非常感谢您的努力。我写了一个查询来显示未知字符,它将这些字符识别为换行和回车。我被你的cmets启发了。您可以在此处查看查询。 drive.google.com/open?id=1qicbv7aNLSbzNYQEBILGfQnktpimRq-F
  • @KushanRandima - 没有理由使用循环或光标来遍历字符。请参阅答案部分以获得更好的选择...

标签: sql sql-server character special-characters trim


【解决方案1】:

很可能是 char(9)、char(10) 或 char(13)(tab、lf、cr;分别)。

您可以在这里阅读它们:https://docs.microsoft.com/en-us/sql/t-sql/functions/char-transact-sql?view=sql-server-2017

您可以使用REPLACE() 删除它们。

如:

DECLARE @VARIABLE VARCHAR(10)

SET @VARIABLE='RM004'+CHAR(10)+CHAR(10)

SELECT @VARIABLE, LEN(@VARIABLE)

SET @VARIABLE = REPLACE(@VARIABLE, CHAR(9),'')
SET @VARIABLE = REPLACE(@VARIABLE, CHAR(10),'')
SET @VARIABLE = REPLACE(@VARIABLE, CHAR(13),'')

SELECT @VARIABLE, LEN(@VARIABLE)

【讨论】:

  • 你是对的。我刚刚编写了一个脚本来打印“名称”值的每个字符的 ASCII 值。额外的字符是 13 和 10。非常感谢您的考虑。
  • 我无法点击它,因为我位于阻止谷歌驱动器的防火墙后面,但很高兴你把它解决了!
【解决方案2】:
DECLARE @string VARCHAR(8000) = 'RM004
     ';

WITH 
    cte_n1 (n) AS (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (n)), 
    cte_n2 (n) AS (SELECT 1 FROM cte_n1 a CROSS JOIN cte_n1 b),
    cte_Tally (n) AS (
        SELECT TOP (DATALENGTH(@string))
            ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
        FROM
            cte_n2 a CROSS JOIN cte_n2 b
        )
SELECT 
    position = t.n,
    char_value = SUBSTRING(@string, t.n, 1),
    ascii_value = ASCII(SUBSTRING(@string, t.n, 1))
FROM
    cte_Tally t;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-24
    • 1970-01-01
    • 1970-01-01
    • 2018-05-26
    • 2016-09-20
    • 1970-01-01
    • 2015-04-27
    相关资源
    最近更新 更多