Базовое преобразование PL / SQL без функций - PullRequest
1 голос
/ 21 июня 2010

Есть ли способ преобразования десятичного числа в двоичное или двоичного числа в десятичное в Oracle 10g без предварительного определения функции?У меня ограниченный доступ к базе данных (только SELECT), и все решения для этого, которые я нашел в Интернете, похоже, включают CREATE FUNCTION, что не работает для меня.

Ответы [ 5 ]

2 голосов
/ 21 июня 2010

Если шестнадцатеричный код достаточно хорош, то 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() для перехода из шестнадцатеричной системы в двоичную.

1 голос
/ 21 июня 2010

Фрэнк Чжоу, который специализируется на непростых головоломках SQL, разработал чистое решение SQL для этой проблемы.Вы можете найти его на его сайте OraQA .Но имейте в виду: это действительно коряво.

обновление

Исходная ссылка на OraQA не работает: У Wayback Machine есть архивверсия здесь .

0 голосов
/ 17 января 2018

Я пытался сделать это в 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;
0 голосов
/ 22 июня 2010

Грубое, но прямолинейное решение для десятичного в двоичное:

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.

0 голосов
/ 21 июня 2010

Можете ли вы выполнить PL / SQL в сценарии SQLPlus следующим образом:

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 конвертировать, хотя это, вероятно, будет неудобно и будет работать, только если вы знаете количество цифр - может быть (я постараюсь собрать его вместе, если смогу получить несколько минут, и если это возможно).

...