sqlserver数据库中隐藏字符遇到的坑

  最近遇到了sqlserver数据库中隐藏字符串的坑,也是困扰我好久,最后来分享下我的解决办法。情况是这样的,需要统计分析某市的考试数据,统计每道题的平均分和得分率,一开始运行拆分统计SQL报错

后面多了很多的小数点,我把题号打印出来一看,确实是5没有错,然后使用 len(@id)函数打印出题号ID的长度,发现是16,看来是有隐藏字符了。

  首先查看隐藏小数点的ASCII码为46

然后使用replace函数替换隐藏字符串,

set @id=replace(@id,char(46),'')

本来以为问题可以解决了,再次运行依旧报错,隐藏小数点没有替换掉,上网查了下其他人的解决办法,基本就是replace函数替换掉了,看来没有人遇到跟我一样的情况,这就有点尴尬了。

  后面我想,既然替换不掉,那我只截取我需要的数字不就行了,于是我采用正则表达式的方法截取数字

set @id=stuff(@id,patindex('%[^0-9]%',@id),1,'')

  这次没有报错,以为问题解决了,语句执行完之后去查看表数据,发现插入的全部是null,数字没有截取出来,返回去调试发现 patindex('%[^0-9]%',@id) 返回的是0,根本没有获取到数字的位置,这个5竟然不能识别为数字。

最后发现只有SUBSTRING(@id,1,1) 能截取出想要的数据,但是这个题号不是个位数的,还有两位数三位数的题号,并且后面的隐藏小数点的长度也不一样,我没有办法获取隐藏字符串出现的位置。经过一番折腾,我的最后解决方法就是循环截取每个字符串比对,下面上代码

CREATE function [dbo].[fn_getnumber](@str varchar(100))
returns varchar(100)
begin
    declare @return varchar(100) = ''
    declare @temp varchar(2)
    declare @IsDecimal int=0;
    declare @IsNumber int =0;
    --此方法解决含有小数点隐藏字符,转换成数字和小数失败的数据,
    
    while LEN(@str) > 0 
    begin
        set @temp = SUBSTRING(@str,1,1)
        if (@IsDecimal=1 and @temp='.' and @IsNumber=1)
        begin 
            --已经添加了小数点,后面是数字,则不再添加小数点返回数据
            break;
        end 
        if (@IsDecimal=1 and @temp='.' and @IsNumber=0)
        begin 
            --已经添加了小数点,后面还是小数点,则删除小数点返回数据
            select @return = SUBSTRING(@return,1,len(@return)-1)
            break;
        end 
        if (@temp between '0' and '9')
        begin
            select @return = @return + @temp
            if @IsDecimal=1
            set @IsNumber=1; --添加了小数点后面是数字,状态改为1
        end 
        set @str = SUBSTRING(@str,2,len(@str))
        --如果是小数点,并且后面还有数据
        if (@temp='.') and (LEN(@str) > 0 )
        begin
            select @return = @return + @temp
            set @IsDecimal=1; --增加了小数点将状态改为1
        end
    end
    return @return
end


GO

  然后执行SQL的时候调用方法,返回需要的数字和小数

set @id=dbo.fn_getnumber(@id);

  终于解决了隐藏小数点的问题,这就是我的最后解决方案,如果有更好的解决方案欢迎评论交流。最主要的是这个隐藏字符是个小数点,而且我转换成绩也是有小数点存在的,之前使用正则表达式的方式其实是不行的,毕竟小数的小数点还是要保存的。

原文地址:https://www.cnblogs.com/-admin1024k/p/13255211.html