#arrays #oracle #plsql
Вопрос:
Я новичок в изучении PLSQL и определенно новичок в типе объектов (абстрактных типах данных) в PLSQL. Так или иначе, я увидел код в своей компании, использующий оператор таблицы при определении курсора, поэтому я подумал попробовать это. В следующем анонимном блоке я получаю ошибку «PLS-00386: несоответствие типа, найденное в» V_CU», между курсором ВЫБОРКИ и переменными», но когда я использую c%rowtype (прокомментированная часть) вместо obj_emp при объявлении V_CU, я не получаю эту ошибку. Я не могу понять причину этой ошибки.
В конце концов, строка курсора c состоит из одного элемента объекта obj_emp, не так ли?
CREATE OR REPLACE TYPE obj_emp IS OBJECT (
first_name VARCHAR2(80),
last_name VARCHAR2(80),
salary NUMBER
);
/
CREATE OR REPLACE TYPE tab_emp_t IS TABLE OF obj_emp;
/
declare
v_num number:=60;
tab_emp tab_emp_t :=tab_emp_t();
cursor c is select * from table(tab_emp);
v_cu obj_emp --c%rowtype
;
begin
for i in (select * from employees_copy where department_id = v_num) loop
tab_emp.extend;
tab_emp(tab_emp.last):=obj_emp(i.first_name, i.LAST_NAME, i.salary);
end loop;
open c;
loop
fetch c into v_cu;
exit when c%notfound;
dbms_output.put_line(v_cu.first_name||' '||v_cu.last_name||' earns '||v_cu.salary);
end loop;
close c;
end;
/
Ответ №1:
Ожидается ошибка; она исправлена, если вы раскомментируете v_cu
тип данных — он все равно должен быть c%rowtype
.
Но я думаю, что вы хотели попробовать показать значения, хранящиеся в коллекции. Если это так, взгляните на следующий код (немного изменив то, что вы написали; у меня нет ваших таблиц, поэтому я использовал EMP
вместо них таблицы Скотта).
SQL> declare
2 v_num number:=10;
3 tab_emp tab_emp_t :=tab_emp_t();
4 v_cnt number:=1;
5 cursor c is select * from table(tab_emp);
6 v_cu c%rowtype; --obj_emp --c%rowtype
7
8 begin
9 dbms_output.put_line('-------- Store values into a collection ---------');
10 for i in (select * from emp where deptno = v_num) loop
11 tab_emp.extend;
12 tab_emp(v_cnt):=obj_emp(i.ename, i.job, i.sal);
13 v_cnt:=v_cnt 1;
14 end loop;
15 v_cnt:=1;
16
17 dbms_output.put_line('-------- Display values from a cursor -----------');
18 open c;
19 loop
20 fetch c into v_cu;
21 exit when c%notfound;
22 dbms_output.put_line(v_cu.first_name||' '||v_cu.last_name||' earns '||v_cu.salary);
23 end loop;
24
25 dbms_output.put_line('-------- Display values from a collection -------');
26
27 for i in tab_emp.first .. tab_emp.last loop
28 dbms_output.put_Line(tab_emp(i).first_name ||' '|| tab_emp(i).last_name ||' earns ' || tab_emp(i).salary);
29 end loop;
30 end;
31 /
Результаты в
-------- Store values into a collection ---------
-------- Display values from a cursor -----------
CLARK MANAGER earns 2450
KING PRESIDENT earns 5000
MILLER CLERK earns 1300
-------- Display values from a collection -------
CLARK MANAGER earns 2450
KING PRESIDENT earns 5000
MILLER CLERK earns 1300
PL/SQL procedure successfully completed.
SQL>
Комментарии:
1. Спасибо Литтлфут за то, что уделили мне время. Я просто хотел правильно извлечь данные из курсора и, вероятно, отобразить значения из курсора. Мой вопрос, который остается без ответа, заключается в том, какой именно тип правильного v_cu. Как это не obj_emp? и каков тип c%rowtype, если он отличается от obj_emp?
2. V_CU является переменной курсора и должна принимать значения, возвращаемые курсором, поэтому ее тип данных-C%ROWTYPE. Взгляните на статью Стивена Фейерштейна здесь ( blogs.oracle.com/oraclemagazine/working-with-cursors ) для получения дополнительной информации и примеров.
3. Привет, Лайтфут, я проверил эту статью, но, думаю, вы не поняли мой вопрос. Я знаю, что когда я объявляю v_cu как тип строки курсора c, это работает нормально, но когда я явно объявляю v_cu как obj_emp, это не работает. Мой вопрос в том, что на самом деле является типом c%rowtype, если не obj_emp? Курсор выбирается из коллекции объектов obj_emp, поэтому я не ошибусь, предположив, что каждая строка курсора c в основном является obj_emp, и, следовательно, я не ошибусь, если получу строки курсора c в переменный экземпляр v_cu obj_emp. Но, увы, я не могу этого сделать!!!