Операторы сдвига в PL / SQL - PullRequest
       10

Операторы сдвига в PL / SQL

7 голосов
/ 22 апреля 2009

Есть ли альтернатива shift операторов в PL / SQL? Существует функция bitand, но она принимает только аргументы типа binary_integer .

Что мне делать, если мне нужно проверить младший / старший бит действительно длинного числа (возможно, установленного в строке)?

В C есть << и >> операторы. Как я могу реализовать их в PL / SQL?

Ответы [ 3 ]

6 голосов
/ 30 июня 2009

Следующий ответ не является независимым от порядка байтов, и моя формулировка основана на формате с прямым порядком байтов ...

Вы можете сдвинуть биты, просто умножив (сдвиг влево) или разделив (сдвиг вправо) аргумент на 2 до степени x, где x - количество бит для сдвига. например, если мне нужно сдвинуть младший байт числа (255: 11111111) на 16 бит влево, я бы выполнил следующую операцию:

select 255 * power(2,16) from dual;  
-- the result will be (16711680:111111110000000000000000)

и наоборот, если я хочу сдвинуть значение 16711680 на 16 бит вправо, я бы выполнил следующее:

select 16711680 / power(2,16) from dual;
-- the result will be (255:11111111)
5 голосов
/ 22 апреля 2009

Начиная с Oracle версии 8, вы можете использовать Java-код в базе данных. В PL / SQL вы можете определить оболочку для кода Java. например,

PACKAGE BODY JAVA_CODE
IS
  function bitshift_left(x in number,
                         n in number) return number
  is language java name 'com.foo.Bitshift(java.lang.Integer, 
                                          java.lang.Integer) return java.lang.Integer';
END JAVA_CODE;

В коде Java вы можете использовать оператор сдвига. Хотя это немного неуклюже, но это может сработать таким образом.

К сожалению, это невозможно в Oracle XE, поскольку в этой «бесплатной» версии Java не поддерживается.

3 голосов
/ 22 апреля 2009

Вот мое собственное решение LPAD / RPAD.

Я беру пакет Тома Кайта в качестве базы и расширяю его.

create or replace function bin_shift_right
(  p_bin in varchar2,
   p_shift in number default null) return varchar2
is
    l_len number;
    l_shift number;
begin
    l_shift := nvl(p_shift, 1);
    l_len := length(p_bin);
    if (l_len <= 0) then
        return null;
    end if; 
    if (l_shift > l_len) then
        l_shift := l_len;
    end if;

    return lpad(substr(p_bin, 1, l_len - l_shift), l_len, '0'); 
end bin_shift_right;

create or replace function shright
(  p_num in number,
   p_shift in number default null) return number
is
begin
    if (trunc(p_num) <> p_num OR p_num < 0) then
        raise PROGRAM_ERROR;
    end if;
    return nvl(to_dec(bin_shift_right(to_bin(p_num), p_shift), 2), 0);
end shright;
/

И тесты

SQL>
SQL> select shright(123) from dual;

SHRIGHT(123)
------------
          61

SQL>
SQL> select shright(123, 2) from dual;

SHRIGHT(123,2)
--------------
            30

SQL>
SQL> select shright(123, 10) from dual;

SHRIGHT(123,10)
---------------


SQL> /
...