【问题标题】:last iteration of loop not fetching count from select statement循环的最后一次迭代没有从 select 语句中获取计数
【发布时间】:2015-11-20 13:30:08
【问题描述】:

我有一个表,我从中选择数据,然后检查从另一个表中提取的数据是否存在,然后将执行其他操作 null;

create table cmts_data (cmts_token varchar2(30), IP varchar2(20));



insert into cmts_data values ('wnlb-cmts-01-1','10.15.0.1');

insert into cmts_data values ('wnlb-cmts-02-2','10.15.0.2');

insert into cmts_data values ('wnlb-cmts-03-3','10.15.0.3');

insert into cmts_data values ('wnlb-cmts-04-4','10.15.0.4');

insert into cmts_data values ('wnlb-cmts-05-5','10.15.0.5');

我从中选择数据的另一个表--

create table link_data (dhcp_token varchar2(30), cmts_to_add     varchar2(200), cmts_to_remove varchar2(200));



insert into link_data values ('dhcp-1-1-1','wnlb-cmts-01-1,wnlb-cmts-02-2', null);

insert into link_data values ('dhcp-1-1-2','wnlb-cmts-03-3,wnlb-cmts-04-4,wnlb-cmts-05-5', null);

insert into link_data values ('dhcp-1-1-3','wnlb-cmts-01-1', null);

insert into link_data values ('dhcp-1-1-4','wnlb-cmts-05-8,wnlb-cmts-05-6,wnlb-cmts-05-0,wnlb-cmts-03-3', null);

insert into link_data values ('dhcp-1-1-5','wnlb-cmts-02-2,wnlb-cmts-04-4,wnlb-cmts-05-7', null);

create table subntwk (subntwk_nm varchar2(30));



insert into subntwk values ('dhcp-1-1-1');

insert into subntwk values ('dhcp-1-1-2');

insert into subntwk values ('dhcp-1-1-3');

insert into subntwk values ('dhcp-1-1-4');

insert into subntwk values ('dhcp-1-1-5');

这些是两个表的结构和示例数据

现在我有了这个 PLSQL 块 --

DECLARE

  l_cmts VARCHAR2( 200 CHAR );

  l_cmts_1 VARCHAR2( 200 CHAR );

  l_dhcp_cnt number;

  l_cmts_cnt number;



BEGIN

  FOR r IN ( SELECT dhcp_token, cmts_to_add || ',' cmts

              FROM link_data

          )

  LOOP

    l_cmts := r.cmts;

    l_cmts_1 := trim(SUBSTR( l_cmts, 1, INSTR(l_cmts, ',' ) - 1 ));

    dbms_output.put_line(r.dhcp_token);

      select count(1) into l_dhcp_cnt from subntwk where subntwk_nm = r.dhcp_token;

      DBMS_OUTPUT.PUT_LINE(l_dhcp_cnt );

  --  WHILE l_cmts_1 IS NOT NULL

    LOOP

      --DBMS_OUTPUT.PUT_LINE( r.dhcp_token || '|' || l_cmts_1 );



      dbms_output.put_line(l_cmts_1);

      select count(1) into l_cmts_cnt from cmts_data where trim(cmts_token) = trim(l_cmts_1);

      DBMS_OUTPUT.PUT_LINE(l_cmts_cnt);



/*     

      if l_dhcp_cnt >0 and l_cmts_cnt > 0 then

      DBMS_OUTPUT.PUT_LINE( r.dhcp_token || '|' || l_cmts_1 );

      end if;

*/   

      l_cmts := trim(SUBSTR( l_cmts, INSTR( l_cmts, ',' ) + 1 ));

      l_cmts_1 := trim(SUBSTR( l_cmts, 1, INSTR( l_cmts, ',' ) - 1 ));



    exit when l_cmts_1 is null;

    END LOOP;

  END LOOP;

END;

而这个块的 DBMS_OUTPUT 是---

dhcp-1-1-1

1

wnlb-cmts-01-1

1

wnlb-cmts-02-2

0

dhcp-1-1-2

1

wnlb-cmts-03-3

1

wnlb-cmts-04-4

1

wnlb-cmts-05-5

0

dhcp-1-1-3

1

wnlb-cmts-01-1

0

dhcp-1-1-4

1

wnlb-cmts-05-8

0

wnlb-cmts-05-6

0

wnlb-cmts-05-0

0

wnlb-cmts-03-3

0

dhcp-1-1-5

1

wnlb-cmts-02-2

1

wnlb-cmts-04-4

1

wnlb-cmts-05-7

0

预期输出--

dhcp-1-1-1

1

wnlb-cmts-01-1

1

wnlb-cmts-02-2

1

dhcp-1-1-2

1

wnlb-cmts-03-3

1

wnlb-cmts-04-4

1

wnlb-cmts-05-5

1

dhcp-1-1-3

1

wnlb-cmts-01-1

1

dhcp-1-1-4

1

wnlb-cmts-05-8

0

wnlb-cmts-05-6

0

wnlb-cmts-05-0

0

wnlb-cmts-03-3

1

dhcp-1-1-5

1

wnlb-cmts-02-2

1

wnlb-cmts-04-4

1

wnlb-cmts-05-7

0

在这里我们可以看到,在内部循环的每次最后一次迭代中,它都给了我 l_cmts_1 的名称,但为什么最后一个 l_cmts_1 的计数是 0。

在这里我也放了一些不存在的值,因为它可以在我的场景中,因为我得到 0 这很好,但是我看到的这个 PLSQL 块的行为是,对于内部循环,它给出了变量的名称,但是选择语句(用于计数)不接受它!

我试图将该 select 语句放在块中的不同位置,但没有一个起作用。

我尝试过的 SQL ---

with link_data_expand  
    as  
   (  
     select dhcp_token  
          , regexp_substr(cmts_to_add, '[^,]+', 1, level) cmts_to_add  
       from link_data  
    connect  
         by level <= length(cmts_to_add) - length(replace(cmts_to_add, ',')) + 1  
  and prior dhcp_token = dhcp_token  
   and prior dbms_random.value() is not null  
   )  
   select a.dhcp_token  
        , a.cmts_to_add  
        , count(b.cmts_token) cnt  
     from link_data_expand a  
     left join  
          cmts_data b  
       on a.cmts_to_add = b.cmts_token  
    group  
       by a.dhcp_token  
        , a.cmts_to_add  
     order  
      by a.dhcp_token  
        , a.cmts_to_add; 

SQL 的结果 --

 DHCP_TOKEN    CMTS_TO_ADD    CNT

 dhcp-1-1-1    wnlb-cmts-01-1    1

 dhcp-1-1-1    wnlb-cmts-02-2  0

 dhcp-1-1-2    wnlb-cmts-03-3    1

 dhcp-1-1-2    wnlb-cmts-04-4    1

 dhcp-1-1-2    wnlb-cmts-05-5  0

 dhcp-1-1-3    wnlb-cmts-01-1  0

 dhcp-1-1-4    wnlb-cmts-03-3  0

 dhcp-1-1-4    wnlb-cmts-05-0    0

 dhcp-1-1-4    wnlb-cmts-05-6    0

 dhcp-1-1-4    wnlb-cmts-05-8    0

 dhcp-1-1-5    wnlb-cmts-02-2    1

 dhcp-1-1-5    wnlb-cmts-04-4    1

 dhcp-1-1-5    wnlb-cmts-05-7    0

任何建议我在这里做错了什么!

数据库版本-

Oracle 数据库 11g 企业版版本 11.2.0.1.0 - 64 位生产

【问题讨论】:

  • “wnlb-cmts-05-7”的计数不正确吗?该值不会出现在 cmts_data 表中。另外,您是否有理由在 pl/sql 过程中执行此操作,而不是在 select 语句中?
  • 预期输出是什么?
  • @Boneist--好的,我有这种情况,我将获得 .csv 文件以将数据加载到数据库中。我正在使用 SQL LOADER 将数据从 .csv 加载到临时表,即 link_data。现在在 link_data 第二列和第三列有用逗号分隔这些字段的字段,我使用 substr() 和 instr() 函数。现在从 LINK_DATA 获取所有这些字段后,我需要首先检查这些从 link_data 提取的值是否已经存在于 subntwk 和 cmts_data 表中,如果是,则将这些字段插入另一个 DB 表中,否则什么也不做。
  • @Boneist--这里一个 DHCP 可以有多个与之关联的 CMTS,所以我想如果 dhcp-1-1-1 wnlb-cmts-01-1 两者都存在于 subntwk 和 cmts_data 表中如果其中一个不存在,我可以将其插入另一个表,然后我不能插入另一个表。我希望这能澄清我的要求。我知道这很简单,但问题是 CMTS 循环的最后一次迭代给了我零计数,这导致我无法进一步登录以将数据插入另一个表。
  • @Boneist--所以这是我的要求。“wnlb-cmts-05-7”的结果是正确的,因为数据库中可能不存在一些 CMTS,所以我有避免这种情况并在数据进入 CSV 文件时继续进行

标签: oracle plsql oracle11g


【解决方案1】:

