2012-11-09 3 views
7

두 개의 테이블이 있습니다.
하나는 등등
다른 테이블의 SELECT 문의 행에 여러 태그 바꾸기

Ans_code      Ans_Desc 
------------------------------------------- 
50000000000000005770  Enter <B><APN></B> and press Ok.  
40000000000000000164  Enter <B><ACCOUNTNAME></B> in connection name. 
40000000000000000165  Enter <B><ACCOUNTNAME></B> in <APN>. 

과를 따를 때 또 다른이 tag_mst됩니다 answer_step_dtl
입니다.

그리고 내 tag_mst이

TAG_CODE     TAG_NAME   TAG_VALUE 
------------------------------------------------------- 
100       <APN>   EXAMPLE.COM 
101       <ACCOUNTNAME> EXAMPLE 

같은 값이 지금 내 요구 사항은 내가 태그 돛대의 대체 값으로 응답 형태로 응답 테이블을 선택하려면이있다. 하나의 태그에 하나 이상의 태그가있을 수 있습니다. ans_desc.


나는

  • 루프 레코드의 여러 개의 태그를 통해 개별 레코드에서 태그를 가져 다음 태그를 대체 answer_dtl의 결과를 통해 접근

    1. 루프를 생각했다

    2. 임시 테이블에 저장하고 새 tem 테이블에 대한 커서를 엽니 다.

    이 방법이 맞습니까? 아니면 이것을하기위한 쉬운 방법이 있습니까?

  • +0

    동일한 'ans_desc'에 두 개의 태그 이름이있을 수 있습니까? – Ben

    +0

    예, 가능하면 @joe 솔루션이 완벽합니다. –

    +0

    @ 벤 @ 내 질문에 친절하게 그것을 보았습니다. –

    답변

    3

    편집 : 보너스 쿼리 @Rob van Wijk에서 (재귀) CTE, inspired by a note을 사용하여 11g을 필요로 (R2?) :

    SQL> WITH data AS (
        2  SELECT ans_code, Ans_Desc, tag_name, tag_value, 
        3   row_number() OVER (partition BY ans_code ORDER BY t.rowid) no, 
        4   row_number() OVER 
        5    (partition BY ans_code ORDER BY t.rowid DESC) is_last 
        6  FROM answer_step_dtl a 
        7  JOIN tag_mst t ON a.ans_desc LIKE '%' || t.tag_name || '%' 
        8 ), n(ans_code, no, is_last, replaced) AS (
        9  SELECT ans_code, no n, is_last, 
    10   replace (ans_desc, tag_name, tag_value) replaced 
    11  FROM data 
    12  WHERE no = 1 
    13  UNION ALL 
    14  SELECT d.ans_code, d.no, d.is_last, 
    15   replace (n.replaced, d.tag_name, d.tag_value) replaced 
    16  FROM data d 
    17  JOIN n ON d.ans_code = n.ans_code 
    18  AND d.no = n.no + 1 
    19 ) 
    20 SELECT * 
    21 FROM n 
    22 WHERE is_last=1; 
    
    ANS_CODE    NO IS_LAST REPLACED 
    -------------------- -- ------- --------------------------------------- 
    40000000000000000164 1  1 Enter <B>EXAMPLE</B> in connection 
    50000000000000005770 1  1 Enter <B>EXAMPLE.COM</B> and press Ok. 
    40000000000000000165 2  1 Enter <B>EXAMPLE</B> in EXAMPLE.COM. 
    

    초기 대답 :

    당신은 PL/SQL 함수를 사용할 수 있습니다. 다음과 같이 여러 개의 태그를 대체하더라도 작동합니다 :

    CREATE OR REPLACE FUNCTION replacetags(p_desc VARCHAR2) 
        RETURN VARCHAR2 IS 
        l_result LONG := p_desc; 
        l_tag_pos INTEGER := 1; 
        l_tag  tag_mst.tag_name%TYPE; 
    BEGIN 
        LOOP 
         l_tag  := regexp_substr(l_result, '<[^<]+>', l_tag_pos); 
         l_tag_pos := regexp_instr(l_result, '<[^<]+>', l_tag_pos) + 1; 
         EXIT WHEN l_tag IS NULL; 
         BEGIN 
         SELECT replace(l_result, l_tag, tag_value) 
          INTO l_result 
          FROM tag_mst 
          WHERE tag_name = l_tag; 
         EXCEPTION 
         WHEN no_data_found THEN 
          NULL; -- tag doesn't exist in tag_mst 
         END; 
        END LOOP; 
        RETURN l_result; 
    END; 
    
    SQL> SELECT ans_code, replacetags(ans_desc) 
        2 FROM answer_step_dtl; 
    
    ANS_CODE    REPLACETAGS(ANS_DESC) 
    --------------------- ---------------------------------------- 
    50000000000000005770 Enter <B>EXAMPLE.COM</B> and press Ok. 
    40000000000000000164 Enter <B>EXAMPLE</B> in connection 
    40000000000000000165 Enter <B>EXAMPLE</B> in EXAMPLE.COM. 
    
    +0

    thaks @ Vincent 나는 이것을 적용하여 그것을 보게 될 것입니다. –

    +0

    덕분에 @Vincent가 완벽하게 작동하고 있습니다. 그러나 나는 answer_step_dtl에 60에서 70 단계가 있고 각 단계에 몇 개의 태그가있는 경우 일부 오버 헤드 (커서 문제 열기)가됩니다. –

    +0

    이렇게하면'answer_step_dtl'의 행을 한 번만 읽게되고 각 태그에 대해 고유 한 색인을 얻을 수 있으므로 OK 여야합니다. 함수가 명시 적 커서를 사용하지 않기 때문에 열린 커서 문제가 없을 것입니다. 11gR2를 사용하는 경우 다른 쿼리를 시도하고 데이터 집합에서 가장 빠른 것을 알려줄 수 있습니다. –

    1

    이 시도 :

    select d."Ans_code",replace("Ans_Desc","TAG_NAME","TAG_VALUE") 
    from answer_step_dtl d, tag_mst m 
    where "Ans_Desc" like '%'|| "TAG_NAME" || '%' 
    


    SQL fiddle demo

    +0

    행에 두 개의 태그가 있으면 작동합니까? –

    +0

    편집을 시도했지만 여러 태그의 경우 작동하지 않습니다. –

    +0

    @krshekhar : –

    관련 문제