Jak w SQL*Plus wyświetlać kolejne rekordy w poziomie?

Dzial developerow

PORADY I WSKAZÓWKI

Gdy wpiszemy jakiekolwiek zapytanie pod SQL*Plus-em to rekordy będą
wyświetlane jeden pod drugim. W pewnych zastosowaniach chcielibyśmy jednak, aby wynik
zapytania był wyświetlony w dwóch, trzech lub większej liczbie kolumn. Przykładem
zastosowania może być sytuacja gdy rekordy są bardzo krótkie i zajmują mało miejsca,
ale za to jest ich sporo. Efekt jaki chcemy wówczas uzyskać może być
następujący:

Bębel Biały Jezierski Kemp
Konopka Koszlajda Kowalski Małkowska
Matysiak Mizgajski Pielacha Rajek

Przeglądanie listy nazwisk, a zwłaszcza gdy zostaną zapisane w pliku
i wydrukowane, będzie znacznie prostsze jeśli zamiast czterech kartek A4 weźmiemy do
ręki tylko jedną. Innym zastosowaniem może być chęć wydrukowania etykiet z adresami,
używając do tego celu po prostu SQL*Plus. Dostępne na rynku arkusze A4 z naklejkami
samoprzylepnymi, które do tego celu można wykorzystać zawierają po dwie, trzy lub
cztery naklejki w rzędzie, więc adresy, które chcemy odczytać z bazy danych powinny
się pojawiać w dwóch, trzech lub czterech kolumnach. Ale do rzeczy, jak to można
zrobić?
Idea jest następująca. Do skryptu SQL-wego, który normalnie byśmy wykorzystali do
wyświetlenia rekordów jeden pod drugim, dodamy blok PL/SQL, który wszystkie wyszukane
rekordy wprowadzi najpierw do pośredniej tabeli. Tabela pośrednia będzie miała taki
schemat, który pozwoli na zapamiętanie w jednym rekordzie kilku rekordów źródłowej
tabeli. Następnie, prostym zapytaniem SQL odczytamy rekordy z tabeli pośredniej
umieszczając po kilka rekordów źródłowych w jednym wierszu.
Weźmy dla przykładu tabelę PRACOWNICY, z której chcemy wyświetlić wszystkie nazwiska
pracowników, a wynik zapisać również w pliku i wydrukować. Normalnie, jeśli nazwiska
miałyby się ukazać jedno pod drugim, to utworzylibyśmy następujący skrypt:

set echo off
set heading off
set feedback off
spool nazwiska.txt
select nazwisko from pracownicy;
spool off
set feedback on
set heading on
set echo on

Teraz załóżmy, że nazwiska mają się pojawić w czterech
kolumnach. Zatem, zgodnie z przedstawioną wyżej ideą, do skryptu dodamy utworzenie
pośredniej tabeli PRAC i blok PL/SQL, który wprowadzi rekordy z tabeli PRACOWNICY do
tabeli PRAC, a następnie wyświetlimy rekordy z tabeli PRAC i ją usuniemy. Skrypt może
wyglądać następująco:

set echo off
set heading off
set feedback off

/******************* Utwórz pośrednią tabelę PRAC */
create table prac(
  nazw1 varchar2(20),
  nazw2 varchar2(20),
  nazw3 varchar2(20),
  nazw4 varchar2(20));

/******************* Wprowadź rekordy do tabeli PRAC */
declare
  cursor c_prac is select * from pracownicy order by nazwisko;
  liczba_kolumn number := 4;
  nazwiska     varchar2(80) := <>;
  kolumna number := 1;
begin
  for P in c_prac loop
  nazwiska := nazwiska || rpad(P.nazwisko,20);
  kolumna := kolumna + 1;
  if kolumna > liczba_kolumn then
    insert into prac values(
      substr(nazwiska, 1,20),
      substr(nazwiska,21,20),
      substr(nazwiska,41,20),
      substr(nazwiska,61,20));
    kolumna := 1;
    nazwiska := <>;
  end if;
end loop;
/****************** Dodaj ostatni niepełny wiersz */
if kolumna > 1 then
  nazwiska := rpad(nazwiska,80);
  insert into prac values(
    substr(nazwiska, 1,20),
    substr(nazwiska,21,20),
    substr(nazwiska,41,20),
    substr(nazwiska,61,20));
  end if;
end;
/
spool nazwiska.txt
select * from prac;
spool off
drop table prac;
set feedback on
set heading on
set echo on

Jeśli w konkretnym zastosowaniu liczba kolumn lub ich szerokość są
inne, skrypt trzeba lekko dostosować. W przypadku gdy oprócz nazwiska chcielibyśmy
wydrukować więcej informacji o pracowniku (np. pełny adres do drukowania na naklejkach)
to oprócz zmiennej nazwiska, która będzie gromadziła pierwszy wiersz z imionami i
nazwiskami, trzeba dodać analogiczne dwie zmienne, np. ulice i miasta do zapamiętywania
w dwóch kolejnych wierszach odczytanych ulic z numerami domów oraz kodów pocztowych z
nazwami miast. Wówczas, zamiast jednego polecenia INSERT pojawią się w pętli trzy
polecenia wstawiające nazwiska, ulice i miasta. Można w tym przypadku dodać również
jeszcze jeden lub kilka poleceń INSERT z samymi wartościami NULL, które będą
oddzielały w pionie kolejne adresy.

Maciej Matysiak
maciej.matysiak@cs.put.poznan.pl
Instytut Informatyki Politechniki Poznańskiej