当我想获取非空或空字符串的记录时,我正在排除SQL Server输出中的一些奇怪现象:
SELECT myString
FROM myTable
WHERE myString IS NOT NULL OR myString != ''
除了显然适合的记录(返回到SSMS网格的字符串值)之外,我还看到网格单元格为空白的记录。当我选择单元格并尝试复制时,我的剪贴板管理器(clipmate.com)会抱怨数据无效。
如果我将查询输出到文件而不是网格,然后通过十六进制字符模式进行检查,果然 - 有些字符我不希望(更不想要)在那里。< / p>
我的数据库归类值的整理显示为:SQL_Latin1_General_CP1_CI_AS
我如何消除任何/所有不可见的角色?
答案 0 :(得分:0)
可以尝试这个,将删除任何不可打印的字符。
CREATE FUNCTION [dbo].[RemoveNonPrintableChars]
(
@p_string varchar(max)
)
RETURNS varchar(max)
AS
BEGIN
declare @l_pos int = 1
declare @l_str varchar(max) = ''
while (@l_pos <= len(@p_string))
begin
if (ascii(substring(@p_string,@l_pos,1)) >=32)
begin
set @l_str=@l_str+substring(@p_string,@l_pos,1)
end
set @l_pos = @l_pos+1
end
return @l_str
END
declare
@l_str varchar(max) = 'andrew'--select char(7)
select dbo.[RemoveNonPrintableChars] (@l_str)
set @l_str = 'andrew'+char(7)-- add NP character
select dbo.[RemoveNonPrintableChars] (@l_str)
答案 1 :(得分:0)
如果您偶然无法使用UDF。
你可能会注意到我不是在这里剥离控制字符,我用空格替换它们,以免连接字符串。
Declare @YourTable table (SomeField varchar(50))
Insert Into @YourTable values
('Michael'+char(13)+char(10)+'LastName')
Select A.*
,B.Value
From @YourTable A
Cross Apply (
Select Value = replace(replace((
Select ''+C
From (
Select N,C=case when ASCII(Substring(A.SomeField,N ,1))>31 then Substring(A.SomeField,N ,1) else '{--space--}' end
From ( Select Top (Len(A.SomeField)) N=Row_Number() Over (Order By Number) From master..spt_values ) N
) C Order by N
For XML Path('') ) ,'{--space--}',' '),' ',' ')
) B
返回
SomeField Value
Michael Michael LastName
LastName
修改强>
但是,如果您确实希望UDF考虑以下非线性方法
CREATE FUNCTION [dbo].[udf-Str-Strip-Control](@S varchar(max))
Returns varchar(max)
Begin
;with cte1(N) As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
cte2(C) As (Select Top (32) Char(Row_Number() over (Order By (Select NULL))-1) From cte1 a,cte1 b)
Select @S = Replace(@S,C,' ')
From cte2
Return LTrim(RTrim(Replace(Replace(@S,' ',' '),' ',' ')))
End
--Select [dbo].[udf-Str-Strip-Control]('Michael'+char(13)+char(10)+'LastName') --Returns: Michael LastName
答案 2 :(得分:0)
我更喜欢John的答案,如果您想控制是否包含某些控制字符,可能会修改它们。这是我过去用来清理一些字符串的函数。
create function dbo.fnCleanVarchar (
@StringParameter varchar(max)
, @CleanStyle tinyint = 1
) returns varchar(max) as
begin;
if @StringParameter is null
return null;
if @CleanStyle > 3 set @CleanStyle = 1;
declare @StringReturn varchar(max);
declare @StringLength int;
declare @CharacterCode int;
declare @CharacterCodePosition int;
set @StringReturn = '';
set @StringLength = len(@StringParameter);
set @CharacterCodePosition = 1;
while @CharacterCodePosition <= @StringLength
begin
set @CharacterCode = ascii(substring(@stringParameter , @CharacterCodePosition , 1))
-- Removes Unprintable Characters 0-8,12,14-31
-- If Style = 1, Remove Unprintable Characters except Tab (9), New Line (10), Carraige Return (13)
-- If Style = 2, Remove Unprintable Characters except character 9 (Tab)
-- If Style = 3, Remove Unprintable Characters and character 9 (Tab)
set @StringReturn = @StringReturn + case
when @CharacterCode >31
then char(@CharacterCode)
when @Style = 3
then ''
when @Style = 2 and @CharacterCode = 9
then char(9)
when @Style = 1 and @CharacterCode in ( 9 , 10 , 13 )
then char(@CharacterCode)
else ''
end;
set @CharacterCodePosition = @CharacterCodePosition + 1
end;
if len(@StringReturn) = 0
return null;
return @StringReturn
end;
答案 3 :(得分:0)
检查不可见字段与查找不可见字符直接相关,因此请考虑以下两个注意事项:
注意1:SQL Server will auto-trimming spaces条款中N' ' = N''
为真,并且空字符的任何连续字符串;
空字符是一个等于N''
的字符。
注意2:有65536个Unicode字符,您可以使用如下查询查看它们:
WITH CTE(i, c) AS (
SELECT 0, NCHAR(0) COLLATE SQL_Latin1_General_CP1_CI_AS --I add COLLATE to express your collation but I think it is optional
UNION ALL
SELECT i+1, NCHAR(i+1) COLLATE SQL_Latin1_General_CP1_CI_AS
FROM CTE
WHERE i < 65535
)
SELECT *
FROM CTE
OPTION ( MaxRecursion 0 );
其中一些不可见且为空,如NCHAR(0), NCHAR(12288), ...
,
其中一些不可见且不为空,如NCHAR(1), ...
,
其中一些可见和空,如NCHAR(502), ...
!!!!。
因此,如果您的字段是
nvarchar
字符串,则过滤不可见字符会遇到很大问题,对于varchar
字符串,您会遇到问题但更少不止于此。
附注:您可以使用COALESCE(myString, '') != ''
代替您的;)。
摘要:
对于一个小针,不要制造锤机!
当这种行为对你来说并不那么重要时,你的项目就不会尝试改变或处理或创建你自己的相等字符串函数;)。
检查字符串是否可见(返回1)或不是(返回0)的示例函数可以是这样的:
CREATE FUNCTION IsVisible ( @string varchar(max) )
RETURNS bit
AS
BEGIN
DECLARE @pString varchar(max) = @string;
WITH InvisibleChars AS (
SELECT c COLLATE SQL_Latin1_General_CP1_CI_AS AS c
FROM (VALUES (CHAR(0)), (CHAR(1)), (CHAR(9)), (CHAR(10)),
(CHAR(11)), (CHAR(12)), (CHAR(13)), (CHAR(28)),
(CHAR(29)), (CHAR(30)), (CHAR(31)), (CHAR(32)),
(CHAR(160)) -- Above characters are non-visibles
) t(c)
)
SELECT @pString = REPLACE(@pString, c, '')
FROM InvisibleChars;
RETURN CASE WHEN @pString = '' THEN 0 ELSE 1 END;
END
GO