繁体   English   中英

在 Oracle PL/SQL 中使用循环动态连接字符串

[英]Dynamically concatenating strings using a loop in Oracle PL/SQL

我一直在尝试用 400k 行来标准化表格的“地址”字段。 问题是,这个字段是一个自由格式的字段,这意味着用户(在注册时)可以在其中输入他们想要的任何内容。 我已经设法将这个地址字段分成 14 个其他字段,地址行的每个单词都按顺序排列。

现在我需要将其中一些字段重新连接到不同的字段中,例如:

  • 街道名称
  • 门牌号码

我希望它可以像抓取前 3 个字段并将街道名称和第 4 个字段称为门牌号一样简单,但由于街道名称的长度不同,带有“门牌号”的字段通常是字段 #4、#5很少有 #3 或 #6。

我已经想到了一种可以在这种情况下工作的方法,它将这些字段连接在一个循环中,并使用第一次出现的第一个数字是数字的字段作为断点。(由于某些房屋正在编号为“10C”、“1A”、“1B”等)

由于不是很擅长 PL/SQL,我不知道如何将这个想法放入代码中。

到目前为止,我所做的只是编写 function 来检查字符串是否以数字开头,因此可以在 IF function 中使用它。

如何使用 PL/SQL 动态“遍历”循环中的字段? 我会使用数组吗? 甚至可能吗?

编辑:此地址字段包含的示例(葡萄牙语):

Avenida Doutor Theomário Pinto da Costa 450 Condominio Renaissance, rua 1, casa 1

Rua Álvaro Peres Filho 60 Casa azul em frente ao orelhão

Travessa Delegado Zé Lima 61 antiga Praça Rio Branco

Rua Finlândia 28 Qd 111

Alameda Áustria 107 Condomínio Jardim Europa I

数据中有一个清晰的模式,这让我相信这个地址数据是以分段格式收集的,然后连接到一个表字段中。 我需要做的是相反的,基本上。

模式是:

Avenida(1) Doutor Theomário Pinto da Costa (2) 450(3) Condominio Renaissance, rua 1, casa 1(4)

1 = 街道类型(大道、街道等)

2 = 街道名称

3 = 门牌号

4 = 参考(通常用于帮助指示,此字段通常是按设计打开的。诸如楼层、建筑物和公寓名称之类的内容在此处。)

正如您从上面的示例中看到的那样,街道通常具有不同的名称长度,这使得将特定数量的字段设置为街道名称是不可能的。

一个可能的解决方案:

Declare
  /* Dynamically concatenating strings using a loop in Oracle PL/SQL */
  --
  type tyArray_parsed
  is table of varchar2(2000)
  index by binary_integer;
  --
  arAddress_parsed   tyArray_parsed;
  --
  cnuSTREET_TYPE   constant integer:=1;
  cnuSTREET_NAME   constant integer:=2;
  cnuHOUSE_NUMBER  constant integer:=3;
  cnuREFERENCE     constant integer:=4;
  --
  Procedure print(p_isbTexto varchar2)
  is
    nuIzq_print  integer;
    nuDer_print    integer;
  Begin
    nuDer_print:=0;
    Loop
       nuIzq_print:=nuDer_print+1;
       nuDer_print:=instr(p_isbTexto,chr(10),nuIzq_print);
       exit when nvl(nuDer_print,0)=0;
       dbms_output.put_line(substr(p_isbTexto, nuIzq_print, nuDer_print-nuIzq_print));
    End loop;
    dbms_output.put_line(substr(p_isbTexto, nuIzq_print));
  End print;
  --
  procedure pAddress_split(isbAddress_string      varchar2,
                           oarAddress_parsed  out tyArray_parsed
                          )
  is
    type tyArray_string
    is table of varchar2(2000)
    index by binary_integer;
    --
    arFields  tyArray_string;
    nuLeft_pos    integer;
    nuRight_pos  integer;
    nuMy_number   number;
    blIs_number   boolean;
    nuStep        integer;
  Begin
    print('---------------------------------------');
    print('isbAddress_string=['||isbAddress_string||']');
    --
    nuRight_pos:=0;
    Loop
       nuLeft_pos:=nuRight_pos+1;
       nuRight_pos:=instr(isbAddress_string,' ',nuLeft_pos);
       exit when nvl(nuRight_pos,0)=0;
       arFields(arFields.COUNT+1):=substr(isbAddress_string,
                                          nuLeft_pos,
                                          nuRight_pos-nuLeft_pos
                                         );
    End loop;
    arFields(arFields.COUNT+1):=substr(isbAddress_string,
                                       nuLeft_pos
                                      );
    print('arFields.COUNT='||arFields.COUNT);
    --
    For nuI in arFields.FIRST..arFields.LAST loop
        print(lpad(nuI,4)||'['||arFields(nui)||']');
    End loop;
    --
    nuStep:=cnuSTREET_TYPE;
    For nuI in arFields.FIRST..arFields.LAST loop
       if nuStep=cnuSTREET_TYPE then
          oarAddress_parsed(cnuSTREET_TYPE):=arFields(nui);
          nuStep:=cnuSTREET_NAME;
       Elsif nuStep=cnuSTREET_NAME then
             blIs_number:=false;
             Begin
               nuMy_number:=to_number(arFields(nui));
               blIs_number:=true;
             Exception
               when others then
                     blIs_number:=false;
             End;
             if blIs_number then
                oarAddress_parsed(cnuHOUSE_NUMBER):=arFields(nui);
                nuStep:=cnuREFERENCE;
             Else
                if not(oarAddress_parsed.exists(cnuSTREET_NAME)) then
                   oarAddress_parsed(cnuSTREET_NAME):=arFields(nui);
                Else
                   oarAddress_parsed(cnuSTREET_NAME):=oarAddress_parsed(cnuSTREET_NAME)||' '||arFields(nui);
                End if;
             End if;
      Elsif nuStep=cnuREFERENCE then
            if not(oarAddress_parsed.exists(cnuREFERENCE)) then
               oarAddress_parsed(cnuREFERENCE):=arFields(nui);
            Else
               if arFields(nui)=',' then
                  oarAddress_parsed(cnuREFERENCE):=oarAddress_parsed(cnuREFERENCE)||arFields(nui);
               Else
                  oarAddress_parsed(cnuREFERENCE):=oarAddress_parsed(cnuREFERENCE)||' '||arFields(nui);
               end if;
            End if;
      End if;
    End loop;
    --
    for nuI in oarAddress_parsed.FIRST..oarAddress_parsed.LAST loop
        print(lpad(nuI,2)||'|['||oarAddress_parsed(nui)||']');
    End loop;
  End pAddress_split;
