2012-11-09 50 views
7

我有两个表。
一个是answer_step_dtl
如下
从另一个表中选择语句中的行中替换多个标记

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。

而且我tag_mst有这样

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

值现在,我的要求是这样的我想选择与标签桅杆的替代价值问答形式回答表。 在一个ans_desc中可以有多个标签。

我在想办法

  1. 遍历的answer_dtl结果

  2. 遍历该记录中的多个标签,读取从单个记录标签,然后更换 标签

  3. 存储在一个临时表中,然后打开新的TEM表的光标。

这是方法。或者有没有简单的方法来做到这一点。

+0

是否有可能在同一个'ans_desc'中有两个标签名? – Ben

+0

是的,这是可能的,否则@joe解决方案是完美的。 –

+0

@Ben我有更新我的问题,请亲切看看它。 –

回答

3

编辑:奖金查询中使用(递归)CTE,inspired by a note@Rob van Wijk,需要第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'的行,并且对于每个标记,您将获得索引唯一扫描,因此这应该是确定的。由于该函数不使用显式游标,所以不会出现游标开放问题。如果您使用的是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:然后尝试更新表而不是选择 –

相关问题