Shift operators in PL/SQL

混江龙づ霸主 提交于 2019-12-23 08:29:19

问题


Whether there is an alternative of shift operators in PL/SQL? There is bitand function, but it accepts only binary_integer-type arguments.

What should I do if I need check up lower/higher bit of really long number (probably set in the line)?

In C there are << and >> operators. How I can realise them in PL/SQL?


回答1:


The following answer is not endianness agnostic and my wording is based on little endian format...

You can shift bits simply multiplying (shift left) or dividing (shift right) the argument by 2 to the power of x where x is the number of bits to shift. for example, if I need to shift the low-order byte of a number (255:11111111) 16 bits to the left I would perform the following operation:

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

conversely, if I want to shift the value 16711680 16 bits to the right I would perform the following:

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



回答2:


Since Oracle Version 8 it's possible you use java code in the database. In PL/SQL you can define a wrapper for the java code. e.g.

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;

In the java code you can then use the shift operator. Although a bit clumsy, but it can work this way.

Sadly, this is not possible with Oracle XE, as there is no support for Java in that 'free' edition.




回答3:


Here is my own LPAD/RPAD solution.

I take Tom Kyte package as base and expand it.

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;
/

And tests

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> /


来源:https://stackoverflow.com/questions/776355/shift-operators-in-pl-sql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!