在PL / SQL中是否有替代的shift
运算符?有bitand
函数,但它只接受binary_integer类型的参数。
如果我需要检查真正长号的较低/较高位(可能设置在行中),我该怎么办?
在C
有<<
和>>
运营商。我如何在PL / SQL中实现它们?
以下答案不是字节序不可知的,我的措辞是基于小端格式......
您可以简单地将位移位(向左移位)或将参数除(右移)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)
从Oracle Version 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代码中,您可以使用shift运算符。虽然有点笨拙,但它可以这样工作。
遗憾的是,Oracle XE无法实现这一点,因为在“免费”版本中不支持Java。
这是我自己的LPAD / RPAD解决方案。
我把Tom Kyte package作为基础并扩展它。
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> /