根据您在上面的 cmets 中输入的内容,我相信以下查询应该可以满足您的需求:

with link_info as (select dhcp_token,
                          cmts_to_add,
                          cmts_to_remove,
                          trim(regexp_substr(cmts_to_add, '[^,]+', 1, level)) sub_cmt_to_add
                   from   link_data
                   connect by prior dhcp_token = dhcp_token
                              and prior dbms_random.value is not null
                              and level <= regexp_count(cmts_to_add, ',') + 1)

select li.dhcp_token,
       sn.subntwk_nm,
       li.sub_cmt_to_add,
       trim(cd.cmts_token) cmts_token,
       cd.ip
from   link_info li
       left outer join cmts_data cd on (li.sub_cmt_to_add = trim(cd.cmts_token))
       left outer join subntwk sn on (li.dhcp_token = sn.subntwk_nm);

DHCP_TOKEN SUBNTWK_NM SUB_CMT_TO_ADD  CMTS_TOKEN      IP        
---------- ---------- --------------- --------------- ----------
dhcp-1-1-1 dhcp-1-1-1 wnlb-cmts-02-2  wnlb-cmts-02-2  10.15.0.2 
dhcp-1-1-1 dhcp-1-1-1 wnlb-cmts-01-1  wnlb-cmts-01-1  10.15.0.1 
dhcp-1-1-2 dhcp-1-1-2 wnlb-cmts-05-5  wnlb-cmts-05-5  10.15.0.5 
dhcp-1-1-2 dhcp-1-1-2 wnlb-cmts-04-4  wnlb-cmts-04-4  10.15.0.4 
dhcp-1-1-2 dhcp-1-1-2 wnlb-cmts-03-3  wnlb-cmts-03-3  10.15.0.3 
dhcp-1-1-3 dhcp-1-1-3 wnlb-cmts-01-1  wnlb-cmts-01-1  10.15.0.1 
dhcp-1-1-4 dhcp-1-1-4 wnlb-cmts-05-0                            
dhcp-1-1-4 dhcp-1-1-4 wnlb-cmts-05-6                            
dhcp-1-1-4 dhcp-1-1-4 wnlb-cmts-05-8                            
dhcp-1-1-4 dhcp-1-1-4 wnlb-cmts-03-3  wnlb-cmts-03-3  10.15.0.3 
dhcp-1-1-5 dhcp-1-1-5 wnlb-cmts-05-7                            
dhcp-1-1-5 dhcp-1-1-5 wnlb-cmts-04-4  wnlb-cmts-04-4  10.15.0.4 
dhcp-1-1-5 dhcp-1-1-5 wnlb-cmts-02-2  wnlb-cmts-02-2  10.15.0.2 

将数据放在 sql 语句中的好处是,您可以将其插入到 INSERT/MERGE/UPDATE 语句中,以进行必要的修改。


关于您的问题,我不知道为什么您看到每个 dhcp_token 的最后一次迭代计数为 0。我运行了您确切的创建表/插入语句/匿名块并得到了预期的结果(不过,我确实在插入语句的末尾添加了一个提交)。

这是我作为脚本运行的(在 Toad 中):

drop table cmts_data;
drop table link_data;
drop table subntwk;

create table cmts_data (cmts_token varchar2(30), IP varchar2(20));

insert into cmts_data values ('wnlb-cmts-01-1','10.15.0.1');

insert into cmts_data values ('wnlb-cmts-02-2','10.15.0.2');

insert into cmts_data values ('wnlb-cmts-03-3','10.15.0.3');

insert into cmts_data values ('wnlb-cmts-04-4','10.15.0.4');

insert into cmts_data values ('wnlb-cmts-05-5','10.15.0.5');

create table link_data (dhcp_token varchar2(30), cmts_to_add     varchar2(200), cmts_to_remove varchar2(200));



insert into link_data values ('dhcp-1-1-1','wnlb-cmts-01-1,wnlb-cmts-02-2', null);

insert into link_data values ('dhcp-1-1-2','wnlb-cmts-03-3,wnlb-cmts-04-4,wnlb-cmts-05-5', null);

insert into link_data values ('dhcp-1-1-3','wnlb-cmts-01-1', null);

insert into link_data values ('dhcp-1-1-4','wnlb-cmts-05-8,wnlb-cmts-05-6,wnlb-cmts-05-0,wnlb-cmts-03-3', null);

insert into link_data values ('dhcp-1-1-5','wnlb-cmts-02-2,wnlb-cmts-04-4,wnlb-cmts-05-7', null);

create table subntwk (subntwk_nm varchar2(30));



insert into subntwk values ('dhcp-1-1-1');

