【发布时间】:2010-02-19 17:41:37
【问题描述】:
我需要替换 sql 字符串中的空字符,我似乎找不到正确的命令来实现这一点。我使用了 replace (myString ,'\0', '') 但这似乎不起作用,任何帮助都会很棒
【问题讨论】:
标签: sql-server-2005
我需要替换 sql 字符串中的空字符,我似乎找不到正确的命令来实现这一点。我使用了 replace (myString ,'\0', '') 但这似乎不起作用,任何帮助都会很棒
【问题讨论】:
标签: sql-server-2005
有效的技巧是在使用 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
【讨论】:
使用这个:
REPLACE(myString, char(0), '')
【讨论】:
对于拉丁字符: 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), '')
【讨论】:
如果您只有有 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.
【讨论】:
这些函数从 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 快得多。
【讨论】:
我不完全确定您的字符串有什么问题,但这里有一些可以尝试的方法,您使用的是 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)
【讨论】:
如果您要连接值以获取字符串,请使用 IsNull(value, replacement) 以避免出现空值,或将 CONCAT_NULL_YIELDS_NULL 设置为 ON 以避免结果出现空字符串。
【讨论】:
我们遇到了同样的问题:在 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)
【讨论】:
已解决的示例
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
【讨论】:
选择 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
【讨论】: