2009-04-22 13 views
7

Se c'è un'alternativa di shift operatori in PL/SQL? C'è la funzione bitand, ma accetta solo gli argomenti tipo binary_integer.operatori di spostamento in PL/SQL

Cosa devo fare se ho bisogno di check-up inferiore/superiore po 'di numero molto lungo (probabilmente impostata nella riga)?

Nel C ci sono gli operatori << e >>. Come posso realizzarli in PL/SQL?

risposta

3

Ecco la mia soluzione LPAD/RPAD.

prendo Tom Kyte package come base e espanderlo.

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

E test

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

Poiché Oracle Versione 8 è possibile si utilizza il codice Java nel database. In PL/SQL è possibile definire un wrapper per il codice java. per esempio.

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; 

Nel codice java è quindi possibile utilizzare l'operatore di spostamento. Anche se un po 'goffo, ma può funzionare in questo modo.

Purtroppo, questo non è possibile con Oracle XE, in quanto non v'è alcun supporto per Java in quell'edizione 'libero'.

+0

bella soluzione, grazie. trovo il modo pl/sql, che inserirò entro pochi minuti – drnk

6

La risposta seguente non è endianness agnostico e il mio testo si basa sul formato little endian ...

è possibile spostare i bit semplicemente moltiplicando (spostamento a sinistra) o dividendo (spostando a destra) l'argomento per 2 alla potenza di x, dove x è il numero di bit da spostare. per esempio, se devo spostare il byte di ordine inferiore di un numero (255: 11111111) 16 bit verso sinistra avrei eseguire la seguente operazione:

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

contrario, se voglio spostare il valore 16711680 16 bit a destra vorrei eseguire quanto segue:

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