2012-11-09 4 views
7

Ho due tabelle.
Uno è answer_step_dtl
Un altro è tag_mst come seguire
Sostituire più tag in una riga nell'istruzione select da un'altra tabella

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>. 

e così via.

E la mia tag_mst ha valori come questo

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

Ora il mio requisito è questo che voglio selezionare modulo di risposta tavolo risposte con valore sostituito di tag montante. Ci può essere più di un tag in uno ans_desc.

Stavo pensando l'approccio

  1. loop attraverso il risultato di answer_dtl recuperare i tag dal singolo record

  2. ciclo tra i più tag nel record e quindi sostituire il tag

  3. memorizzare in una tabella temporanea e quindi aprire il cursore per la nuova tabella di tem.

È questo l'approccio. O c'è un semplice approccio per farlo.

+0

E 'possibile avere due nomi dei tag nella stessa 'ans_desc'? – Ben

+0

sì, questo è il possibile altrimenti la soluzione @joe è perfetta. –

+0

@ Ben ho aggiornato la mia domanda gentilmente vederlo. –

risposta

3

Edit: interrogazione bonus usando (ricorsiva) CTE, inspired by a note da @Rob van Wijk, ha bisogno di 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. 

risposta iniziale:

È possibile utilizzare una funzione di PL/SQL. Di seguito vi funziona anche se ci sono diversi tag da sostituire:

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 Ho intenzione di applicare questo e vederlo –

+0

grazie a @Vincent funziona perfettamente. Ma il loro sarà un sovraccarico (problema del cursore aperto) se answer_step_dtl ha un passaggio da 60 a 70 e ogni passo ha qualche tag. –

+0

Questo leggerà le righe da 'answer_step_dtl' solo una volta, e per ogni tag otterrete una scansione univoca dell'indice, quindi questo dovrebbe essere OK. Non ci sarà alcun problema con il cursore aperto poiché la funzione non usa cursori espliciti :) Se sei su 11gR2 puoi provare l'altra query e dirci quale è la più veloce sul tuo set di dati. –

1

provare questo:

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

funzionerà se ho due tag in una riga? –

+0

Ho provato con la modifica ma per più tag non funziona. –

+0

@krshekhar: quindi prova ad aggiornare la tabella invece di selezionare –

Problemi correlati