如何将十六进制数据字符串转换为字符串DB2SQL

如何将十六进制数据字符串转换为字符串DB2SQL,sql,db2,db2-400,rpgle,Sql,Db2,Db2 400,Rpgle,如何使用select语句对十六进制字符串进行解码以获得文本格式的值 例如,我的十六进制数据是: 4f004e004c005900200046004f00520020004200410043004b002d005500500020004f004e0020004c004500560045004c0020004f004e004500200046004f00520020004300520041004e0045005300200020002000200020002000200020002000200020

如何使用select语句对十六进制字符串进行解码以获得文本格式的值

例如,我的十六进制数据是:

4f004e004c005900200046004f00520020004200410043004b002d005500500020004f004e0020004c004500560045004c0020004f004e004500200046004f00520020004300520041004e004500530020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020000000
我想使用select语句对其进行解码以获得字符串值。 上述值为“仅用于起重机一级备用”

我尝试的是:

    SELECT CAST('4f004e004c005900200046004f00520020004200410043004b002d005500500020004f004e0020004c004500560045004c0020004f004e004500200046004f00520020004300520041004e004500530020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020000000' 
    AS VARCHAR(30000) CCSID 37) from myschema.atable
上面的sql返回完全相同的十六进制字符串,而不是我所期望的“仅用于起重机一级备份”的解码文本字符串

可以用石膏做这个吗?如果是,语法是什么

我的问题是系统将文本数据存储在blob字段中,我想使用select语句查看blob字段中的文本数据

Db:Ibm上的Db2

编辑:

我已使用以下方法将字符串转换为十六进制值:

    select hex(cast('ONLY FOR BACK-UP ON LEVEL ONE FOR CRANES' as varchar(100) ccsid 1208))
FROM myschema.atable
这给了我十六进制的字符串:

4F4E4C5920464F52204241434B2D5550204F4E204C4556454C204F4E4520464F52204352414E4553
现在我需要做相反的运算,得到值

谢谢

编辑

使用Daniel Lema的答案,我尝试使用unhex函数,但得到的结果是:

|+<ßã|êâ ä.í&|+<áîá<|+áã|êäê +áë

|+我问你为什么需要这样做

有充分的理由将十六进制字符串转换回它的等效字符…例如,有人向您发送一个32字节的字符串UUID,您希望它返回16字节的二进制格式

但是没有理由
只在一级为起重机提供备份
应该转换为十六进制

我怀疑您需要发布一个新的问题,询问为什么您首先得不到可读字符串

然而,在回答这个问题时。。。IBMi有一个MI函数,可以从任何ILE语言轻松调用。您可以将该函数调用包装到用户定义的函数中,以便从SQL使用它

请注意,您需要知道十六进制字符串表示什么,EBCDIC、ASCII或Unicode,因为您需要能够告诉系统您从何开始。有很多方法可以在编码之间进行转换

这里有一篇文章展示了如何从RPG调用MI函数。

原型的更现代的自由形式版本利用了CCSID关键字的增强功能,可能看起来像

dcl-pr FromHex extproc('cvtch');
  charString char(32767) ccsid(*UTF8) options(*varsize);
  hexString  char(65534) ccsid(*HEX) const options(*varsize);
  hexStringLen int(10) value;
end-pr;
在上述原型中,系统将把返回的字符串视为UTF8(ccsid 1208)。但我所做的只是告诉系统如何解释返回的字节。如果字符串实际上是EBCDIC,我将得到垃圾

我认为您甚至可以直接将
cvtch
函数定义为外部UDF,而不需要ILE包装器。我得好好玩玩这个


忽略这个想法…cvtch只有参数,没有返回值。使用ILE包装器是将输出参数移动到返回值以用作UDF的最佳方式。

我尝试了Marcin Rudzki在上发布的以下解决方案,该解决方案在我自己的Db2 for LUW v11中进行了小的修改

解决方案包括按照Marcin的建议创建一个函数:

CREATE FUNCTION unhex(in VARCHAR(32000) FOR BIT DATA)
RETURNS VARCHAR(32000) 
LANGUAGE SQL
CONTAINS SQL
DETERMINISTIC NO EXTERNAL ACTION
BEGIN ATOMIC
RETURN in;
END
为了测试解决方案,让我们创建一个HEXSAMPLE表,其中包含一个加载了十六进制序列字符串表示的HEXSTRING列:

INSERT INTO HEXSAMPLE (HEXSTRING) VALUES ('4F4E4C5920464F52204241434B2D5550204F4E204C4556454C204F4E4520464F52204352414E4553')
然后执行以下查询(此处与原始方案不同):

结果:

 TEXT                                           HEXSTRING
 ----------------------------------------   --------------------------------------------------------------------------------
 ONLY FOR BACK-UP ON LEVEL ONE FOR CRANES   4F4E4C5920464F52204241434B2D5550204F4E204C4556454C204F4E4520464F52204352414E4553

我希望其他人能找到更直接的解决办法。另外,如果有人能解释它的工作原理,那将是非常有趣的。

