Oracle/PL SQL 相当于 Convert(VARBINARY)
Oracle/PL SQL equivalent to 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;
这只是 returns“7000”或:
POS1
POS2
POS3
POS4
55
48
48
48
如果我先尝试转换为十六进制,则会收到一条错误消息(无效的十六进制数):
select HEXTORAW(to_char(37000,'XXXXXXXX')) from dual
如果我分开转换我知道 37000 的十六进制是 9088。但是下面的 returns 输入字符串(我已经把它拆开了。)
select HEXTORAW('9088') from dual
最终,此转换操作的输出将与其他字符串数据连接并存储在定义为 VARCHAR 的列中。
我觉得我在这里遗漏了一些非常基本的东西。
如有任何想法或意见,我们将不胜感激。
如果您想要数值作为数字,只需使用算术:
SELECT MOD( FLOOR( value / (256*256*256) ), 256 ) AS pos1,
MOD( FLOOR( value / (256*256) ), 256 ) AS pos2,
MOD( FLOOR( value / 256 ), 256 ) AS pos3,
MOD( value, 256 ) AS pos4
FROM table_name
然后,对于您的示例数据:
CREATE TABLE table_name ( value ) AS
SELECT 37000 FROM DUAL;
它输出:
POS1 | POS2 | POS3 | POS4
---: | ---: | ---: | ---:
0 | 0 | 144 | 136
如果你想要它作为 4 字节 RAW
然后在十六进制转换中添加 FM
格式模型以去除前导白色 - space 并使用 0XXXXXXX
获取带前导零的 4 字节:
SELECT HEXTORAW(TO_CHAR(value,'FM0XXXXXXX')) AS raw_value
FROM table_name;
输出:
| RAW_VALUE |
| :--------- |
| 0x00009088 |
db<>fiddle here
这个东西:
select HEXTORAW(to_char(37000,'XXXXXXXX')) from dual
returns 一个错误,因为默认情况下 to_char
会在您的数字的十六进制表示形式的左侧添加一个 space,而 hextoraw
不够智能知道如何处理它。 (这是数字代数符号的占位符,+
,或者更重要的是,-
)。
要解决此问题,您必须使用 fm
格式修饰符,这会导致生成的十六进制值省略前导 space.
另外,'XXXXXXXX' 模型导致前导零被省略。如果要使原始值的长度为四个字节(而不是两个字节的长度,这将由转换整数 37000 产生),则需要在格式模型中使用 0 而不是 X,至少对于第一个数字(从左开始)。模型中的最后一位占位符(右侧)必须仍然是 X 以表示十六进制。
所以,我们剩下这个:
select hextoraw(to_char(37000, 'fm0XXXXXXX')) as converted_to_raw
from dual;
CONVERTED_TO_RAW
----------------
00009088
你不能通过查看这个查询的结果来真正分辨(它只是看起来像一个十六进制数),但该值确实是 RAW 数据类型,长度为 4,字节是你的正在进入 SQL 服务器(我假设这就是你所说的 MS SQL 的意思)。在 Oracle 中,您可以使用 dump
函数查看数据类型(23 表示 RAW)和确切的字节数。默认情况下,它以十进制表示法显示字节(这正是您从 SQL 服务器显示的内容)。它看起来像这样:
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
的尝试是在正确的道路上,但您需要在整数到十六进制字符串的转换中使用非常精确的格式模型(避免前导 space, 包括前导零);而且,如果您真的想查看结果数据类型和所有字节,则必须使用 dump
。请记住 dump
- 它在许多不同的上下文中非常有用。
我正在寻找在 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;
这只是 returns“7000”或:
POS1 | POS2 | POS3 | POS4 |
---|---|---|---|
55 | 48 | 48 | 48 |
如果我先尝试转换为十六进制,则会收到一条错误消息(无效的十六进制数):
select HEXTORAW(to_char(37000,'XXXXXXXX')) from dual
如果我分开转换我知道 37000 的十六进制是 9088。但是下面的 returns 输入字符串(我已经把它拆开了。)
select HEXTORAW('9088') from dual
最终,此转换操作的输出将与其他字符串数据连接并存储在定义为 VARCHAR 的列中。
我觉得我在这里遗漏了一些非常基本的东西。
如有任何想法或意见,我们将不胜感激。
如果您想要数值作为数字,只需使用算术:
SELECT MOD( FLOOR( value / (256*256*256) ), 256 ) AS pos1,
MOD( FLOOR( value / (256*256) ), 256 ) AS pos2,
MOD( FLOOR( value / 256 ), 256 ) AS pos3,
MOD( value, 256 ) AS pos4
FROM table_name
然后,对于您的示例数据:
CREATE TABLE table_name ( value ) AS
SELECT 37000 FROM DUAL;
它输出:
POS1 | POS2 | POS3 | POS4 ---: | ---: | ---: | ---: 0 | 0 | 144 | 136
如果你想要它作为 4 字节 RAW
然后在十六进制转换中添加 FM
格式模型以去除前导白色 - space 并使用 0XXXXXXX
获取带前导零的 4 字节:
SELECT HEXTORAW(TO_CHAR(value,'FM0XXXXXXX')) AS raw_value
FROM table_name;
输出:
| RAW_VALUE | | :--------- | | 0x00009088 |
db<>fiddle here
这个东西:
select HEXTORAW(to_char(37000,'XXXXXXXX')) from dual
returns 一个错误,因为默认情况下 to_char
会在您的数字的十六进制表示形式的左侧添加一个 space,而 hextoraw
不够智能知道如何处理它。 (这是数字代数符号的占位符,+
,或者更重要的是,-
)。
要解决此问题,您必须使用 fm
格式修饰符,这会导致生成的十六进制值省略前导 space.
另外,'XXXXXXXX' 模型导致前导零被省略。如果要使原始值的长度为四个字节(而不是两个字节的长度,这将由转换整数 37000 产生),则需要在格式模型中使用 0 而不是 X,至少对于第一个数字(从左开始)。模型中的最后一位占位符(右侧)必须仍然是 X 以表示十六进制。
所以,我们剩下这个:
select hextoraw(to_char(37000, 'fm0XXXXXXX')) as converted_to_raw
from dual;
CONVERTED_TO_RAW
----------------
00009088
你不能通过查看这个查询的结果来真正分辨(它只是看起来像一个十六进制数),但该值确实是 RAW 数据类型,长度为 4,字节是你的正在进入 SQL 服务器(我假设这就是你所说的 MS SQL 的意思)。在 Oracle 中,您可以使用 dump
函数查看数据类型(23 表示 RAW)和确切的字节数。默认情况下,它以十进制表示法显示字节(这正是您从 SQL 服务器显示的内容)。它看起来像这样:
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
的尝试是在正确的道路上,但您需要在整数到十六进制字符串的转换中使用非常精确的格式模型(避免前导 space, 包括前导零);而且,如果您真的想查看结果数据类型和所有字节,则必须使用 dump
。请记住 dump
- 它在许多不同的上下文中非常有用。