首页 > 解决方案 > Oracle/PL SQL 等效于 Convert(VARBINARY)

问题描述

我正在寻找在 MS SQL 中很容易做到的 Oracle 等价物,即:

DECLARE @INDEC AS INT
SET @INDEC = 37000
RIGHT(CONVERT(VARBINARY(8),@INDEC),4)

这复制了 MS SQL 数据库中的旧软件数据存储格式。相同的软件可以在 oracle 上运行,我现在需要在那里复制相同的语句。

具体来说,当我查看这个字符的结果时,我看到了一组独特的 ASCII 值:

SELECT 
    ASCII(SUBSTRING(RIGHT(CONVERT(VARBINARY(8),37000),4),1,1)) AS POS1,
    ASCII(SUBSTRING(RIGHT(CONVERT(VARBINARY(8),37000),4),2,1)) AS POS2,
    ASCII(SUBSTRING(RIGHT(CONVERT(VARBINARY(8),37000),4),3,1)) AS POS3,
    ASCII(SUBSTRING(RIGHT(CONVERT(VARBINARY(8),37000),4),4,1)) AS POS4
FROM MYTABLE
POS1 POS2 POS3 POS4
0 0 144 136

当我在 Oracle 上尝试使用 CAST 作为 RAW 时,我要么将输入值返回给我,要么收到错误消息。

我专门尝试了各种转换选项,包括指定数据的长度以及在转换为原始数据之前将输入转换为十六进制。

SELECT 
  ASCII(SUBSTR(CAST('37000' AS RAW(8)),3,1)) AS POS1, 
  ASCII(SUBSTR(CAST('37000' AS RAW(8)),4,1)) AS POS2,
  ASCII(SUBSTR(CAST('37000' AS RAW(8)),5,1)) AS POS3,
  ASCII(SUBSTR(CAST('37000' AS RAW(8)),6,1)) AS POS4
FROM dual;

这只是返回“7000”或:

POS1 POS2 POS3 POS4
55 48 48 48

如果我先尝试转换为十六进制,我会收到一条错误消息(十六进制数无效):

select HEXTORAW(to_char(37000,'XXXXXXXX')) from dual

如果我分开转换,我知道 37000 的十六进制是 9088。但以下返回输入字符串(我已将其拆开。)

select HEXTORAW('9088') from dual

最终,此转换操作的输出将与其他字符串数据连接并存储在定义为 VARCHAR 的列中。

我觉得我在这里遗漏了一些非常基本的东西。

任何想法或意见将不胜感激。

标签: oracleoracle11goracle-sqldeveloper

解决方案


这东西:

select HEXTORAW(to_char(37000,'XXXXXXXX')) from dual

返回一个错误,因为默认情况下to_char会在您的数字的十六进制表示的左侧添加一个空格,并且hextoraw不够聪明,不知道如何处理它。(这是数字的代数符号的占位符,+或者,更重要的是,-)。

要解决此问题,您必须使用fm格式修饰符,这会导致生成的十六进制值省略前导空格。

另外,“XXXXXXXX”模型会导致前导零被省略。如果要使原始值的长度为四个字节(而不是长度为 2,这将由转换整数 37000 产生),则需要在格式模型中使用 0 而不是 X,至少对于第一个数字(从左至右)。模型中的最后一个数字占位符(右侧)仍必须为 X 以表示十六进制。

所以,我们只剩下这个:

select hextoraw(to_char(37000, 'fm0XXXXXXX')) as converted_to_raw
from   dual;

CONVERTED_TO_RAW
----------------
00009088

你不能通过查看这个查询的结果来判断(它看起来像一个十六进制数字),但该值确实是 RAW 数据类型,长度为 4,并且字节是你在 SQL Server 中获得的字节(我假设这就是您所说的 MS SQL 的意思)。在 Oracle 中,您可以使用该dump函数同时查看数据类型(23 表示 RAW)和确切的字节数。默认情况下,它以十进制表示法显示字节(这正是您从 SQL Server 中显示的内容)。它看起来像这样:

select dump(hextoraw(to_char(37000, 'fm0XXXXXXX'))) as converted_to_raw
from   dual;

CONVERTED_TO_RAW              
------------------------------
Typ=23 Len=4: 0,0,144,136 

因此,总而言之,您的尝试hextoraw是正确的,但是您需要在整数到十六进制字符串的转换中使用非常精确的格式模型(避免前导空格,包括前导零);而且,如果您真的想查看生成的数据类型和所有字节,则必须使用dump. 请记住dump- 它在许多不同的情况下都非常有用。


推荐阅读