问题是您的原始字符串是ASCII格式的(实际上每个字母后面都有x'00'字节),您必须将其转换为EBCDIC。
以下是仅适用于拉丁大写字母的解决方案:

select cast(translate(replace(mycol, x'00', x'')  
, x'C1C2C3C4C5C6C7C8C9D1D2D3D4D5D6D7D8D9E2E3E4E5E6E7E8E940'  
, x'4142434445464748494A4B4C4D4E4F505152535455565758595A20'
) as varchar(500) ccsid 37)
from mytab;
每个ASCII字符都转换为相应的EBCDIC字符。

x'00'符号已删除。

我能够将您的缩短十六进制字符串转换为有效的EBCDIC字符串。 我遇到的问题是,您收到的原始十六进制代码是UTF-16LE(感谢Tom Blodget)。IBM的CCSID系统在UTF-16BE和UTF-16LE之间没有区别,因此我不知道如何正确转换它

如果它是在稍后生成的UTF-8中,那么以下内容将适用于您。它不是最漂亮的,但是把它放在几个函数中,它就会工作

Create or replace function unpivothex (in_ varchar(30000))
    returns table (Hex_ char(2), Position_ int)
    return
    with returnstring (ST , POS )
    as 
    (Select substring(STR,1,2), 1
    from table(values in_) as A(STR)
    union all
    Select nullif(substring(STR,POS+2,2),'00'), POS+2
    from returnstring, table(values in_) as A(STR)
    where POS+2 <= length(in_)
    )
    Select ST, POS 
    from returnstring
    ;
如果您不在V7R2 TR6或V7R3 TR2上,那么这里有一个版本

Create or replace function converthextostring
   (in_string char(30000))
   returns varchar(30000)
   return
   (select xmlserialize(
             xmlagg(
               xmltext(cast(char(varbinary_format(B.Hex_),1) as char(1) CCSID 37)) 
             order by In_table.Position_) 
           as varchar(30000))
   from table(unpivothex(upper(in_string))) in_table
   join table(unpivothex(hex(cast('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ' as char(53) CCSID 1208)))) A on In_table.Hex_ = A.Hex_
   join table(unpivothex(hex(cast('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ' as char(53) CCSID 37)))) B on A.Position_ = B.Position_
   );

我不认为这是可能的,你想要什么,你想要把一个ASCII或EBCDIC值转换成一个对应的字符值,SQL只能转换一个类型,而不能转换它…是的,我想要ASCII值,所以你是说你应该创建一个函数来做这件事?是的,我想你需要一个函数,但是等其他人,也许还有另一种方法这里有一个流行的答案,它看起来是通过cast to CHAR(而不是VARCHAR)来实现的-你试过了吗?我手头没有db2 for I,但是你试过从mytab选择VARCHAR_格式(myhexcol)了吗?它适用于db2 for luw,但字母之间有空格…我尝试使用该函数,但得到的结果与您不同。请检查我的问题的编辑更新。对不起。。。我不知道您正在为IBMi开发DB2。我有一些想法,但在回答之前,我手头没有一台IBM,所以,这次我通过了。顺便说一句:HEXTORAW在IBMi知识中心上没有文档记录,因此,它可能还没有得到官方支持。我们有一个遗留数据库,其中一列声明为char(3),但(RPG)程序员使用它来存储24个使用位的标志。使用“十六进制(标志)”很容易读取(JDBC)——Java程序将其作为一个长度为6的十六进制数字字符串接收。写作是个问题。上面的x'ABCDEF'解决方案工作得很好,但我找不到一种方法让它与准备好的语句(SpringDataJPA)一起工作。最终我发现“cast(hextoraw(:hexval)as char(3))”有效。hextoraw出现在DB210.5和DB2foriSQL7.3手册中
Create or replace function converthextostring
   (in_string char(30000))
   returns varchar(30000)
   return
   (select listagg(char(varbinary_format(B.Hex_),1)) within group(order by In_table.Position_)
   from table(unpivothex(upper(in_string))) in_table
   join table(unpivothex(hex(cast('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ' as char(53) CCSID 1208)))) A on In_table.Hex_ = A.Hex_
   join table(unpivothex(hex(cast('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ' as char(53) CCSID 37)))) B on A.Position_ = B.Position_
   );
Create or replace function converthextostring
   (in_string char(30000))
   returns varchar(30000)
   return
   (select xmlserialize(
             xmlagg(
               xmltext(cast(char(varbinary_format(B.Hex_),1) as char(1) CCSID 37)) 
             order by In_table.Position_) 
           as varchar(30000))
   from table(unpivothex(upper(in_string))) in_table
   join table(unpivothex(hex(cast('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ' as char(53) CCSID 1208)))) A on In_table.Hex_ = A.Hex_
   join table(unpivothex(hex(cast('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ' as char(53) CCSID 37)))) B on A.Position_ = B.Position_
   );
cast (col_name as varchar(2000) ccsid ascii for sbcs data)