在SQL Server中,我需要将2个字符打包成1个字符,类似于HEX.如何去做

本文关键字:字符 包成 1个 类似于 HEX 何去做 Server SQL 2个 | 更新日期: 2023-09-27 18:12:36

我有一个SQL Server表,其中有一个列被定义为二进制(7)。它使用来自具有Comp-3数据(打包的十进制)的Cobol程序的数据进行更新。我写了一个c#程序来获取一个数字并创建Comp-3值。我有它可用的SQL服务器通过CLR集成。我可以像访问存储过程一样访问它。

我的问题是,我需要从这个程序中获取值并将其保存在二进制列中。当我选择一行已经在那里的数据时,我看到的值如下所示:

0 x00012f0000000f

显示的值是COBOL comp-3(打包的十进制)数据,存储在SQL表中。记住,这个字段被定义为Binary(7)。这里连接并存储了两个值。无符号值为12,无符号值为0。

我需要将0x00012F(长度为3个字符)和0x0000000F(长度为4个字符)连接在一起并将其写入列。

我的问题分为两部分。

1)我能够从我的程序返回Comp-3值的字符串表示形式。但是,我不确定这是否是我需要返回的格式,使这项工作。我应该返回什么格式的SQL,使它可以正确使用?

2)我需要做些什么来转换它使其工作?

我希望我说得够清楚了。这是很多消化…谢谢!

在SQL Server中,我需要将2个字符打包成1个字符,类似于HEX.如何去做

我明白了!我需要将输出更改为byte[],并在SQL中将其引用为varbinary。

这是代码,如果将来有人需要它。我希望这有助于其他需要在SQL中创建Comp-3(打包十进制)的人。我将在下面列出使用它的步骤。

下面是c#程序的源代码。将其编译为dll。

using System;
using System.Collections.Generic;
using System.Data;
using Microsoft.SqlServer.Server;
using System.Data.SqlTypes;
namespace Numeric2Comp3
{
//PackedDecimal conversions
public class PackedDecimal
{
    [Microsoft.SqlServer.Server.SqlProcedure]
    public static void ToComp3(string numberin, out byte[] hexarray, out string hexvalue)
    {
        long value;
        bool result = Int64.TryParse(numberin, out value);
        if (!result)
        {
            hexarray = null;
            hexvalue = null;
            return;
        }
        Stack<byte> comp3 = new Stack<byte>(10);
        byte currentByte;
        if (value < 0)
        {
            currentByte = 0x0d;     //signed -
            value = -value;
        }
        else if (numberin.Trim().StartsWith("+"))
        {
            currentByte = 0x0c;     //signed +
        }
        else
        {
            currentByte = 0x0f;     //unsigned 
        }
        bool byteComplete = false;
        while (value != 0)
        {
            if (byteComplete)
                currentByte = (byte)(value % 10);
            else
                currentByte |= (byte)((value % 10) << 4);
            value /= 10;
            byteComplete = !byteComplete;
            if (byteComplete)
                comp3.Push(currentByte);
        }
        if (!byteComplete)
            comp3.Push(currentByte);
        hexarray = comp3.ToArray();
        hexvalue = bytesToHex(comp3.ToArray());
    }
    private static string bytesToHex(byte[] buf)
    {
        string HexChars = "0123456789ABCDEF";
        System.Text.StringBuilder sb = new System.Text.StringBuilder((buf.Length / 2) * 5 + 3);
        for (int i = 0; i < buf.Length; i++)
        {
            sbyte b = Convert.ToSByte(buf[i]);
            b = (sbyte)(b >> 4);     // Hit to bottom
            b = (sbyte)(b & 0x0F);   // get HI byte
            sb.Append(HexChars[b]);
            b = Convert.ToSByte(buf[i]);             // refresh
            b = (sbyte)(b & 0x0F);   // get LOW byte
            sb.Append(HexChars[b]);
        }
        return sb.ToString();
    } 
} 
}

将dll保存在SQL Server机器的某个文件夹中。我使用了"C:'NTA'Libraries'Numeric2Comp3.dll".

接下来,您需要在SQL Server上启用CLR集成。在微软的网站上阅读相关内容:SQL Server CLR集成介绍。打开SQL Server Management Studio并执行以下命令以启用CLR集成:

sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'clr enabled', 1;
GO
RECONFIGURE;
GO

完成后,在Management Studio中执行以下命令:

CREATE ASSEMBLY Numeric2Comp3 from 'C:'NTA'Libraries'Numeric2Comp3.dll' WITH PERMISSION_SET = SAFE

如果出于任何原因需要,可以执行以下命令来删除程序集:

drop assembly Numeric2Comp3

接下来,在Management studio中执行以下命令来创建引用dll的存储过程:

CREATE PROCEDURE Numeric2Comp3
@numberin nchar(27), @hexarray varbinary(27) OUTPUT, @hexstring nchar(27) OUTPUT
AS
EXTERNAL NAME Numeric2Comp3.[Numeric2Comp3.PackedDecimal].ToComp3

如果上面的一切都运行成功,你就完成了!

下面是一些SQL来测试它:

DECLARE @in nchar(27), @hexstring nchar(27), @hexarray varbinary(27)
set @in = '20120123'
EXEC Numeric2Comp3 @in, @hexarray out, @hexstring out
select len(@hexarray), @hexarray
select len(@hexstring), @hexstring

这将返回以下值:

(No column name)    (No column name)
5                   0x020120123F
(No column name)    (No column name)
10                  020120123F                 

在我的例子中,我需要的是来自@hexarray的值。这将被写入到我的表的Binary列。

我希望这有助于其他人可能需要它!

如果您将Comp-3作为十六进制字符串存储在二进制文件中,那么我想知道创建该文件的过程是否正常工作。

尽管如此,最好的解决方案是在select中强制转换它们;强制转换系统很简单,但我不知道是否有comp-3强制转换。

以下是MSDN上的示例。

那么让我们来处理一下字符串:要转换字符串,你可以使用这个:

string in2 = "020120123C";
long iOut = Convert.ToInt64(in2.Substring(0, in2.Length - 1)) 
          * (in2.Substring(in2.Length - 1, 1)=="D"? -1 : 1 ) ;

它将最后一个字符作为符号,其中'D'是唯一的负号。'F'和'C'都是正数。

还需要回写数据吗?

我很好奇:像123.45这样的小数的字符串表示是什么?

(我将保留原始答案供参考…)


这里有几行代码来展示如何使用位和字节。

使用的操作有:

  • 将数据向左或右移n位:<< n>> n
  • 屏蔽/清除不需要的高位:例如,将除最后4位外的所有位设置为0:& 0xF
  • 添加位:|

如果您有一个字符串表示,就像您所显示的那样,out3和out4字节将是结果。其他转换只是如何处理位的例子;小数不可能是二进制或者看起来像小数的二进制。也许你得到的是整数,那么out7和out8就是结果。

要将两个字节组合成一个整数,请查看最后一次计算!

// 3 possible inputs:
long input = 0x00012F0000071F;
long input2 = 3143;
string inputS = "0x00012F0000071F";
// take binary input as such
byte out1 = (byte)((input >> 4) & 0xFFFFFF );
byte out2 = (byte)(input >> 36);
// take string as decimals
byte out3 = Convert.ToByte(inputS.Substring(5, 2));
byte out4 = Convert.ToByte(inputS.Substring(13, 2));
// take binary as decimal
byte out5 = (byte)(10 * ((input >> 40) & 0xF) + (byte)((input >> 36) & 0xF));
byte out6 = (byte)(10 * ((input >> 8) & 0xF) + (byte)((input >> 4) & 0xF));
// take integer and pick out 3rd and last byte 
byte out7 = (byte)(input2 >> 8);
byte out8 = (byte)(input2 & 0xFF);
// combine two bytes to one integer
int byte1and2 = (byte)(12) << 8 | (byte)(71) ;
Console.WriteLine(out1.ToString());
Console.WriteLine(out2.ToString());
Console.WriteLine(out3.ToString());
Console.WriteLine(out4.ToString());
Console.WriteLine(out5.ToString());
Console.WriteLine(out6.ToString());
Console.WriteLine(out7.ToString());
Console.WriteLine(out8.ToString());    
Console.WriteLine(byte2.ToString());
相关文章: