有没有办法在 Oracle 10g 中将十进制转换为二进制或二进制转换为十进制,而无需先定义函数?我的数据库访问权限有限(仅限 SELECT),我在网上找到的所有解决方案似乎都涉及CREATE FUNCTION
,这对我不起作用。
5 回答
如果十六进制足够好,那么 TO_CHAR 和 TO_NUMBER 可以工作:
SQL> select to_char(31, '0x') from dual;
TO_
---
1f
SQL> select to_number('1f', '0x') from dual;
TO_NUMBER('1F','0X')
--------------------
31
您也可以使用RAWTOHEX()
和HEXTORAW()
函数将十六进制转换为二进制。
专门研究粗糙 SQL 谜题的 Frank Zhou 为这个问题设计了一个纯 SQL 解决方案。您可以在他的 OraQA 网站上找到它。但请注意:这真的很粗糙。
更新
OraQA 的原始链接已损坏:Wayback Machine 在此处有存档版本。
十进制到二进制的粗略但直接的解决方案:
SELECT REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(REPLACE
(TO_CHAR (100,'FMxxx'),
'0','0000'),
'1','0001'),
'2','0010'),
'3','0011'),
'4','0100'),
'5','0101'),
'6','0110'),
'7','0111'),
'8','1000'),
'9','1001'),
'A','1010'),
'B','1011'),
'C','1100'),
'D','1101'),
'E','1110'),
'F','1111')
FROM DUAL;
二进制到十进制会更棘手。您可以使用connect by
将字符串拆分为 4 个字符的段,以类似的方式将它们转换,然后将它们重新连接在一起(第二次connect by
使用SYS_CONNECT_BY_PATH
?),但这对我来说今晚有点太乏味了。
再想一想,这是二进制到十进制的解决方案(我对connect by
问题很感兴趣):
SELECT TO_NUMBER(
REPLACE (
SYS_CONNECT_BY_PATH (octet, '!'),
'!', ''),
'xxxxxx')
FROM (SELECT CASE SUBSTR
(LPAD (a,
CEIL (LENGTH(a)/4)*4, '0'),
(LEVEL-1)*4+1, 4)
WHEN '0000'
THEN '0'
WHEN '0001'
THEN '1'
WHEN '0010'
THEN '2'
WHEN '0011'
THEN '3'
WHEN '0100'
THEN '4'
WHEN '0101'
THEN '5'
WHEN '0110'
THEN '6'
WHEN '0111'
THEN '7'
WHEN '1000'
THEN '8'
WHEN '1001'
THEN '9'
WHEN '1010'
THEN 'A'
WHEN '1011'
THEN 'B'
WHEN '1100'
THEN 'C'
WHEN '1101'
THEN 'D'
WHEN '1110'
THEN 'E'
WHEN '1111'
THEN 'F'
END AS octet,
LEVEL AS seq,
CEIL (LENGTH(a)/4) AS max_level
FROM (SELECT '101010101010101010' AS a
FROM DUAL)
CONNECT BY LEVEL <= CEIL(LENGTH(a)/4))
WHERE LEVEL = max_level
CONNECT BY PRIOR seq = seq-1
此解决方案一次仅适用于当前编写的一行。要使其适用于多行,您需要在最外层添加某种唯一标识符connect by
。
你能像这样在 SQLPlus 脚本中执行 PL/SQL:
declare
procedure bin_2_dec(/*some parameters here*/) is
begin
/*do computation and print result*/
end;
begin
bin_2_dec('11110000');
end;
/
我不确定,但我认为该函数不会在数据库中永久创建,我认为它只会在脚本期间暂时存在,因此这可能会起作用。值得一试,对吧?;)
或者,如果这不起作用,您可以SELECT ... from dual
进行转换,尽管这可能会很尴尬,并且只有在您知道位数的情况下才会起作用 - 也许(如果我能得到几分钟,我会尝试将它放在一起,并且如果它是可能的)。
我在 Oracle 中尝试用一个简单的语句CONNECT BY
将十进制转换为二进制。SELECT
终于得到了想要的输出。你可以使用下面的,它工作正常。
WITH INPUT AS
(SELECT &N AS X FROM DUAL)
SELECT SUM(MOD(FLOOR(X*POWER(0.5,LEVEL-1)),2)*POWER(10,LEVEL-1)) AS
OUTPUT FROM INPUT CONNECT BY POWER(2,LEVEL-1)<=X;