2014-11-21 2 views
0

웹 응용 프로그램에서 사용자 개입을 통해 시간이 지남에 따라 증가 할 수있는 다음과 같은 수의 열을 가질 수있는 Oracle 데이터베이스가 있습니다. Oracle Query : 열을 동적으로 순환하여 행을 만듭니다.

ID | Name | Football | WhoCreated | When  | Baseball | Cheerleading | Swimming 
1 | Billy | (null) | sam, smith | (Timestamp)| 1  | (null)  | 1 
2 | Susie | 1  | sam, smith | (Timestamp)| (null) | 1   | 1 
3 | Johnny | 1  | Homer  | (Timestamp)| 1  | (null)  | (null) 

나는 내가 UNION 사용하여이 작업을 수행 할 수
2, Susie, Football 
3, Johnny, Football 
1, Billy, Baseball 
3, Johnny, Baseball 
2, Susie, Cheerleading 
1, Billy, Swimming 
2, Susie, Swimming 

과 같은 출력을 생성하기 위해 노력하고 있어요,하지만 난 특정 이름 필드의 각을 조정해야합니다. 저는 이미 최대 50 개의 컬럼 (50 개의 조합)을 가지고 있으며 시스템의 사용자가 언제든지 확장 할 수 있습니다. 더 복잡한 작업을 위해 목록의 중간에 감추어 진 감사 용 칼럼이 몇 개 있습니다. 필자는 칼럼을 반복하는 동적 인 방법이 필요합니다. 검색해 봤지만, 아무도 내가 가진 문제를 해결하지 못하는 것 같습니다.

+1

데이터 모델 표준화는 어떻게됩니까? –

+1

이 데이터베이스는 설계하지 않았지만보고 만하고 있습니다. 이것이 이것을 구조화하는 가장 좋은 방법이라고 생각하는 사람은 누구든 저주하고 싶습니다. –

답변

0

이렇게하면 아이디어를 얻을 수 있습니다. 나는 그것을 테스트 할 수는 없지만 이해하기는 상당히 쉽다.

create or replace package test_pkg AS 

    TYPE REP_CURS IS REF CURSOR; 
    TYPE output_REC IS RECORD(
    id_ number, 
    name_ varchar2(50), 
    field_ varchar2(50)); 

    TYPE output_TAB IS TABLE OF output_REC; 

    FUNCTION Get_Data RETURN output_TAB 
    PIPELINED; 

END test_pkg; 

CREATE OR REPLACE PACKAGE BODY test_pkg IS 

    FUNCTION Get_Data RETURN output_TAB 
    PIPELINED IS 

    output_REC_ output_REC; 
    rep_lines_ REP_CURS; 
    stmt_  VARCHAR2(5000); 
    table_rec_ yourtable%ROWTYPE; 

    begin 
    stmt_ := ' YOUR QUERY HERE '; 

    OPEN rep_lines_ FOR stmt_; 
    LOOP 
     FETCH rep_lines_ 
     INTO table_rec_; 
     EXIT WHEN rep_lines_%NOTFOUND; 

     output_REC_.id_ := table_rec_.id; 
     output_REC_.name_ := table_rec_.name; 

     if table_rec_.football IS not null then 
     output_REC_.field_ := table_rec_.football; 
     PIPE ROW(output_REC_); 
     end if; 

     if table_rec_.Baseball IS not null then 
     output_REC_.field_ := table_rec_.Baseball; 
     PIPE ROW(output_REC_); 
     end if; 

     if table_rec_.Cheerleading IS not null then 
     output_REC_.field_ := table_rec_.Cheerleading; 
     PIPE ROW(output_REC_); 
     end if; 

     if table_rec_.Swimming IS not null then 
     output_REC_.field_ := table_rec_.Swimming; 
     PIPE ROW(output_REC_); 
     end if; 

    END LOOP; 
    CLOSE rep_lines_; 

    RETURN; 
    exception 
    when others then 
     DBMS_OUTPUT.put_line('Error:' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE || 
          DBMS_UTILITY.FORMAT_ERROR_STACK || 
          DBMS_UTILITY.FORMAT_CALL_STACK); 
    END Get_Data; 

END test_pkg; 
당신은 그것을 사용하는 다음 함수를 작성해야
+0

고맙습니다. 프로덕션 서버가 아닌 서버에서 테스트 해 보겠습니다. –

+0

멋진데, 어떻게 작동하는지 알려주세요 !! – Shankar

+0

My Oracle 라이센스가 공급 업체에 의해 엄격히 제한되어 있습니다. 권한 오류가 충분하지 않습니다. 나는 이것을 SQL 밖에서해야 할 필요가 있다고 생각한다. 그래도 그 코드에 매달릴거야! –

0

은, 아래의 코드 고려하시기 바랍니다 : 그것은 동적 솔루션은 아니지만

CREATE OR REPLACE FUNCTION commalist (par_id NUMBER) RETURN VARCHAR2 IS 
    TYPE curs IS REF CURSOR; 
    v_emp_cursor curs; 
    fieldvalue VARCHAR2(4000); 
    var_out  VARCHAR2(4000); 
    CURSOR col IS 
    SELECT column_name 
    FROM user_tab_columns 
    WHERE table_name = 'TABLE'; 

BEGIN 

    FOR reccol IN col LOOP 
    OPEN v_emp_cursor FOR ('SELECT '||reccol.column_name||' val 
         FROM TABLE 
        WHERE id = '||par_id); 
    LOOP 
     FETCH v_emp_cursor INTO fieldvalue; 
     IF fieldvalue IS NOT NULL THEN 
      var_out := var_out||fieldvalue||', '; 
     END IF; 
     EXIT WHEN v_emp_cursor%NOTFOUND; 
    END LOOP; 

    CLOSE v_emp_cursor; 
    END LOOP; 

    RETURN SubStr(var_out, 0, Length(var_out) - 2); 

END; 
+0

기능을 만들 권한이 없습니다. 불행히도 내 라이센스는 공급 업체에 의해 제한됩니다. 이러한 답변은 금광이지만 미래를 위해 저장하려고합니다. Crystal 보고서로 테이블을 넘기려고합니다. –

0

with src as (select 1 ID, 'Billy' name, 0 Football, 'sam smith' WhoCreated, sysTimestamp when, 
        1 Baseball, cast(null as number) Cheerleading, 1 Swimming 
       from dual 
      union all 
      select 2, 'Susie', 1, 'sam smith', sysTimestamp, null, 1, 1 
       from dual 
      union all 
      select 3, 'Johnny', 1, 'Homer', sysTimestamp, 1, null, null 
       from dual), 

unpivottbl as (select * 
       from src 
       UNPIVOT 
       (
        VAL 
        FOR descript 
        IN (Football, Baseball, Cheerleading, Swimming) 
       )) 

select ID, name, descript 
    from unpivottbl 
where VAL = 1 

을 시도, 당신이 필요합니다 데이터를 unpivot 할 열을 추가하십시오. 이것은 unpivot에 대한 참조입니다.

+0

정적 솔루션입니다. 제목을 확인하십시오 – Aramillo

+0

불행히도 정적 솔루션이 내 유일한 희망 일 수 있습니다. 왜 내가 유니언 선언문에 반대하는 피 피비언트 테이블을 사용하는 이유는 무엇입니까? 내 실제 데이터에 50 개 정도의 기둥이 있다는 것을 기억하십시오. –