database.sarang.net
UserID
Passwd
Database
DBMS
MySQL
PostgreSQL
Firebird
ㆍOracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
Oracle Q&A 22001 게시물 읽기
No. 22001
Sql 바인딩.
작성자
유성
작성일
2005-03-15 13:16
조회수
7,606

안녕하세요.

프로젝트를 진행하다, 쿼리를 날리는 부분에서 어떻게 작성해야할지 난감한 부분이 있어서 이렇게 질문드리게 됐습니다.

예전부터 바인드 변수를 쓰는 것이 더낫다는 말을 듣고 쿼리나 프로그램도 그렇게 작성하고 있습니다.

그런데 다음과 같은 경우에 어떻게 써야할지 난감하더군요.

 

예를 들어, 어떤 게시판 리스트에서 사용자가 게시물을 check box로 선택하여 시퀀스 값을 넘깁니다.

이는 하나가 될 수도 있고 여러개의 값이 될 수 있습니다.

해당 시퀀스 리스트를 받아서 해당 테이블에 SELECT, UPDATE, DELETE 를 수행해야한다고 했을 때,

 

SELECT REG_NO, WRITER, POINT FROM TABLE_NAME WHERE REQ_NO IN (1,2,3,4,5);

UPDATE TABLE_NAME SET POINT=POINT+10 WHERE REQ_NO IN (8);

DELETE FROM TABLE_NAME WHERE REQ_NO IN (3,6,8,11);

 

예를 들었지만 위와 같이 처리하게 됩니다. (각각의 시퀀스 값은 신경쓰지 마세요. 그냥 예를 든것입니다. 어떤 규칙도 없습니다. 사용자가 임의로 선택한 값일 뿐입니다.)

이를 바인드로 처리하기 위해선 각각의 쿼리를 Application 상에서 루프를 돌아야 가능합니다.

 

for (i=0; i<cnt; ++i)

{

query = "SELECT REG_NO, WRITER, POINT FROM TABLE_NAME WHERE REQ_NO = :NO";

setBindValue(":NO") = check[i];

rs[] = stmt->exec(query);

// 처리.

}

위와 같이 말이죠.

 

결론적으로 제가 궁금한 것은,

1. 여러개의 값을 바인드를 처리하지 않고 IN 을 써서 한번에 쿼리를 날리는 것이 DB Server의 부하가 적을지,

2. 바인드 처리를 한 후, 여러번 쿼리를 날리는 것이 나을지에 대한 것입니다.

 

그럼 고수님들의 현명한 답변 부탁드립니다.

검색도 해보고, 여러 서적을 찾아보았으나 명확한 답변을 얻지 못하여서 이렇게 질문드립니다.

 

-----------------------------------------------------------

DB : Oracle 8.1.7

빈번도 : 약 1초당 한건씩 호출됩니다. (SELECT)

그 외 UPDATE, DELETE 문은 약 1 분당 한 건 씩 호출됩니다.

-----------------------------------------------------------

 

이 글에 대한 댓글이 총 5건 있습니다.

웹스크립트코딩은 안해봤지만 저라면 우선

in절에 배열변수가 지원되는지 확인해보시고 된다면

당근 배열변수로 바인딩 처리하시고요

안된다면 스토어 프로시져로 만들어서 메모리에서 KEEP시키던가

in으로 처리하겠습니다.

만약 cnt가 100번이라면 for문은 거의 죽음이죠...^^

최성준(junkk)님이 2005-03-15 18:09에 작성한 댓글입니다.
이 댓글은 2005-03-15 18:15에 마지막으로 수정되었습니다.

오라클에서 제공하는 jdbc 드라이버를 쓰시면

collection 타입에 대한 binding이 됩니다. 이것을 사용하시면

되구요 아니라면

1. 문자열을 받아 collection 타입을 리턴 하는 함수를 만든다.

2. 위의  함수를 사용하여 select from table(fn) 을 in () 안에 두는 방법을 사용한다.

김흥수(protokhs)님이 2005-03-15 22:02에 작성한 댓글입니다.

예외 없는 법칙은 없습니다.

 

대부분 Binding 이 좋지만, 그렇지 않을 때도 있습니다.

 

님과 같은 경우에는 Binding으로 못할 거는 아니지만, 그래도 Dynamic하게 처리하는게 좋아보입니다.

 

그래도 굳이 바인딩으로 하려면 for-loop 를 돌리는 거 보다는

다음과 같은 방식이 더 효율적일 겁니다.

 

IN 구문은 NULL을 넣었을 때 처리하지 않고 통과를 시킵니다.

즉, IN ( 1, NULL ) 은 IN ( 1 ) 과 똑같습니다.

 

