【发布时间】: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 文件时继续进行