我有两个描述范围的变量; from
和to
。但是,我的代码中定义的范围之间存在一些重叠。我想通过使用变量从范围中排除一个值,因为我将这些变量作为参数传递给包来调用其他程序。
例如,如果我有这段代码:
IF name = 'AA'
THEN
from := '101-0000-0000';
to := '101-9999-9999';
ELSIF name = 'BB'
THEN
from := '200-0000-0000';
to := '200-9999-9999';
ELSIF name = 'CC'
THEN
from := '100-0000-0000';
to := '120-9999-0000';
ELSIF name = 'DD'
THEN
from := '400-0000-0000';
to := '402-9999-9999';
END IF;
我想从101-****-****
范围中排除name = 'CC'
值,因为它们已被name = 'AA'
范围使用。 CC
from
值为100-0000-0000
,值为120-9999-9999
,完全涵盖101-****-****
。
答案 0 :(得分:1)
你不能以你想要的方式做到这一点。您将不得不拥有更多变量,例如from2
和to2
(或将它们放在数组中)。如果你需要排除2个范围,那么你将需要3组变量等。因此,这种方法不可扩展,只会导致无法维护的代码膨胀。我认为你已经到了那里。
create table name_ranges (
name varchar2(2) not null
, min_value varchar2(13) not null
, max_value varchar2(13) not null
, constraint pk_name_ranges primary key (name, min_value)
, constraint uk_name_ranges_min unique (min_value)
, constraint uk_name_ranges_max unique (max_value)
, constraint ck_name_ranges_min_max check (min_value <= max_value)
);
insert into name_ranges values ('AA', '101-0000-0000', '101-9999-9999');
insert into name_ranges values ('BB', '200-0000-0000', '200-9999-9999');
insert into name_ranges values ('CC', '100-0000-0000', '100-9999-9999');
insert into name_ranges values ('CC', '102-0000-0000', '120-9999-9999');
insert into name_ranges values ('DD', '400-0000-0000', '402-9999-9999');
我把这些数字保留为VARCHARs;但我会考虑将它们改为NUMBER。当您需要显示数据时,可以添加分隔符,但它们只会使剩余的时间内管理数字变得更加困难。虽然我添加了一些约束,但是没有办法保证没有重叠的范围;在代码中声明这些时,你必须要小心。
现在,每当您需要根据这些范围从另一个表中选择数据时,您可以使用正常的非等连接加入:
select my.*
from my_table my
join name_ranges nr
on my.name = nr.range
and my.column_name between nr.min_value and nr.max_value
这有利于简化代码并减少音量。这也意味着如果您需要更改任何内容,则只需更改表格即可。没有其他的。从长远来看,它可以节省所以非常麻烦,令人难以置信。如果您对范围所做的某些选择的推理不清楚,请在使用自由文本填充的表格中添加一个描述列来解释它们。
如果您必须在代码中将这些作为变量,那么声明一个类型,该类型是实际表的表,然后将它们放入其中。
declare
type t__name_ranges is table of name_ranges index by binary_integer;
t_name_ranges t__name_ranges;
begin
select * bulk collect into t_name_ranges
from name_ranges;
-- do_something
end;