이런 원리를 이용한다면, 입력 받는 CNT가 어느 정도 Max값을 가질 테니까

, MAX까지 IN 구문으로 만들어 놓고 값이 들어오면 그 값으로, 없으면 Null로 바인딩을 시켜버리면 됩니다...

 

 

 

 

남해 짱님이 2005-03-16 11:36에 작성한 댓글입니다. Edit

유성님은 오라클 옴티마이져가 조아하는 방식으로 어플을 개발

하시네요....^^

일반적으로 개발자가 어플을 개발할 때 DBMS의 특성과는 상관없이

결과만 나오면 된다는 생각으로 개발을 하죠...그러다가 보니 나중에

시간이 흐르면 DB 서버는 매우 많은 작업량으로 인하여서 몸살이 나고

급기야는 퍼지는 현상이 발생한답니다...

 

일반적으로 쿼리는 동적쿼리와 정적쿼리가 있는데...현재 님이 사용하는 방식이 정적쿼리에 해당합니다. 그러다가 보니 "in" 뒤에오는 상수값에 해당하는 바인딩 변수에 문제가 생길수가 있는데... 바인딩변수는

변수에 들어있는 내용을 한줄의 문자열로 인식합니다. 아래의 쿼리를

참조 하세요...이 쿼리는 엔코아 컨설팅에서 제공한 것이며, 아직 저두

사용은 해 보지 못했습니다. 

 

SELECT *
FROM   emp
WHERE  empno IN (
 SELECT trim(SUBSTR(','||col2||',',INSTR(','||col2||',',',',1, NO)+1,
        (INSTR(','||col2||',',',', 1,NO+1)-INSTR(','||col2||',',',', 1,NO))-1)) col2
 FROM   (
         SELECT col2, (LENGTH(col2)-LENGTH(REPLACE(col2,',','')))+1 len
         FROM  (SELECT :in_list col2 FROM dual )
        ) x,
        COPY_T y
 WHERE  y.NO <= x.len)

 

-- 값을 넘길때 '100, 110, 111, 112' 와 같은 하나의 스트링으로 넘기면 됩니다.

 

사용방법은 좀 연구 해 보시고요..참고고 어플에서 넘기는 상수는 당연히 여러개가 넘오겠지요... 위의 쿼리는 어플에서 넘겨받은 상수를 하나씩 짤라서 바인딩으로 처리를 하는 것입니다...

 

 

나그네님이 2005-03-16 11:52에 작성한 댓글입니다.
이 댓글은 2005-03-16 11:54에 마지막으로 수정되었습니다. Edit

아앗. 그렇군요.

jdbc에서 collection 타입으로 바인드할 수 있는 거였군요.

그리고 php에서 배열로 넘어가는 것이 가능한지 테스트 해보겠습니다. ^^

미리 바인드 변수를 설정해놓고, 할당하지 않는 값들은 NULL로 처리해도 간단히 해결이 되는 군요.. -_-;

최대 값을 미리 알고 있어야 한다는 단점이 있지만, 머 어플에서 막아버리면 될테니. ㅋ

위의 예처럼 게시판 같은 곳에 쓰면 딱일 것 같습니다.

 

그리고 나그네님께서 알려주신 쿼리.. 환상적이네요. *^^*

가로로 나열된 값을 Row로 만들어주는 쿼리.

COPY_T 테이블이 머가 될지 고민 좀 했습니다만, 시퀀스 NO만 가지고 있는 테이블 하나 만드니 간단히 해결되네요.

이거 상당히 유용할 것 같습니다.

 

조언 해주신 분들께 너무 감사드립니다.

몇 개월간 고민하던게 확 날아가버리니 정말 신나네요. ^^

유성님이 2005-03-16 13:31에 작성한 댓글입니다. Edit
[Top]
No.
제목
작성자
작성일
조회
22004RMAN 으로 CLON DB 생성
정광철
2005-03-15
1863
22003오라클에서 scott/tiger와 같은 권한을 가진 user를 만들고 싶어요 [1]
2005-03-15
4418
22002쿼리에 대한 기본개념을 흔들어 버린 쿼리 [8]
이무용
2005-03-15
3611
22001Sql 바인딩. [5]
유성
2005-03-15
7606
22000테이블 파티션 할때 unique index 는 어떻게 생성하나요?
서지수
2005-03-15
2452
21999전체업데이트할때 속도여.... [3]
도와주세요.
2005-03-15
2372
21998CLOB타입에 XML데이타 가져오기
우웅
2005-03-15
2031
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2023 DSN, All rights reserved.
작업시간: 0.051초, 이곳 서비스는
	PostgreSQL v16.1로 자료를 관리합니다