2012-11-29 2 views
4

숫자 목록을 plsql 변수로 쿼리하고 다른 SQL 쿼리의 in 절에서 사용하려고합니다. 내가하고 싶은 것을 아래에 테스트 케이스를 만들었다.'IN'절에서 바인드 변수 사용

나는 해결책을 찾기 위해 google을했는데 어떻게 든 가능해야한다고 생각하지만 그냥 실행하지 않아도된다. 컴파일 솔루션으로 도와주세요.

CREATE OR REPLACE PROCEDURE PROCEDURE1 
as 
    type t_id is table of number; 
    v_ids t_id; 
    v_user_ids number; 
BEGIN 

-- fill variable v_id with id's, user_id is of type number 
select user_id 
bulk collect into v_ids 
from user_users; 

-- then at a later stage ... issue a query using v_id in the in clause 
select user_id into v_user_ids from user_users 
-- this line does not compile (local collection type not allowed in SQL statements) 
where user_id in (v_ids); 

END PROCEDURE1; 
+1

아마도이 간단한 데모이지만 두 개의 쿼리를 하나로 결합하지 않겠습니까? "Select ... from ... 어디에서 user_id (select user_id from ...)"? 또는 참여를 수행 하시겠습니까? –

+0

예, 이것은 어리 석다. 컴파일 할 때 예제가 필요합니다 - 줄에 오류가 발생합니다. 여기서 user_id (v_ids) – opi

+0

은 SQL 배열을 사용하고 있습니다. plsql 중첩 테이블은 옵션이 아닙니다. 그렇다면 TABLE() 함수를 사용하여 문제를 해결할 수 있습니다. 마지막 문장은 select into로 선택되지 않으므로 한 행으로 끝납니다. 실제 SQL이 select max이면 괜찮습니다.() 또는 rownum = 1 또는 무엇인가). – DazzaL

답변

4

는 SQL 유형을 사용 :

SQL> create type t_id is table of number; 
    2/

Type created. 

SQL> CREATE OR REPLACE PROCEDURE PROCEDURE1 
    2 as 
    3 v_ids t_id; 
    4 v_user_ids number; 
    5 BEGIN 
    6 
    7 -- fill variable v_id with id's, user_id is of type number 
    8 select user_id 
    9 bulk collect into v_ids 
10 from user_users 
11 where user_id between 100 and 120; 
12 
13 select user_id into v_user_ids 
14  from user_users 
15  where user_id in (select /*+ cardinality(t, 10) */ t.column_value from table(v_ids) t) 
16  and rownum = 1; 
17 
18 dbms_output.put_line(v_user_ids); 
19 
20 END PROCEDURE1; 
21/

Procedure created. 

SQL> exec procedure1 
100 

cardinality(t, 10)은 배열에있는 많은 요소에 대한 합리적인 추측을 있어야 할 곳에.

참고 : 바운드 형식의 대부분을 사용 당신이 가지고있는 것처럼 수집 :

8 select user_id 
    9 bulk collect into v_ids 
10 from user_users; 

은 일반적으로 크지 않다 배열 천 많은 이상의 행으로 끝낼 수 있다면, 당신은 너무 많은 스트레스를 옮기고로 메모리와 결국 코드를 ​​충돌합니다. 명시 적 커서 open x for ..을 사용하고 제한 절이있는 루프 (예 : fetch x bulk collect into v_ids limit 100)에서 대량 가져 오기를 수행하고 100-1000의 배치로 처리하는 것이 좋습니다.

+0

위의 코드는 내부 선택이 트릭을 수행한다. 'create type ... '을 피할 수 있을까요? 이미 오라클이 제공 한 유형을 재사용 할 수 있습니까? - 실제 코드는 1000 개 단위로 100 만개의 레코드를 통과합니다. 성능상의 이유로 plsql에서이 작업을 수행해야합니다. – opi

+0

당신은 데이터베이스'select owner, type_name, coll_type, upper_bound, precision, all_coll_types의 스케일을 elem_type_name = 'NUMBER';와 같이 선택하고 (v_ids KU $ _OBJNUMSET;과 같이) 선택할 수 있습니다. 오라클이 소유하고있는 (SYS) 소유권을 사용하여 오라클의 향후 릴리스에서 사라질 것이거나 변경 될 것을 기억하십시오 :) – DazzaL

+0

"Batches of 1,000"과 "performance Batch"는 나에게 상호 배타적 인 소리를냅니다. 매우 많은 수의 레코드가있는 경우 가능한 한 적은 SQL 문을 사용하여 코드에 전달해야하는 값을 전역 임시 테이블에 삽입하고 조인하는 것을 고려하십시오. –

관련 문제