All thing of the world!

Oracle BITAND 설명 : 오라클 함수 본문

IT/Oracle DBMS

Oracle BITAND 설명 : 오라클 함수

WorldSeeker 2021. 3. 30. 21:14

1. 함수의 목적
   
   Oracle BITAND 함수는 input 파라미터를 내부적으로 비트벡터로 변환하여,  비트 AND로 연산결과한 결과를 리턴한다.  무슨 말인지 좀 어렵다. "2. 샘플을 통한 개념 퀵뷰"를 보면 쉽게 이해가 갈 것이다.

2. 샘플을 통한 개념 퀵뷰

SELECT BITAND(6,3)
FROM DUAL;

BITAND(6,3)
-----------
2

 INPUT파라미터 6을 비트벡터 1,1,0으로 변환하고 3을 0,1,1로 변환하여 AND 연산하면?
BIT AND 연산은 0 AND 0 = 0, 0 AND 1 = 0, 1 AND 0 = 0, 1 AND 1 = 1 이다.

                      6 = 1,1,0
                      3 = 0,1,1
AND 연산 결과  = 0,1,0

비트벡터 0,1,0을 10진수로 바꾸면 2가 된다.

3. 사용방법  


4. 함수 PARAMETER 설명

[expr1] [expr2]
  이 인수의 데이터 타입은 NUMBER이며, 결과값도 NUMBER  타입니다. 함수의 목적에서 INPUT 파라미터를 비트벡터로 변환한다는 이야기는 NUMER 타입의 INPUT 파라미터를 받아서 비트벡터로 내부적으로 변환한다는 이야기다.
  이 인자의 범위는

며, 이 범위를 넘어가면 오류가 나며 현재 n은 128까지 지원한다. (엄청나게 큰 숫자를 쓸 수 있으니 걱정하지 않아도 된다. 의심되면 계산해보시길.. )

* 주의 :  expr1, expr2로 인수를 2개만 가질 수 있다. 무한정 쓸 수 있는게 아니다. bitwise AND 연산이라 당연한 것이다.

5. 다양한 샘플표현

example 1) 인자를 1개만 넣으면 에러가 난다. 1개로 비트연산이 가능하면 오류는 나지 않았을 것이다. 비트 연산이 안되니까 필수다.

select bitand(1) from dual;

select bitand(1) from dual
       *
1행에 오류:
ORA-00909: 인수의 개수가 부적합합니다


example 2) 어머어마하게 큰 숫자를 넣어보자.  오버플로우 오류가 난다.

select bitand(1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111,1) from dual;

select bitand(1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111,1) from dual
              *
1행에 오류:
ORA-01426: 수치 오버플로우


example 5)  BITAND와 BIN_TO_NUM을 활용하여 한개의 값으로 다중 상태값 관리

order테이블의 order_status컬럼은 있고, 주문상품의 현재 위치구분(창고/우체국:), 배송방법구분(육로/항공), 수령인구분(주문자본인/대리인)을 관리하고 있다고 가정하자.

값을 넣을때는 pl/sql로 아래와 같이 넣고 있다고 가정하자.

DECLARE
    warehouse NUMBER := 1;
    ground NUMBER := 1;
    insured NUMBER := 1;
   result NUMBER;
BEGIN
    SELECT BIN_TO_NUM(warehouse, ground, insured) INTO result FROM DUAL;
    UPDATE orders SET order_status = result WHERE order_id = 2441;
END;

BIN_TO_NUM(warehouse, ground, insured)에 창고에 있다면  창고에 있다면 warehouse 비트를 켜서 1로 입력하고, 육로배송이라면 ground 비트를 켜서 1로 입력하는 방식이다.
정의상 창고에 있다면 창고의 비트인 첫번째 비트를 켠 1,0,0비트로 십진수 4가 될 것이고, 육로배송이라면 0,1,0비트로 십진수 2가 될 것이고, 수령자가 본인이라면 0,0,1비트로 십진수 1이 될 것이다.
 
그럼 order_status 값 1개로 어떻게 다중값을 추출해 낼 수 있을까?

아래와 같은 쿼리로 추출이 가능하다.

SELECT order_id, customer_id, order_status,
DECODE(BITAND(order_status, 4), 4, 'Warehouse', 'PostOffice') "Location",
DECODE(BITAND(order_status, 2), 2, 'Ground', 'Air') "Method",
DECODE(BITAND(order_status, 1), 1, 'Insured', 'Certified') "Receipt"
FROM orders;

BITAND가 핵심이다. (BITAND는 두 인자값으로 받은 숫자를 비트벡터로 풀어서 BITWISE연산을 하는 함수다)
DECODE(BITAND(order_status, 4), 4, 'Warehouse', 'PostOffice') "Location"를 예로 설명하면, 4의 비트벡터는 1,0,0이다. 그럼으로 order_status의 값이 어떤 값이 들어오든 첫번째 비트만 1이라면 창고에 있는 상태와 같다는 얘기가 된다. 
Method도 마찬가지로 2의 비트벡터는 0,1,0이 되고, order_status가 어떤 값이 들어오던지 두번째 비트만 1이 된다면 육로배송이 된다.

위 쿼리의 결과는 아래와 같다.

Comments