PL/SQL: ORA-01403 为复杂集合设置值时找不到数据
PL/SQL: ORA-01403 No data found when setting values to complex collection
我正在努力为循环中的特定限制添加小时数。我想设置从游标 c_hour 到集合 t_limits_in_plan 的值(对于当前 limit_id ), 但我在下面的循环中做错了。
我收到 ORA-01403 No data found 错误,但是 dbms_output.put_line 部分正在返回值,所以有是为 limit
指定的小时数
我不确定我是否可以解释清楚,所以我会展示。我有这样的功能
CREATE OR REPLACE FUNCTION testFunction (p_tLimits t_limit)
RETURN t_limits_in_plan IS
tLimitsInPlan t_limits_in_plan;
tLimits t_limit;
nLimitId number;
CURSOR c_hour(LimitID number) IS
SELECT *
FROM hours h
WHERE h.limit_id= LimitID;
BEGIN
tLimits := p_tLimits;
FOR i IN tLimits.FIRST .. tLimits.LAST
LOOP
nLimitId := tLimits(i).id;
FOR r_hour IN c_hour(nLimitId)
LOOP
--I CANNOT MAKE THIS PART TO WORK
LimitsInPlan(tLimitsInPlan.last).hour_period_data(NVL(tLimitsInPlan(tLimitsInPlan.last).hour_period_data.last, 0) + 1).hour_from := r_hour.hour_from;
tLimitsInPlan(tLimitsInPlan.last).hour_period_data(tLimitsInPlan(tLimitsInPlan.last).hour_period_data.last).hour_to := r_hour.hour_to;
dbms_output.put_line('Limit ' || nLimitId || '. Hours: ' || r_hour.hour_from || ' - ' || r_hour.hour_to);
END LOOP;
END LOOP;
RETURN tLimitsInPlan;
END testFunction;
我使用的类型是
TYPE r_limits_in_plan IS RECORD (limit_in_plan_id number
,limit r_limit
,hour_period_data t_hour_period_data_tab
);
TYPE t_limits_in_plan IS TABLE OF r_limits_in_plan INDEX BY binary_integer;
-----------------------------------------------------------------------------------
TYPE r_limit IS RECORD(limit_id number
,ind varchar2(400)
);
TYPE t_limit IS TABLE OF r_limit INDEX BY binary_integer;
-----------------------------------------------------------------------------------
TYPE t_hour_period_data IS RECORD(hour_from number
,hour_to number);
TYPE t_hour_period_data_tab IS TABLE OF t_hour_period_data INDEX BY binary_integer;
编辑:
I'm passing below Limit IDs to this functions
Limit ID: 26
Limit ID: 41
Limit ID: 81
So result that I'm expecting is
For LimitID 26 hours 2-3 / 12-15 / 20-23
41 hours 5-7
81 no hours
小时内的样本数据table
CREATE TABLE hours
(
hour_from NUMBER not null,
hour_to NUMBER not null,
limit_id NUMBER(17) not null
)
INSERT INTO hours (hour_from, hour_to, limit_id) VALUES (12, 13, 23);
INSERT INTO hours (hour_from, hour_to, limit_id) VALUES (2, 3, 26);
INSERT INTO hours (hour_from, hour_to, limit_id) VALUES (12, 15, 26);
INSERT INTO hours (hour_from, hour_to, limit_id) VALUES (20, 23, 26);
INSERT INTO hours (hour_from, hour_to, limit_id) VALUES (5, 7, 41);
有人能帮忙吗?我想我添加了所有需要的信息,但如果有什么需要澄清的,我会更新
最简单的解决方案是使用 SQL 定义的嵌套 table 集合和对象(而不是 PL/SQL 定义的关联数组集合和记录)传递数据,然后您可以在一个查询中完成所有处理:
CREATE TYPE r_limit IS OBJECT(
column1 number
,column2 varchar2(400)
,column3 varchar2(400)
,column4 number
);
CREATE TYPE t_limit IS TABLE OF r_limit;
CREATE TYPE t_hour_period_data IS OBJECT(
hour_from number
,hour_to number
);
CREATE TYPE t_hour_period_data_tab IS TABLE OF t_hour_period_data;
CREATE TYPE r_limits_in_plan IS OBJECT(
column1 number
,column2 varchar2(400)
,column3 varchar2(400)
,column4 varchar2(400)
,limit r_limit
,hour_period_data t_hour_period_data_tab
);
CREATE TYPE t_limits_in_plan IS TABLE OF r_limits_in_plan;
您可以将函数定义为:
CREATE FUNCTION testFunction (p_tLimits t_limit)
RETURN t_limits_in_plan
IS
tLimitsInPlan t_limits_in_plan;
BEGIN
SELECT r_limits_in_plan(
l.column1,
l.column2,
l.column3,
l.column4,
VALUE(l),
( SELECT CAST(
COLLECT(
t_hour_period_data(
h.hour_from,
h.hour_to
)
) AS t_hour_period_data_tab
)
FROM hours h
WHERE l.column1 = h.limit_id
)
)
BULK COLLECT INTO tLimitsInPlan
FROM TABLE(p_tLimits) l;
RETURN tLimitsInPlan;
END testFunction;
/
然后:
DECLARE
v_limits t_limit := t_limit(
r_limit(26, '26 - Col2', '26 - Col3', 26.4),
r_limit(41, '41 - Col2', '41 - Col3', 41.4),
r_limit(81, '81 - Col2', '81 - Col3', 81.4)
);
v_lip t_limits_in_plan;
BEGIN
v_lip := testFunction(v_limits);
FOR i IN 1 .. v_lip.COUNT LOOP
DBMS_OUTPUT.PUT( v_lip(i).column1 || ': ' );
FOR j IN 1 .. v_lip(i).hour_period_data.COUNT LOOP
DBMS_OUTPUT.PUT( v_lip(i).hour_period_data(j).hour_from || '-' );
DBMS_OUTPUT.PUT( v_lip(i).hour_period_data(j).hour_to || ' / ' );
END LOOP;
DBMS_OUTPUT.NEW_LINE();
END LOOP;
END;
/
输出:
26: 2-3 / 12-15 / 20-23 /
41: 5-7 /
81:
db<>fiddle here
我正在努力为循环中的特定限制添加小时数。我想设置从游标 c_hour 到集合 t_limits_in_plan 的值(对于当前 limit_id ), 但我在下面的循环中做错了。
我收到 ORA-01403 No data found 错误,但是 dbms_output.put_line 部分正在返回值,所以有是为 limit
指定的小时数我不确定我是否可以解释清楚,所以我会展示。我有这样的功能
CREATE OR REPLACE FUNCTION testFunction (p_tLimits t_limit)
RETURN t_limits_in_plan IS
tLimitsInPlan t_limits_in_plan;
tLimits t_limit;
nLimitId number;
CURSOR c_hour(LimitID number) IS
SELECT *
FROM hours h
WHERE h.limit_id= LimitID;
BEGIN
tLimits := p_tLimits;
FOR i IN tLimits.FIRST .. tLimits.LAST
LOOP
nLimitId := tLimits(i).id;
FOR r_hour IN c_hour(nLimitId)
LOOP
--I CANNOT MAKE THIS PART TO WORK
LimitsInPlan(tLimitsInPlan.last).hour_period_data(NVL(tLimitsInPlan(tLimitsInPlan.last).hour_period_data.last, 0) + 1).hour_from := r_hour.hour_from;
tLimitsInPlan(tLimitsInPlan.last).hour_period_data(tLimitsInPlan(tLimitsInPlan.last).hour_period_data.last).hour_to := r_hour.hour_to;
dbms_output.put_line('Limit ' || nLimitId || '. Hours: ' || r_hour.hour_from || ' - ' || r_hour.hour_to);
END LOOP;
END LOOP;
RETURN tLimitsInPlan;
END testFunction;
我使用的类型是
TYPE r_limits_in_plan IS RECORD (limit_in_plan_id number
,limit r_limit
,hour_period_data t_hour_period_data_tab
);
TYPE t_limits_in_plan IS TABLE OF r_limits_in_plan INDEX BY binary_integer;
-----------------------------------------------------------------------------------
TYPE r_limit IS RECORD(limit_id number
,ind varchar2(400)
);
TYPE t_limit IS TABLE OF r_limit INDEX BY binary_integer;
-----------------------------------------------------------------------------------
TYPE t_hour_period_data IS RECORD(hour_from number
,hour_to number);
TYPE t_hour_period_data_tab IS TABLE OF t_hour_period_data INDEX BY binary_integer;
编辑:
I'm passing below Limit IDs to this functions
Limit ID: 26
Limit ID: 41
Limit ID: 81
So result that I'm expecting is
For LimitID 26 hours 2-3 / 12-15 / 20-23
41 hours 5-7
81 no hours
小时内的样本数据table
CREATE TABLE hours
(
hour_from NUMBER not null,
hour_to NUMBER not null,
limit_id NUMBER(17) not null
)
INSERT INTO hours (hour_from, hour_to, limit_id) VALUES (12, 13, 23);
INSERT INTO hours (hour_from, hour_to, limit_id) VALUES (2, 3, 26);
INSERT INTO hours (hour_from, hour_to, limit_id) VALUES (12, 15, 26);
INSERT INTO hours (hour_from, hour_to, limit_id) VALUES (20, 23, 26);
INSERT INTO hours (hour_from, hour_to, limit_id) VALUES (5, 7, 41);
有人能帮忙吗?我想我添加了所有需要的信息,但如果有什么需要澄清的,我会更新
最简单的解决方案是使用 SQL 定义的嵌套 table 集合和对象(而不是 PL/SQL 定义的关联数组集合和记录)传递数据,然后您可以在一个查询中完成所有处理:
CREATE TYPE r_limit IS OBJECT(
column1 number
,column2 varchar2(400)
,column3 varchar2(400)
,column4 number
);
CREATE TYPE t_limit IS TABLE OF r_limit;
CREATE TYPE t_hour_period_data IS OBJECT(
hour_from number
,hour_to number
);
CREATE TYPE t_hour_period_data_tab IS TABLE OF t_hour_period_data;
CREATE TYPE r_limits_in_plan IS OBJECT(
column1 number
,column2 varchar2(400)
,column3 varchar2(400)
,column4 varchar2(400)
,limit r_limit
,hour_period_data t_hour_period_data_tab
);
CREATE TYPE t_limits_in_plan IS TABLE OF r_limits_in_plan;
您可以将函数定义为:
CREATE FUNCTION testFunction (p_tLimits t_limit)
RETURN t_limits_in_plan
IS
tLimitsInPlan t_limits_in_plan;
BEGIN
SELECT r_limits_in_plan(
l.column1,
l.column2,
l.column3,
l.column4,
VALUE(l),
( SELECT CAST(
COLLECT(
t_hour_period_data(
h.hour_from,
h.hour_to
)
) AS t_hour_period_data_tab
)
FROM hours h
WHERE l.column1 = h.limit_id
)
)
BULK COLLECT INTO tLimitsInPlan
FROM TABLE(p_tLimits) l;
RETURN tLimitsInPlan;
END testFunction;
/
然后:
DECLARE
v_limits t_limit := t_limit(
r_limit(26, '26 - Col2', '26 - Col3', 26.4),
r_limit(41, '41 - Col2', '41 - Col3', 41.4),
r_limit(81, '81 - Col2', '81 - Col3', 81.4)
);
v_lip t_limits_in_plan;
BEGIN
v_lip := testFunction(v_limits);
FOR i IN 1 .. v_lip.COUNT LOOP
DBMS_OUTPUT.PUT( v_lip(i).column1 || ': ' );
FOR j IN 1 .. v_lip(i).hour_period_data.COUNT LOOP
DBMS_OUTPUT.PUT( v_lip(i).hour_period_data(j).hour_from || '-' );
DBMS_OUTPUT.PUT( v_lip(i).hour_period_data(j).hour_to || ' / ' );
END LOOP;
DBMS_OUTPUT.NEW_LINE();
END LOOP;
END;
/
输出:
26: 2-3 / 12-15 / 20-23 / 41: 5-7 / 81:
db<>fiddle here