0

我创建了一个 MSSQL Server 函数,它使用“#”和“;”将特殊字符(例如:हिन्दीabcde fG#)编码为 un​​icode 数字 作为分隔符。只有像“abc”这样非常简单的字符不会被编码:

declare @position int, @txt nvarchar(max), @output as varchar(max);
set @position=1;
set @txt = N'हिन्दीabcde fG#';
set @output = '';

while @position <= len(@txt)
begin

    declare @t int;
    select @t=unicode(substring(@txt,@position,1))
    --print '&#'+ CONVERT(nvarchar(5),@t)+';'
    if ( (@t between 48 and 57) OR (@t between  65 and 90) or (@t between 97 and 122) )
    BEGIN
    SET @output = @output +  CONVERT(nvarchar(5), substring(@txt,@position,1) );    
    END
    else
    BEGIN
        SET @output = @output + '#'+ CONVERT(nvarchar(5),@t)+';'    
    END
    set @position = @position+1
end


Print @output

结果是:

2361;#2367;#2344;#2381;#2342;#2368;abcde#32;fG#35;

我需要它来使用 ODBC 驱动程序并避免特殊字符的问题。

但现在我需要回去的路——解码编码的字符。是否有任何聪明的解决方案或者我需要至少两个循环,“NCHAR”函数......?

我会尝试构建这样的功能 - 如果成功,我会在这里发布:)

4

2 回答 2

2

您可能会发现这种方法更具吸引力。首先,创建一个维护顺序的拆分函数:

CREATE FUNCTION dbo.SplitStringsOrdered
(
  @List   NVARCHAR(MAX),
  @delim  NVARCHAR(10)
)
RETURNS TABLE
AS
  RETURN
  (
      SELECT rn, v = LTRIM(RTRIM(SUBSTRING(@List, rn,
        CHARINDEX(@delim, @List + @delim, rn) - rn)))
      FROM
      (
        SELECT TOP (8000) rn = ROW_NUMBER() OVER (ORDER BY s1.[object_id])
        FROM sys.all_objects AS s1 CROSS JOIN sys.all_objects AS s2
      ) AS n 
      WHERE rn <= LEN(@List)
      AND SUBSTRING(@delim + @List, rn, LEN(@delim)) = @delim
  );
GO

用法:

DECLARE @x NVARCHAR(MAX) = N'#2361;#2367;#2344;#2381;'
                      + N'#2342;#2368;abcde#32;fG#35;';


-- need one small adjustment to make the string more split-friendly:
SET @x = REPLACE(@x, '#', ';#');

DECLARE @output NVARCHAR(MAX);

SELECT @output = (SELECT
  CASE WHEN v LIKE '#%' THEN NCHAR(REPLACE(v, '#', '')) ELSE v END 
  FROM dbo.SplitStringsOrdered(@x, ';') AS x
  ORDER BY rn FOR XML PATH(''), 
  TYPE).value('./text()[1]','nvarchar(max)');

SELECT @output;

输出:

हिन्दीabcde fG#
于 2013-09-04T22:03:20.063 回答
0

我已经解决了这个查询的问题:

declare @position int, @txt nvarchar(max), @output as nvarchar(max), @buffer as varchar(max);
set @position=1;
set @txt = '#2361;#2367;#2344;#2381;#2342;#2368;abcde#32;fG#35;';
set @output = '';
set @buffer = '';

while @position <= len(@txt)
begin

    declare @t varchar(max);
    select @t=(substring(@txt,@position,1))



    if ( len(@buffer) = 0 and  @t <> '#' and  @t <> ';')
    BEGIN
        -- Append simple chars, which were not encoded
        Print 'Hänge den String ganz normal an den Output: ' + @t
        SET @output = @output + @t;
    END
    ELSE
    BEGIN

        if ( @t = '#' )
        BEGIN
            Print 'Raute wurde erkannt: #';
            SET @buffer = '#';
        END
        else if ( @t = ';' )
        BEGIN
            SET @buffer = REPLACE( @buffer, '#' , '' );
            Print 'Umwandeln: ' + @buffer
            SET @output = @output + isnull( NCHAR(@buffer) , '');
            SET @buffer = '';
        END
        else
        BEGIN
            Print 'Ganzzahl an den Buffer anhängen: ' + @t;
            SET @buffer = @buffer +  @t;
        END
    END

    set @position = @position+1
end


Print @output
于 2013-09-04T21:58:04.360 回答