2012-11-09 4 views
7

Mam dwie tabele.
Jednym z nich jest answer_step_dtl
Innym jest tag_mst jak postępować
Zamień wiele znaczników w wierszu w instrukcji select z innej tabeli

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

i tak dalej.

A moja tag_mst ma wartości jak ten

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

Teraz moje wymogiem jest to, że chcesz wybrać formularz odpowiedź tabeli odpowiedzieć zastąpiona wartością znacznika masztu. Może być więcej niż jeden znacznik w jednym ans_desc.

Myślałam podejście

  1. Przelotowe wyniku answer_dtl pobierania znaczników od indywidualnego zapisu

  2. pętli wielu znaczników w płycie, a następnie zastąpienie Znacznik

  3. zapisać w tabeli tymczasowej, a następnie otworzyć kursor dla nowej tabeli tem.

Czy to jest podejście. Czy istnieje jakaś prosta metoda robienia tego.

+0

Czy to możliwe, że masz dwie nazwy znaczników w tym samym 'ans_desc'? – Ben

+0

tak, jest to możliwe inaczej rozwiązanie @joe jest idealne. –

+0

@Ben Mam aktualizację moje pytanie uprzejmie go zobaczyć. –

Odpowiedz

3

Edit: zapytania Bonus użyciu (rekurencyjne) CTE, inspired by a note z @Rob van Wijk potrzebuje 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. 

odpowiedź początkowa:

Można używać z funkcji PL/SQL. Poniższe będą działać, nawet jeśli istnieje kilka tagów do zastąpienia:

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 Zamierzam zastosować to i zobaczyć go –

+0

dzięki @Vincent to działa idealnie. Ale będzie ich trochę narzut (kwestia otwartego kursora), jeśli answer_step_dtl ma od 60 do 70 kroków i każdy krok ma jakiś znacznik. –

+0

Spowoduje to odczytanie wierszy z 'answer_step_dtl' tylko raz, a dla każdego znacznika otrzymasz unikatowy skan indeksu, więc powinno to być OK. Nie będzie problemu z otwartym kursorem, ponieważ funkcja nie używa wyraźnych kursorów :) Jeśli używasz 11gR2, możesz wypróbować inne zapytanie i powiedzieć nam, które jest najszybsze w twoim zestawie danych. –

1

spróbuj tego:

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

będzie działać, jeśli mam dwa tagi z rzędu? –

+0

Próbowałem przez edycję, ale dla wielu tagów nie działa. –

+0

@krshekhar: następnie spróbuj zaktualizować tabelę zamiast wybierać –

Powiązane problemy