#oracle #plsql
#Oracle #plsql
Вопрос:
Мой код:
create table dep_emp_ast(
cod_dep number(3),
cod_ang number(3));
declare
type tab_imb is table of dept_ast.department_id%type;
type ang is table of emp_ast.employee_id%type;
v_ang ang:=ang();
t tab_imb:=tab_imb();
begin
select department_id
bulk collect into t
from dept_ast;
for i in 1..t.count loop
select employee_id bulk collect into v_ang
from emp_ast
where department_id=t(i);
forall j in 1..v_ang.count
insert into dep_emp_ast
values(t(i), v_ang(j));
dbms_output.put_line( sql%bulk_rowcount(j));
v_ang.delete;
end loop;
end;
/
Я получаю «Идентификатор ‘j’ должен быть объявлен»» при попытке вызвать sql%bulk_rowcount (j);
Я знаю, что могу использовать sql%bulk_rowcount (index) в циклах for или forall .
Комментарии:
1. Вы нигде не объявили
j
.
Ответ №1:
Вот рабочая версия.
Я переименовал некоторые переменные, чтобы их было легче понять (по крайней мере, для меня), и добавил еще несколько dbms_output
сообщений, чтобы более четко показать, что он делает.
declare
type tab_dept is table of dept_ast.department_id%type;
type tab_emp is table of emp_ast.employee_id%type;
employees_t tab_emp := tab_emp();
departments_t tab_dept := tab_dept();
begin
select department_id bulk collect into departments_t
from dept_ast;
dbms_output.put_line(departments_t.count || ' departments added to departments_t');
for i in 1 .. departments_t.count loop
select employee_id bulk collect into employees_t
from emp_ast where department_id = departments_t(i);
dbms_output.put_line(employees_t.count || ' employees added to employees_t for department_id '||departments_t(i));
forall j in 1 .. employees_t.count
insert into dep_emp_ast
values
( departments_t(i)
, employees_t(j) );
for k in 1 .. employees_t.count loop
dbms_output.put_line('sql%bulk_rowcount('||k||') = '|| sql%bulk_rowcount(k));
end loop;
dbms_output.put_line('sql%rowcount = ' ||sql%rowcount);
employees_t.delete;
end loop;
end;
Вывод:
3 departments added to departments_t
2 employees added to employees_t for department_id 1
sql%bulk_rowcount(1) = 1
sql%bulk_rowcount(2) = 1
sql%rowcount = 2
2 employees added to employees_t for department_id 2
sql%bulk_rowcount(1) = 1
sql%bulk_rowcount(2) = 1
sql%rowcount = 2
2 employees added to employees_t for department_id 3
sql%bulk_rowcount(1) = 1
sql%bulk_rowcount(2) = 1
sql%rowcount = 2
Тестовая настройка:
create table dep_emp_ast(
cod_dep number(3),
cod_ang number(3));
create table dept_ast
( department_id number );
create table emp_ast
( employee_id number
, department_id number );
delete dept_ast;
delete emp_ast;
insert all
into dept_ast values (1)
into dept_ast values (2)
into dept_ast values (3)
into emp_ast (department_id, employee_id) values (1, 10)
into emp_ast (department_id, employee_id) values (1, 20)
into emp_ast (department_id, employee_id) values (2, 30)
into emp_ast (department_id, employee_id) values (2, 40)
into emp_ast (department_id, employee_id) values (3, 50)
into emp_ast (department_id, employee_id) values (3, 60)
select * from dual;
Ответ №2:
@WilliamRobertson прав в своем комментарии, что «вы нигде не объявили j», и я верю ему на слово, что это рабочая версия. Но ни то, ни другое на самом деле не объясняет, почему вы получаете ошибку. Ваш код на самом деле показывает 2 заблуждения.
Сначала инициализация (из-за отсутствия лучшей работы) FOR и FORALL
FOR <index> IN <lower bound> .. <upperbound> Loop ... END LOOP;
FORALL <index> IN <lower bound> .. <upperbound> DML statement;
В обоих случаях переменная создается только на время действия инструкции. Таким образом, когда цикл или оператор DML завершается, переменная больше не существует. Таким образом, когда вы использовали переменную j после завершения вставки, она больше не существовала. Даже если вы объявляете переменную с тем же именем, правила определения области действия делают их разными переменными (см. Пример здесь).
У вас есть и другая проблема. SQL%bulk_rowcount содержит запись as для каждой обработанной строки строки, но поскольку индексная переменная forall больше не существует, вам нужен цикл FOR для их итерации. Итак, после forall:
for j in 1..v_ang.count
loop
dbms_output.put_line( ' Rows for ' || v_ang(j) || ':' || SQL%bulk_rowcount(j));
end loop;
Но предполагая, что v_ang содержит таблицу PK для employee (кажется вероятным), которая просто предоставит вам список из 1. Возможно, вам действительно нужен SQL%Rowcount . Это дает вам общее количество обработанных строк.
Я надеюсь, это поможет вам понять для (всех) переменных индекса цикла.