无需函数的 PL/SQL 基础转换

发布于 2024-09-06 14:54:37 字数 139 浏览 6 评论 0原文

在 Oracle 10g 中,有没有办法将十进制转换为二进制,或二进制转换为十进制,而无需先定义函数?我的数据库访问权限有限(仅限 SELECT),并且我在网上找到的所有解决方案似乎都涉及 CREATE FUNCTION,这对我不起作用。

Is there any way to convert decimal to binary, or binary to decimal, in Oracle 10g without having to first define a function? I have limited database access (SELECT only) and all the solutions for this I've found online seem to involve CREATE FUNCTION, which does not work for me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

源来凯始玺欢你 2024-09-13 14:54:37

如果十六进制足够好,则 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() 函数将十六进制转换为二进制,如下所示出色地。

If hexadecimal is good enough, then TO_CHAR and TO_NUMBER can work:

SQL> select to_char(31, '0x') from dual;

TO_
---
 1f

SQL> select to_number('1f', '0x') from dual;

TO_NUMBER('1F','0X')
--------------------
                  31

You may be able to use the RAWTOHEX() and HEXTORAW() functions to make the hex to binary transition as well.

傲性难收 2024-09-13 14:54:37

Frank Zhou 专门研究棘手的 SQL 难题,为这个问题设计了一个纯 SQL 解决方案。您可以在 他的 OraQA 网站。但请注意:这确实很粗糙。

更新

OraQA 的原始链接已损坏:The Wayback Machine 在这里有一个存档版本

Frank Zhou who specializes in gnarly SQL puzzlers has devised a pure SQL solution for this problem. You can find it on his OraQA site. But be warned: it is really gnarly.

update

Original link to OraQA is broken: The Wayback Machine has an archived version here.

め七分饶幸 2024-09-13 14:54:37

您能否在 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;
/

我不确定,但我不认为该函数会在数据库中永久创建,我认为它只会在脚本运行期间暂时存在,所以这个 < em>可能有效。值得一试,对吧? ;)

或者,如果这不起作用,您可以 SELECT ... from Dual 进行转换,尽管这可能会很尴尬,并且只有在您知道位数的情况下才有效 - 也许(我'如果我能抽出几分钟时间并且可能的话,我会尝试将其组合在一起)。

Can you execute PL/SQL in an SQLPlus script like this:

declare
    procedure bin_2_dec(/*some parameters here*/) is
    begin
        /*do computation and print result*/
    end;
begin    
    bin_2_dec('11110000');
end;
/

I'm not sure but I don't think the function will be created permanently in the database, I think it will only exist temporarily for the duration of the script so this might work. It's worth a shot, right? ;)

Or if that doesn't work, you could SELECT ... from dual to convert, though that will probably be awkward and will only work if you know the number of digits - maybe (I'll try to throw it together if I can get a few minutes, and if it's possible).

誰ツ都不明白 2024-09-13 14:54:37

十进制到二进制的一个粗略但直接的解决方案:

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 添加某种唯一标识符。

A crude, but straight-forward solution for decimal-to-binary:

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;

Binary-to-decimal would be trickier. You might be able to use connect by to split the string into 4-character segments, convert them in a similar fashion, then concatenate them back together (a second connect by using SYS_CONNECT_BY_PATH?), but that's a little too tedious for me to work out tonight.


On second thought, here's the Binary-to-decimal solution (I'm a sucker for connect by problems):

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

This solution only works for one row at a time as currently written. To make it work with multiple rows, you'd need to add some sort of unique identifier to the outermost connect by.

疏忽 2024-09-13 14:54:37

我在 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;

I was trying this in Oracle using CONNECT BY to covert decimal to binary in a simple SELECT statement. Finally got the desired output. You can use the below, it is working fine.

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文