注册 登录
编程论坛 SQL Server论坛

请教高手,编写了一个函数,运行结果很奇怪

zy20006 发布于 2017-03-27 09:53, 1659 次点击
函数如下:
Create function [dbo].[fn_hexStrToChar](@hexstr nvarchar(1024))
returns nvarchar
begin
    declare
    @str nvarchar(255),
    @result nvarchar(255),
    @len int,
    @bit int
    set @str = ''
    set @len = LEN(@hexstr)
    set @bit = 3
    while @bit < @len
    begin
        set @str = @str + nchar([dbo].[hextoint](SUBSTRING(@hexstr,@bit,4)))
        set @bit = @bit + 6
    end
    return @str
end

该函数作用是传入一个16进制的字符串,返回与之对应的Unicode字符串
比如:select dbo.fn_hexStrToChar('\u4e2d\u6587\u8f6c\u6362')
执行后应返回“中文转换”。
但是只返回“中”,测试过任何输入都只返回第一个字符。
请教各位高手指点。
住:[dbo].[hextoint]这是另一个函数,作用是单个16进制字符转换。
6 回复
#2
mywisdom882017-03-27 17:14
你要把 [dbo].[hextoint]也发出来,才知道你问题在那里
#3
zy200062017-03-28 09:45
回复 2楼 mywisdom88
Create  function [dbo].[hextoint](@s varchar(16))
returns bigint  
begin
 declare @result bigint
 set @result=CONVERT(bigint, CONVERT(varbinary, CAST(N'0x' + @s AS char), 1))
 return @result
END
#4
zy200062017-03-28 09:51
回复 2楼 mywisdom88
已经发了,但是应该不是这个问题。我试过甩开这个函数,只读取输入的字符串,也是不行。
#5
zy200062017-03-28 10:23
回复 4楼 zy20006
多谢了,问题已经找到了。
是因为函数中定义返回类型时没有标明长度,所以默认就是只有1位。
#6
mywisdom882017-03-28 14:59
以下是引用zy20006在2017-3-28 10:23:28的发言:

多谢了,问题已经找到了。
是因为函数中定义返回类型时没有标明长度,所以默认就是只有1位。

我怎么运行,报“set @str = @str + nchar([dbo].[hextoint](SUBSTRING(@hexstr,@bit,4)))”有错误的。

select unicode('中')  --20013
select nchar('20013') -- 中
你的怎么是 u4e2d


[此贴子已经被作者于2017-3-28 16:04编辑过]

#7
mywisdom882017-03-28 17:08
以下是引用zy20006在2017-3-28 09:45:25的发言:

Create  function [dbo].[hextoint](@s varchar(16))
returns bigint  
begin
 declare @result bigint
 set @result=CONVERT(bigint, CONVERT(varbinary, CAST(N'0x' + @s AS char), 1))
 return @result
END


我电脑出错,是在这里,我的是SQL2000,你上面的函数好像不能用在SQL2000上。要用下面的才可以

CREATE FUNCTION [dbo].[HexStrToVarBin](@hexstr VARCHAR(16))   
RETURNS varbinary(16)   
AS   
BEGIN   
   DECLARE @hex CHAR(2), @i INT, @count INT, @b varbinary(16), @odd BIT, @start bit   
   SET @count = LEN(@hexstr)   
   SET @start = 1   
   SET @b = CAST('' AS varbinary(1))   
   IF SUBSTRING(@hexstr, 1, 2) = '0x'   
       SET @i = 3   
   ELSE   
       SET @i = 1   
   SET @odd = CAST(LEN(SUBSTRING(@hexstr, @i, LEN(@hexstr))) % 2 AS BIT)   
   WHILE (@i <= @count)   
    BEGIN   
       IF @start = 1 AND @odd = 1   
       BEGIN   
           SET @hex = '0' + SUBSTRING(@hexstr, @i, 1)   
       END   
       ELSE   
       BEGIN   
           SET @hex = SUBSTRING(@hexstr, @i, 2)   
       END   
       SET @b = @b +   
               CAST(CASE WHEN SUBSTRING(@hex, 1, 1) LIKE '[0-9]'   
                   THEN CAST(SUBSTRING(@hex, 1, 1) AS INT)   
                   ELSE CAST(ASCII(UPPER(SUBSTRING(@hex, 1, 1)))-55 AS INT)   
               END * 16 +   
               CASE WHEN SUBSTRING(@hex, 2, 1) LIKE '[0-9]'   
                   THEN CAST(SUBSTRING(@hex, 2, 1) AS INT)   
                   ELSE CAST(ASCII(UPPER(SUBSTRING(@hex, 2, 1)))-55 AS INT)   
               END AS binary(1))   
       SET @i = @i + (2 - (CAST(@start AS INT) * CAST(@odd AS INT)))   
       IF @start = 1   
       BEGIN   
           SET @start = 0   
       END   
    END   
    RETURN @b   
END


然后,把 set @str = @str + nchar([dbo].[hextoint](SUBSTRING(@hexstr,@bit,4))) 改为这个
         set @str = @str + nchar([dbo].[HexStrToVarBin](SUBSTRING(@hexstr,@bit,4)))
1