insert into subntwk values ('dhcp-1-1-2');

insert into subntwk values ('dhcp-1-1-3');

insert into subntwk values ('dhcp-1-1-4');

insert into subntwk values ('dhcp-1-1-5');

commit;

set serveroutput on;

DECLARE

  l_cmts VARCHAR2( 200 CHAR );

  l_cmts_1 VARCHAR2( 200 CHAR );

  l_dhcp_cnt number;

  l_cmts_cnt number;



BEGIN

  FOR r IN ( SELECT dhcp_token, cmts_to_add || ',' cmts

              FROM link_data

          )

  LOOP

    l_cmts := r.cmts;

    l_cmts_1 := trim(SUBSTR( l_cmts, 1, INSTR(l_cmts, ',' ) - 1 ));

    dbms_output.put_line(r.dhcp_token);

      select count(1) into l_dhcp_cnt from subntwk where subntwk_nm = r.dhcp_token;

      DBMS_OUTPUT.PUT_LINE(l_dhcp_cnt );

  --  WHILE l_cmts_1 IS NOT NULL

    LOOP

      --DBMS_OUTPUT.PUT_LINE( r.dhcp_token || '|' || l_cmts_1 );



      dbms_output.put_line(l_cmts_1);

      select count(1) into l_cmts_cnt from cmts_data where trim(cmts_token) = trim(l_cmts_1);

      DBMS_OUTPUT.PUT_LINE(l_cmts_cnt);



/*     

      if l_dhcp_cnt >0 and l_cmts_cnt > 0 then

      DBMS_OUTPUT.PUT_LINE( r.dhcp_token || '|' || l_cmts_1 );

      end if;

*/   

      l_cmts := trim(SUBSTR( l_cmts, INSTR( l_cmts, ',' ) + 1 ));

      l_cmts_1 := trim(SUBSTR( l_cmts, 1, INSTR( l_cmts, ',' ) - 1 ));



    exit when l_cmts_1 is null;

    END LOOP;

  END LOOP;

END;
/

这是我得到的输出:

Table dropped.
Table dropped.
Table dropped.
Table created.
1 row created.
1 row created.
1 row created.
1 row created.
1 row created.
Table created.
1 row created.
1 row created.
1 row created.
1 row created.
1 row created.
Table created.
1 row created.
1 row created.
1 row created.
1 row created.
1 row created.
Commit complete.
dhcp-1-1-1
1
wnlb-cmts-01-1
1
wnlb-cmts-02-2
1
dhcp-1-1-2
1
wnlb-cmts-03-3
1
wnlb-cmts-04-4
1
wnlb-cmts-05-5
1
dhcp-1-1-3
1
wnlb-cmts-01-1
1
dhcp-1-1-4
1
wnlb-cmts-05-8
0
wnlb-cmts-05-6
0
wnlb-cmts-05-0
0
wnlb-cmts-03-3
1
dhcp-1-1-5
1
wnlb-cmts-02-2
1
wnlb-cmts-04-4
1
wnlb-cmts-05-7
0
 PL/SQL procedure successfully completed.

【讨论】:

  • 是的,这就是我想要的,为什么它没有给我这个结果!!请在我的 TOAD 中给我这个我必须在明天之前将它删除,因为这个未知的问题我无法测试它.那么我将如何交付它。我认为我的工具有问题!
  • 我已经给了你我在 Toad 中运行的确切内容。我不能给你别的东西!也许您可以尝试复制并运行我粘贴在答案中的确切脚本,看看结果如何?我强烈建议您切换到使用 sql 语句(或类似的语句,如果这与您所追求的不完全匹配)。
  • 我知道我也准备好了 SQL,但正如你所见,SQL 也给了我相同的结果,那么我可以使用这两种方法中的任何一种,但前提是至少有一个或者他们两个都给我正确的结果来测试,或者我应该假设它在生产环境中它会正确运行并继续进行进一步验证并在该 BLOCK 中写入插入语句,但是 LINK 依赖于 subntwk 表,这就是为什么我不能测试一下
  • 您是说当您运行 sql 语句时,它给出的结果与我在答案中发布的结果不同?如果是这样,我只能假设您表中的数据与我表中的数据不同,这意味着我们没有运行相同的插入语句。不过,我运行的正是你发布的内容,所以......
  • 我也提交了,我使用 SQL LOADER 并在自动提交的 SHELL SCRIPTS 中运行 SQL SCRIPTS。
猜你喜欢
  • 1970-01-01
  • 2011-01-17
  • 1970-01-01
  • 1970-01-01
  • 2013-03-18
  • 2011-07-11
  • 2015-05-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多