Begin
  dbms_application_info.set_module('Split','START-'||to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'));
  --
  pAddress_split('Avenida Doutor Theomário Pinto da Costa 450 Condominio Renaissance, rua 1, casa 1',arAddress_parsed);
  pAddress_split('Rua Álvaro Peres Filho 60 Casa azul em frente ao orelhão',arAddress_parsed);
  pAddress_split('Travessa Delegado Zé Lima 61 antiga Praça Rio Branco',arAddress_parsed);
  pAddress_split('Rua Finlândia 28 Qd 111',arAddress_parsed);
  pAddress_split('Alameda Áustria 107 Condomínio Jardim Europa I',arAddress_parsed);
  --
  --
  dbms_application_info.set_module('Split','END-'||to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'));
End;
/

回答:

---------------------------------------
isbAddress_string=[Avenida Doutor Theomário Pinto da Costa 450 Condominio Renaissance, rua 1, casa 1]
arFields.COUNT=13
   1[Avenida]
   2[Doutor]
   3[Theomário]
   4[Pinto]
   5[da]
   6[Costa]
   7[450]
   8[Condominio]
   9[Renaissance,]
  10[rua]
  11[1,]
  12[casa]
  13[1]
 1|[Avenida]
 2|[Doutor Theomário Pinto da Costa]
 3|[450]
 4|[Condominio Renaissance, rua 1, casa 1]
---------------------------------------
isbAddress_string=[Rua Álvaro Peres Filho 60 Casa azul em frente ao orelhão]
arFields.COUNT=11
   1[Rua]
   2[Álvaro]
   3[Peres]
   4[Filho]
   5[60]
   6[Casa]
   7[azul]
   8[em]
   9[frente]
  10[ao]
  11[orelhão]
 1|[Rua]
 2|[Álvaro Peres Filho]
 3|[60]
 4|[Casa azul em frente ao orelhão]
---------------------------------------
isbAddress_string=[Travessa Delegado Zé Lima 61 antiga Praça Rio Branco]
arFields.COUNT=9
   1[Travessa]
   2[Delegado]
   3[Zé]
   4[Lima]
   5[61]
   6[antiga]
   7[Praça]
   8[Rio]
   9[Branco]
 1|[Travessa]
 2|[Delegado Zé Lima]
 3|[61]
 4|[antiga Praça Rio Branco]
---------------------------------------
isbAddress_string=[Rua Finlândia 28 Qd 111]
arFields.COUNT=5
   1[Rua]
   2[Finlândia]
   3[28]
   4[Qd]
   5[111]
 1|[Rua]
 2|[Finlândia]
 3|[28]
 4|[Qd 111]
---------------------------------------
isbAddress_string=[Alameda Áustria 107 Condomínio Jardim Europa I]
arFields.COUNT=7
   1[Alameda]
   2[Áustria]
   3[107]
   4[Condomínio]
   5[Jardim]
   6[Europa]
   7[I]
 1|[Alameda]
 2|[Áustria]
 3|[107]
 4|[Condomínio Jardim Europa I]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM