Sql server SQL Server-删除所有不可打印的ASCII字符

Sql server SQL Server-删除所有不可打印的ASCII字符,sql-server,sql-server-2014,Sql Server,Sql Server 2014,我们最近从SQL Server 2012迁移到SQL Server 2014,所有FOR XML代码都开始抛出有关不可打印ASCII字符的错误。 我编写了这个可怕的函数来删除不可打印的ASCII字符作为快速修复。我想换个更干净的。有办法做到这一点吗 ALTER FUNCTION [dbo].[remove_non_printable_chars] (@input_string nvarchar(max)) RETURNS nvarchar(max) BEGIN RETURN RE

我们最近从SQL Server 2012迁移到SQL Server 2014,所有FOR XML代码都开始抛出有关不可打印ASCII字符的错误。 我编写了这个可怕的函数来删除不可打印的ASCII字符作为快速修复。我想换个更干净的。有办法做到这一点吗

ALTER FUNCTION [dbo].[remove_non_printable_chars]
(@input_string nvarchar(max))
RETURNS nvarchar(max)
BEGIN
    RETURN
    REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
    REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
    REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
    REPLACE(REPLACE(@input_string,
        CHAR(1), ''),CHAR(2), ''),CHAR(3), ''),CHAR(4), ''),CHAR(5), ''),CHAR(6), ''),CHAR(7), ''),CHAR(8), ''),CHAR(9), ''),CHAR(10), ''),
        CHAR(11), ''),CHAR(12), ''),CHAR(13), ''),CHAR(14), ''),CHAR(15), ''),CHAR(16), ''),CHAR(17), ''),CHAR(18), ''),CHAR(19), ''),CHAR(20), ''),
        CHAR(21), ''),CHAR(22), ''),CHAR(23), ''),CHAR(24), ''),CHAR(25), ''),CHAR(26), ''),CHAR(27), ''),CHAR(28), ''),CHAR(29), ''),CHAR(30), ''),
        CHAR(31), ''), NCHAR(0) COLLATE Latin1_General_100_BIN2, '')
END
下面是关于破坏的XML代码的示例。这不是我写的。它已经在代码库中

SELECT @HTMLTableData =
(
    SELECT  HTMLRows 
    FROM (
        SELECT N'<tr>' + HTMLRow + N'</tr>' AS HTMLRows 
        FROM @HTMLRowData
    ) mi            
    FOR XML PATH(''), TYPE
).value('/', 'NVARCHAR(MAX)')
联机版本:

create function [dbo].[remove_non_printable_chars] (@input_string nvarchar(max))
returns table with schemabinding as return (
  select 
    replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(
    replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(
    replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(
    replace(replace(@input_string collate latin1_general_100_bin2,
        char(1), ''),char(2), ''),char(3), ''),char(4), ''),char(5), ''),char(6), ''),char(7), ''),char(8), ''),char(9), ''),char(10), ''),
        char(11), ''),char(12), ''),char(13), ''),char(14), ''),char(15), ''),char(16), ''),char(17), ''),char(18), ''),char(19), ''),char(20), ''),
        char(21), ''),char(22), ''),char(23), ''),char(24), ''),char(25), ''),char(26), ''),char(27), ''),char(28), ''),char(29), ''),char(30), ''),
        char(31), ''), char(0) , '') 
     as clean_string
);
go
并像这样使用它:

select c.clean_string
from dbo.remove_non_printable_chars(@dirtystring) c

参考:

另一种选择

此函数将替换控制字符并更正任何剩余的重复空格。例如,Jane Smith{13}在这里不会像Jane Smith在这里一样被返回,而是Jane Smith在这里


只是把前面的答案扩展一点

在白名单字符下面,所有其他字符将被清除


在10%的10%和10%的他们他们的,,,,10-10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10Þ这有点麻烦,但要删除这些特定字符,必须进行嵌套替换。嵌套替换也非常快。您可以考虑将此转换为内联表值函数,而不是标量函数。FWIW,我不认为这个函数很可怕。需要的是大量难看的代码……首先是函数的要点:我会在codereview.stackexchange.comWeb搜索中发布这篇文章:@SeanLange谢谢你的好话:这句话让我想到:我们最近从SQL Server 2012迁移到SQL Server 2014,我们所有的for XML代码开始抛出关于不可打印ASCII字符的错误。为什么和哪些错误?您是如何创建XML的?这不应该发生。。。阅读有关的信息,它可能有助于展示一些在SS12中工作而在SS14中不工作的示例。我很肯定,这个问题——以及它的解决方案在别的地方…谢谢…我会等其他的答案。如果不是,我就切换到表值函数。看起来你被否决我的人否决了。我不知道他知道我们错过了什么@约翰卡佩莱蒂:我想我们永远也不会知道。你能详细说明一下拉丁文对照的用法吗?起初,我试图省略它,因为我的数据库具有不同的排序规则,但我注意到对于一个约3000行的查询,使用collate latin1_general_100_bin2 2 2秒vs 30秒,函数速度要快得多……我不明白为什么。@ChristianSpecht我担心即使没有collate开关,查询也需要30秒才能运行3000行。你用的这些绳子有多大?我没想到会有这么大的不同。谢谢。我明天试试这个。我不确定是否要添加空格,因为控制字符可能在一个单词中。@Munir fair,那么只需更改Select@S=Replace@S,C',以选择@S=Replace@S,C,但是,您有可能words@scsimon你能怪我吗?当我第一次看到它的时候,我的第一个想法是我。。。然后我突然明白了。。。真棒!不,我还记得那个答案,被吹走了,所以我现在记得了!因此,如果我理解正确,cte1N将创建一个包含10个1的表,cte2将它们转换为char0到char100,并选择前32个,select替换所有控制字符,return语句中的表达式将所有多个空格转换为单个空格。因为我想保持输入的原样,所以返回了@S,没有任何更改。对于我来说,这也比嵌套替换稍微快一点,所以我将使用它。非常感谢。现在,我们只希望只有基于拉丁字母的语言的用户才会使用该应用程序。
select ...
  , c.clean_string
from t
  cross apply dbo.remove_non_printable_chars(t.dirty_string) c
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(replace(@S,' ','†‡'),'‡†',''),'†‡',' ')))
End
--Select [dbo].[udf-Str-Strip-Control]('Michael        '+char(13)+char(10)+'LastName')  --Returns: Michael LastName