【问题标题】:Replace null character in a string in sql在sql中替换字符串中的空字符
【发布时间】:2010-02-19 17:41:37
【问题描述】:

我需要替换 sql 字符串中的空字符,我似乎找不到正确的命令来实现这一点。我使用了 replace (myString ,'\0', '') 但这似乎不起作用,任何帮助都会很棒

【问题讨论】:

    标签: sql-server-2005


    【解决方案1】:

    有效的技巧是在使用 REPLACE 之前将您的值 COLLATE 到 Latin1_General_BIN,并且还对 string_pattern 使用 nchar(0x00) COLLATE Latin1_General_BIN

    REPLACE (string_expression , string_pattern , string_replacement )

     select 
     [Terminated]      =          N'123' + nchar(0) + N'567'                                
    ,[Replaced with -] = REPLACE((N'123' + nchar(0) + N'567') COLLATE Latin1_General_BIN
                                              , nchar(0x00) COLLATE Latin1_General_BIN 
                                                     ,'-')      
    ,[Removed]        = REPLACE((N'123' + nchar(0) + N'567') COLLATE Latin1_General_BIN
                                        , nchar(0x00)      COLLATE Latin1_General_BIN
                                                ,'')    
    

    这是结果(使用输出到文本):

    Contains   Replaced with -   Removed
    ---------- ----------------- --------
    123 567    123-567           123567
    

    【讨论】:

      【解决方案2】:

      使用这个:

      REPLACE(myString, char(0), '')
      

      【讨论】:

      • 切换到使用 REPLACE(myString, char(0), '') 仍然生成返回字符串中的空字符
      • 请说明如何生成 myString 和/或示例数据。
      • 对不起,我不能详细说明,替换字符串功能有效。所描述的方式感谢您的帮助。
      • 不适用于 UNICODE!对不起,不得不大声说出来。这显然是 SQL Server Replace() 函数中的一个错误,它不会替换 nVarChar 中的空字符。是的,我尝试了 nChar(0),但它仍然不起作用。见这里:stackoverflow.com/a/2828467/555798
      • 对于 Unicode 支持,请参阅使用 COLLATE 的答案。
      【解决方案3】:

      对于拉丁字符: select REPLACE('Ho'+CHAR(0)+'mer' COLLATE SQL_Latin1_General_CP1_CS_AS, CHAR(0), '')

      对于俄语字符: select REPLACE(('Го'+CHAR(0)+'мер') COLLATE Cyrillic_General_BIN , CHAR(0), '')

      【讨论】:

        【解决方案4】:

        如果您只有ASCII (Char/VarChar) 字符串,那么这将按照@DyingCactus 的建议工作:

        REPLACE(myString, Char(0x00), '')
        

        然而,如果您正在处理 Null-Terminated Strings 并尝试修复或转换为 XML 之类的内容,并且您的数据是 Unicode (nChar/nVarChar),然后使用这个:

        (CASE WHEN UNICODE(SUBSTRING(myString, LEN(myString), 1)) = 0x0000
              THEN SUBSTRING(myString, 1, LEN(myString) - 1)
              ELSE myString END)
        

        这适用于 ASCII (Char/VarChar) 和 Unicode (nChar/nVarChar)。

        注意

        将 Replace() 函数与 Char(0) 或 nChar(0) 结合使用适用于 Unicode (nChar/nVarChar)。
        这是 SQL Server Replace() 函数中的一个错误

        您可以转换为 VarChar,然后使用 Replace(),但是您可能会丢失任何您可能打算保留的特殊 Unicode/非 ASCII 字符。
        否则,您一开始就不会使用 Unicode 数据类型(占用两倍的空间来存储数据)。

        如果您的 Unicode 字符串中混入了 Null-Characters(不仅在结尾处),并且出于查询的目的,维护 Unicode 特定的字符并不重要,那么作为最后的手段,您可以使用这个:

        (CASE WHEN myString LIKE (N'%' + nCHAR(0x0000) + N'%')--Has Null-Character(s).
              THEN REPLACE(CAST(myString as VarChar(MAX)), Char(0x00), '')--Cast as ASCII
              ELSE myString END)--Else, leave as Unicode to preserve Unicode-Only chars.
        

        【讨论】:

          【解决方案5】:

          这些函数从 Unicode 字符串中删除空字符,至少在 SQL Server 2008 中是这样。

          -- Remove all null characters
          CREATE FUNCTION RemoveNulls(@s nvarchar(max))
          RETURNS nvarchar(max)
          AS
          BEGIN
              DECLARE @r nvarchar(max);
              SET @r = REPLACE(@s COLLATE Latin1_General_BIN, NCHAR(0), N'');
              RETURN @r; 
          END
          
          -- Remove all characters from the first null character
          CREATE FUNCTION TrimNull(@s nvarchar(max))
          RETURNS nvarchar(max)
          AS
          BEGIN
              DECLARE @r nvarchar(max);
              DECLARE @i int = CHARINDEX(NCHAR(0), @s COLLATE Latin1_General_BIN);
              IF @i = 0
                  SET @r = @s;
              ELSE
                  SET @r = SUBSTRING(@s, 1, @i - 1);
              RETURN @r; 
          END
          
          -- Example usage
          DECLARE @s nvarchar(10) = N'Test' + NCHAR(0) + N'!';
          SELECT dbo.RemoveNulls(@s), dbo.TrimNull(@s);
          --> Test!, Test
          

          在我的例子中,来自 ODBC 的字段被填充为 8000 个带有 null 的字符,并且 TrimNull 比 RemoveNulls 快得多。

          【讨论】:

          • 我希望我能给这 10 票。这是我发现的唯一一篇使用 COLLATE Latin1_General_BIN 而不是 SQL_Latin1_General_CP1_CI_AS 的帖子。后者对我不起作用,但你的整理可以!靠我自己解决不是一件容易的事。谢谢!
          【解决方案6】:

          我不完全确定您的字符串有什么问题,但这里有一些可以尝试的方法,您使用的是 varchar 吗?编辑问题并提供更多详细信息:

          如果字符串中有 NULL 字符:

          declare @x varchar(10)
          set @x='123'+char(0)+'456'
          SELECT @x AS Has_NULL_in_it, REPLACE(@x, char(0), '') AS Has_NULL_removed
          

          输出:

          Has_NULL_in_it Has_NULL_removed
          -------------- ----------------
          123 456        123456
          
          (1 row(s) affected)
          

          如果你不能分辨字符串中的字符,试试这个 ASCII:

          DECLARE @y varchar(10),@c int
          set @y='123'+char(0)+'456'
          set @c=0
          WHILE @c<LEN(@y)
          BEGIN
              SET @c=@c+1
              PRINT CONVERT(varchar(5),@c)+' - '+SUBSTRING(@y,@c,1)+' - CHAR('+CONVERT(varchar(5),ASCII(SUBSTRING(@y,@c,1)))+')'
          END
          

          输出:

          1 - 1 - CHAR(49)
          2 - 2 - CHAR(50)
          3 - 3 - CHAR(51)
          4 - - CHAR(0)
          5 - 4 - CHAR(52)
          6 - 5 - CHAR(53)
          7 - 6 - CHAR(54)
          

          试试这个 unicode:

          DECLARE @y nvarchar(10),@c int
          set @y='123'+char(0)+'456'
          set @c=0
          WHILE @c<LEN(@y)
          BEGIN
              SET @c=@c+1
              PRINT CONVERT(nvarchar(5),@c)+' - '+SUBSTRING(@y,@c,1)+' - UNICODE('+CONVERT(nvarchar(5),UNICODE(SUBSTRING(@y,@c,1)))+')'
          END
          

          如果您的字符串完全为 NULL:

          declare @z varchar(10)
          set @z=NULL
          select @z AS IS_NULL, ISNULL(@Z,'') AS NULL_Removed
          

          输出:

          IS_NULL    NULL_Removed
          ---------- ------------
          NULL       
          
          (1 row(s) affected)
          

          【讨论】:

          • 这个答案的第一部分取决于排序规则的选择。
          【解决方案7】:

          如果您要连接值以获取字符串,请使用 IsNull(value, replacement) 以避免出现空值,或将 CONCAT_NULL_YIELDS_NULL 设置为 ON 以避免结果出现空字符串。

          【讨论】:

          • 永远不要使用 CONCAT_NULL_YIELDS_NULL,SQL Server 2008 之后将不再支持它,请确保它默认设置为 ON 并处理与 NULL 相关的所有字符串连接: COALESCE、ISNULL 和/或 NULLIF
          【解决方案8】:

          我们遇到了同样的问题:在 nvarchar 字段中结束 \0 字符并且无法用任何建议的 REPLACE 变体替换它(SQL Server 2008)。使用时

          LEFT(Bar, LEN(Bar)-1)
          

          它与 \0 一起切断了最后一个常规字符!

          我们现在纠正字段的解决方案是(乍一看可能很奇怪):

          UPDATE Foo
              SET Bar = LEFT(Bar, LEN(Bar))
          WHERE RIGHT(Bar, 1) = CHAR(0)
          

          【讨论】:

            【解决方案9】:

            已解决的示例

            CREATE FUNCTION dbo.F_ReplaceNullChar( @STR NVARCHAR(MAX) )
            RETURNS NVARCHAR(MAX)
            AS
            BEGIN
            DECLARE @i INT=0
            DECLARE @RET NVARCHAR(MAX)=''
                WHILE @I<LEN(@STR) 
                BEGIN 
                    SET @i=@i+1
                    IF UNICODE(SUBSTRING(@STR,@i,1)) <> 0x0000
                        SET @RET=@RET+SUBSTRING(@STR,@i,1)
            
                END
                RETURN @RET
            END
            GO
            
            SELECT LEN(mycol) lenbefore,mycol,
             LEN( dbo.F_ReplaceNullChar(mycol)) lenafter, dbo.F_ReplaceNullChar(mycol) mycolafter 
            FROM mytab
            

            【讨论】:

              【解决方案10】:

              选择 zz.xx , 替换(zz.xx, '', '') 从 ( 选择 t.string_with_null, ( 选择 s.string_with_null+'' 从 TABLE_1 秒 其中 s.token_hash = t.token_hash 对于 xml 路径('') ) xx 从 TABLE_1 t(无锁) )zz

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2013-01-04
                • 2012-03-26
                • 2011-04-03
                • 2013-05-09
                • 2013-07-18
                • 1970-01-01
                • 2014-11-12
                • 1970-01-01
                相关资源
                最近更新 更多