#oracle #plsql #sql
Есть таблица Lease в которой хранятся данные о договорах, и есть таблица Tenant в которой хранятся данные об арендаторах. Нужно написать курсор, с помощью которого, из Lease выбираются данные об арендаторах, фамилия которых начинается с определенной буквы. Собственно пишет, что команда PL/SQL завершена успешно, но на выходе ничего: SET SERVEROUTPUT ON; --accept firstchar prompt 'Введите первую букву фамилии арендатора: '; DECLARE CURSOR lease_curs2 IS SELECT* FROM Lease; row_lease lease_curs2%ROWTYPE; BEGIN OPEN lease_curs2; WHILE lease_curs2%FOUND LOOP BEGIN FETCH lease_curs2 INTO row_lease; FOR char IN (SELECT* FROM Tenant WHERE Tenant.NTn = row_lease.NTn) LOOP IF char.Tn LIKE 'S%' THEN DBMS_OUTPUT.PUT_LINE ('Lease number: ' || row_lease.NLease); END IF; END LOOP; END; END LOOP; CLOSE lease_curs2; END; /
Ответы
Ответ 1
Что-то вроде этого: declare cursor lease_cur is select * from lease where tn like 'S%' ; lease_rec lease_cur%rowtype; begin open lease_cur; loop fetch lease_cur into lease_rec; dbms_output.put_line('Lease number: '||lease_rec.nlease); exit when lease_cur%NOTFOUND; end loop; close lease_cur; end;Ответ 2
Кроме отсутствующих чтения данных с fetch и закрытия курсора с close, блок в вопросе имеет ряд серьёзных недостатков: Вложенные циклы с открытием нового курсора внутри цикла - плохая практика. Надо по возможности ограничиться одним запросом, и пусть цикл выполняется в SQL движке, он сделает это наиболее эффективно. Не надо держать курсоры открытыми обрабатывая пошагово данные в цикле. Это не клиентское приложение, блок выполняется на сервере. Лучше считать все данные в табличную переменную и потом работать с ней. Рабочий пример учитывая вышесказанное: declare cursor cur (prefix varchar2) is select * from tenant t join lease l on l.ntn = t.ntn where t.tn like prefix||'%' ; type arr is table of cur%rowtype; rows arr; begin open cur ('S'); fetch cur bulk collect into rows; close cur; for ix in 1..rows.count loop dbms_output.put_line ('Lease number: '||rows(ix).nlease||' for '||rows(ix).tn); end loop; end; / Вывод: Lease number: 10 for Smith Lease number: 20 for Sue Тестовые данные для примера: with tenant (ntn, tn) as ( select rownum, trim (column_value) from xmltable ('"Smith", "Sue", "Woo"')), lease (nlease, ntn) as ( select ntn*10, ntn from tenant )Ответ 3
Ваша ошибка в том, что вы забыли перед WHILE lease_curs2%FOUND добавить FETCH lease_curs2 INTO row_lease; DECLARE CURSOR lease_curs2 IS SELECT* FROM Lease; row_lease lease_curs2%ROWTYPE; BEGIN OPEN lease_curs2; FETCH lease_curs2 INTO row_lease; WHILE lease_curs2%FOUND LOOP BEGIN FETCH lease_curs2 INTO row_lease; FOR char IN (SELECT* FROM Tenant WHERE Tenant.NTn = row_lease.NTn) LOOP IF char.Tn LIKE 'S%' THEN DBMS_OUTPUT.PUT_LINE ('Lease number: ' || row_lease.NLease); END IF; END LOOP; END; END LOOP; CLOSE lease_curs2; END; /
Комментариев нет:
Отправить комментарий