Oracle 仅用表中的单词列表替换精确的单词

Oracle 仅用表中的单词列表替换精确的单词,oracle,Oracle,这个问题是这个问题的一部分 最初的问题是一个由两部分组成的问题,一部分是,有没有更好的方法 我有可以工作的代码,但速度非常慢,每条记录大约2秒 所以我有一个表,NR_POSTAL_ABBR,它有两个字段和大约400条记录 ReplaceWhat ReplaceWith Ave Avenue St Street 我希望能够用上表中的值替换另一个表中的地址字段 所以,如果我有一个地址123大街-它应该说123大街 如果我有12

这个问题是这个问题的一部分

最初的问题是一个由两部分组成的问题,一部分是,有没有更好的方法

我有可以工作的代码,但速度非常慢,每条记录大约2秒

所以我有一个表,NR_POSTAL_ABBR,它有两个字段和大约400条记录

ReplaceWhat       ReplaceWith
Ave               Avenue
St                Street
我希望能够用上表中的值替换另一个表中的地址字段

所以,如果我有一个地址123大街-它应该说123大街

如果我有123大街——它应该保持在123大街,它不应该变成123大街

带有地址的表有几百万行,有没有快速的方法


如你所问,谢谢你。我的建议是遍历
正则表达式
,因此这里是针对您的案例的un更新代码

假设您有一个带有字段地址的表测试,您需要做的是非常简单的,创建一个符合您需求的正则表达式

因此:您需要为
Street
Avenue
更换每个
St
,这是您应该做的

update test
   set address = 
   regexp_replace(
           regexp_replace(address, 'Av | Av$| Av ', ' Avenue ' ),
                           'St | St$| St ', ' Street ');
这里有一个例子

解释正则表达式:

regexp\u replace
基于正则表达式模式替换另一个字符串,请参见文档:

关于正则表达式,您可以在这里看到,几乎每种语言都遵循
POSIX
模式,因此,一旦您学会了它,您就会很好

所以我习惯于
regexp\u replace
来实现您想要的,因为您给出了两个要求。我不会写函数的参数,只写表达式

在第一个表达式中,您有
'Av | Av$| Av'
,这意味着: 注:我把
-
放在你看到的地方(所以忽略它)。所以我不会把它放在这里

  • -Av-
    (末尾有空格)=在字符串上查找每个
    Av
    后面有空格的字符串
  • -|-
    (管道符号)=等于
    语句
  • -Av$-
    =当
    Av
    位于字符串末尾时,查找前面有空格的所有
    Av
    <代码>$
  • -Av-
    =查找所有
    Av
    ,前面有空格,后面有空格

    然后,该函数将用单词
    Avenue
    替换任何出现的问题。请注意,我在前面和后面各放了一个空格,以避免出现类似
    Peer-HarborAvenue

    同样的解释也适用于
    St
    string


    如果你喜欢正则表达式功能,你可以在这里看到更多信息:

    只要根据Jorge的回复发布自动版本,以防有人需要

        DECLARE
         ReplOrder NUMBER;
    BEGIN
         ReplOrder := 1;
    
    
         DECLARE
           CURSOR getReplsStrng IS
             SELECT replacewhat
                ,replacewith
               FROM analyst.NR_POSTAL_ABBR
              WHERE ReplaceOrder = ReplOrder;
         BEGIN
           FOR getInnerRec IN getReplsStrng LOOP
             --        DBMS_OUTPUT.put_line('replace what ' || getInnerRec.replacewhat);
             --        DBMS_OUTPUT.put_line('Replace Order ' || ReplOrder);
    
    
             UPDATE NR_TMP_106 tmp
                SET NewAddress = LOWER(REGEXP_REPLACE(LOWER(NewAddress)
                                      ,   '$'
                                    || getInnerRec.replacewhat
                                    || ' | '
                                    || getInnerRec.replacewhat
                                    || '$| '
                                    || getInnerRec.replacewhat
                                    || ' '
                                      ,' ' || getInnerRec.replacewith || ' '))
              WHERE     1 = 1
                 AND (   tmp.NewAddress LIKE '%' || CHR(32) || '' || getInnerRec.replacewhat || '' || NULL || '%'
                      OR tmp.NewAddress LIKE '%' || CHR(32) || '' || getInnerRec.replacewhat || '' || CHR(32) || '%'
                      OR tmp.NewAddress LIKE '%' || NULL || '' || getInnerRec.replacewhat || '' || CHR(32) || '%');
    
             COMMIT;
           END LOOP;
         END;
    
    
         ReplOrder := 2;
    
    
         DECLARE
           CURSOR getReplsStrng IS
             SELECT replacewhat
                ,replacewith
               FROM analyst.NR_POSTAL_ABBR
              WHERE ReplaceOrder = ReplOrder;
         BEGIN
           FOR getInnerRec IN getReplsStrng LOOP
             --        DBMS_OUTPUT.put_line('replace what ' || getInnerRec.replacewhat);
             --        DBMS_OUTPUT.put_line('Replace Order ' || ReplOrder);
    
    
             UPDATE NR_TMP_106 tmp
                SET NewAddress = LOWER(REGEXP_REPLACE(LOWER(NewAddress)
                                      ,   '$'
                                    || getInnerRec.replacewhat
                                    || ' | '
                                    || getInnerRec.replacewhat
                                    || '$| '
                                    || getInnerRec.replacewhat
                                    || ' '
                                      ,' ' || getInnerRec.replacewith || ' '))
                    WHERE     1 = 1
                          AND (   tmp.NewAddress LIKE '%' || CHR(32) || '' || getInnerRec.replacewhat || '' || NULL || '%'
                               OR tmp.NewAddress LIKE '%' || CHR(32) || '' || getInnerRec.replacewhat || '' || CHR(32) || '%'
                               OR tmp.NewAddress LIKE '%' || NULL || '' || getInnerRec.replacewhat || '' || CHR(32) || '%');
    
             COMMIT;
           END LOOP;
         END;
    END;
    

    假设每个地址中只有一个缩写应该被替换,这样安全吗?不,不是)可以有超过1个,请告诉我这适合你,然后我会发布回答:如果这是一次性的,Jorge有正确的想法。您应该为
    NR\u POSTAL\u ABBR
    表中的所有内容编写一个正则表达式,并使用它。我恭敬地指出,解决这个问题的任何方法都将是缓慢的。正如您所指出的,地址表中的一行必须与NR_POSTAL_ABBR中的所有行(~400行)进行比较,并且这400个检查中的每一个都必须以这样的方式进行,即它只能找到独立的缩写,而不是其他单词的一部分。因此,您将进行400*(地址数=数百万行数)检查,这几乎肯定需要一段时间。祝你好运。