Садржај
1 Релационе базе података
1.0 1 Релационе базе података
1.0 2 Релационе базе података - квиз
1.0 3 Веза један према више
1.0 4 Веза један према више - квиз
1.0 5 Веза више према више
1.0 6 Веза више према више - квиз
1.0 7 Алат за пројектовање
1.0 8 СУБП
1.0 9 Креирање базе на други начин
1.0 10 Још неке SQL команде
1.1 1 Упит SELECT
1.1 2 Упит SELECT - упит из једне табеле - задаци
1.1 3 Упит SELECT - упит из једне табеле - квиз
1.1 4 Упит SELECT - функције и подупити - задаци
1.1 5 Упит SELECT - функције и подупити - квиз
1.1 6 Упит SELECT - спајање - задаци
1.1 7 Упит SELECT - спајање - квиз
1.1 8 Упит SELECT - нерешени задаци
1.2 1 База података за библиотеку - креирање базе
1.2 2 БП Библиотека - Упит SELECT - упит из једне табеле - задаци
1.2 3 БП Библиотека - Упит SELECT - упит из једне табеле - нерешени задаци
1.2 4 БП Библиотека - Упит SELECT - спајање - задаци
1.2 5 БП Библиотека - Упит SELECT - спајање - нерешени задаци
1.2 6 БП Библиотека - Упит SELECT - функције и подупити - задаци
1.2 7 БП Библиотека - Упит SELECT - функције и подупити - нерешени задаци
1.3 1 База података за возачке дозволе - креирање базе
1.3 2 БП Возачке дозволе - Дијаграм и подаци - практичан рад
1.3 3 БП Возачке дозволе - Упит SELECT - задаци
1.3 4 БП Возачке дозволе - Упит SELECT - нерешени задаци
1.4 1 БП Филмови - Креирање базе - практични рад
1.4 2 БП Филмови - Дијаграм и подаци - практични рад
1.4 3 БП Филмови - Упит SELECT - задаци
1.4 4 БП Филмови - Упит SELECT - нерешени задаци
2 Писање програма унутар система за управљање базама података
2.0 1 Процедуре и команда INSERT
2.0 2 Процедуре и команде UPDATE и DELETE
2.0 3 Процедуре и команде INSERT, UPDATE, и DELETE - квиз
2.0 4 Процедуре и тестирање програма
2.0 5 Процедуре и упит SELECT
2.0 6 Процедуре и курсор за упит SELECT
2.1 1 Функције и упит SELECT
2.1 2 Процедуре и функције са упитом SELECT - квиз
2.1 3 Процедуре и функције са упитом SELECT из једне табеле - задаци
2.1 4 Процедуре и функције са упитом и групним функцијама - задаци
2.1 5 Процедуре и функције са упитом SELECT са спајањем табела - задаци
2.1 6 Процедуре и функције са упитом - нерешени задаци
2.1 7 Формат XML
2.2 1 База података за библиотеку - Процедуре, функције и поређење различитих решења
2.2 2 Процедуре, функције и поређење различитих решења
2.2 3 Процедуре и функције са упитом SELECT из једне табеле - вежбање
2.2 4 Процедуре и функције са упитом SELECT са спајањем табела - вежбање
2.2 5 Процедуре и функције са упитом и групним функцијама и подупитима - вежбање
2.2 6 Процедуре и функције са упитом SELECT - нерешени задаци
2.3 1 База података за возачке дозволе - процедуре и функције са упитом SELECT - вежбање
2.3 2 База података за возачке дозволе - процедуре и функције - нерешени задаци
2.4 1 База података за филмове - процедуре и функције са упитом SELECT - вежбање
2.4 2 База података за филмове - процедуре и функције - нерешени задаци
3 Писање програма у програмским језицима вишег нивоа
3.0 1 Писање програма у развојном окружењу Visual Studio
3.0 2 Писање програма у развојном окружењу Visual Studio - практичан рад
3.0 3 Писање програма у развојном окружењу Visual Studio - процедуре
3.0 4 Писање програма у развојном окружењу Visual Studio - квиз
3.1 1 Угнежђени упит SELECT унутар програма
3.1 2 Угнежђени упит SELECT унутар програма - задаци
3.1 3 Позив процедуре унутар програма
3.1 4 Позив креиране функције унутар програма
3.1 5 Програм са угнежђеним командама у развојном окружењу Visual Studio - квиз
3.1 6 Програм са угнежђеним упитом SELECT из једне табеле - вежбање
3.1 7 Програм са угњежђеним упитом и групним фунцкијама - вежбање
3.1 8 Програм са угнежђеним упитом SELECT са спајањем табела - вежбање
3.1 9 Програм са класом
3.1 10 Програм са угнежђеним упитом - нерешени задаци
3.1 11 Програм са угнежђеним командама INSERT, UPDATE, и DELETE
3.2 1 База података за библиотеку - програм са угнежђеним упитом SELECT из једне табеле - задаци
3.2 2 База података за библиотеку - програм са угнежђеним упитом SELECT - вежбање
3.2 3 База података за библиотеку - програм са угнежђеним упитом - нерешени задаци
3.3 1 База података за возачке дозволе - програм са угнежђеним упитом SELECT - вежбање
3.3 2 База података за возачке дозволе - програм са угнежђеним упитом - нерешени задаци
3.4 1 База података за филмове - програм са угнежђеним упитом SELECT - вежбање
3.4 2 База података за филмове - програм са угнежђеним упитом - нерешени задаци
4 Друга софтверска решења - СУБП Oracle
4.0 1 Oracle Apex и језик PL/SQL
4.0 2 Језик PL/SQL - задаци
4.0 3 Језик PL/SQL - квиз
4.0 4 Језик PL/SQL – нерешени задаци
4.0 5 Наредбе гранања
4.0 6 Наредбе гранања - нерешени задаци
4.0 7 Наредбе циклуса
4.0 8 Наредбе циклуса - нерешени задаци
4.1 1 База података за библиотеку - практичан рад
4.1 2 Наредба SELECT INTO
4.1 3 Наредба SELECT INTO - zadaci
4.1 4 Наредба SELECT INTO - квиз
4.1 5 Наредба SELECT INTO - вежбање
4.1 6 Наредба SELECT INTO - нерешени задаци
4.2 1 Курсори - Узимање података из више редова
4.2 2 Курсори - задаци
4.2 3 Различити начини да се реши проблем
4.2 4 Курсори - нерешени задаци
4.2 5 Курсор са параметром
4.2 6 Курсор са параметром - задаци
4.2 7 Курсор са параметром - нерешени задаци
4.2 8 Курсори - квиз
4.2 9 Курсори и гранање - задаци
4.2 10 Курсори - вежбање
4.2 11 Тренутне позајмице члана - пример
4.2 12 Спискови књига - пример
4.3 1 Процедуре и функције у СУБП-у Oracle Apex
4.3 2 Процедуре и функције - задаци
4.3 3 Процедуре и функције - нерешени задаци
4.3 4 Позајмице једне књиге - пример
4.3 5 Тренутне позајмице - пример
4.3 6 Процедуре и друге SQL команде
4.3 7 Тригери
4.3 8 Списак свих објеката у бази података
4.4 1 Креирање апликације помоћу алата App Builder
4.4 2 Додатне опције App Builder алата
4.4 3 Покретање апликације
4.4 4 Креирање нових страница у апликацији
4.4 5 Покретање раније креиране процедуре
4.4 6 Алат App Builder и XML
4.5 1 База података за салон аутомобила у СУБП-у Oracle Apex - 1. део
4.5 2 База података за салон аутомобила у СУБП-у Oracle Apex - 2. део
4.5 3 База података за салон аутомобила у СУБП-у Oracle Apex - 3. део
4.5 4 База података за продавницу - нерешени пројектни рад

Процедуре и курсор за упит SELECT

Већ смо видели једно могуће програмерско решење када библиотека жели да провери колико има примерака књига неког издавача да би размотрили да ли да набављају још књига. Процедуре имају и друге могућности. Можемо, на пример, за сваку књигу прво да прикажемо број примерака, а затим да излистамо њене примерке уколико их имамо у бази. Да бисмо могли ово да постигнемо, потребни су нам курсори (енг. сursor).

Следи другачије решење истог проблема за који смо већ писали процедуру, али са објашњењем како се користе курсори.

Сви приказани примери су у вези са табелама које чине део базе података за библиотеку. Следи списак свих табела са колонама. Примарни кључеви су истакнути болд, а страни италик.

../_images/slika_512a.jpg

Програмски код, као и команде језика SQL, пише се и покреће када се кликне New Query након што се покрене систем SQL Server и кликне на креирану базу Biblioteka_knjige у прозору Object Explorer. Фајл са упитима SQLQuery1.sql може, а и не мора да се сачува.

Након што се унесе програмски код, кликне се на дугме Execute. Уколико се у простору за писање команди налази више блокова кода, потребно је обележити онај који желимо да покренемо. Ако имате више база података, обавезно проверите да ли је поред овог дугмета назив базе у којој желите да покрећете програме.

../_images/slika_510a.jpg

Написаћемо другачију процедуру која такође може да се користи у ситуацији када библиотека жели да провери колико има примерака књига неког издавача како би размотрили да ли да набављају још књига тог издавача. За сваку књигу ћемо прво да прикажемо број примерака, а затим да излистамо њене примерке уколико их имамо у бази.

Ако желимо да прођемо појединачно ред по ред кроз више редова које враћа неки упит, неопходно је да користимо курсор. У овом примеру нам прво треба курсор који ће редом да обради једну по једну књигу изабраног издавача.

Курсор се декларише тако што му се додели назив и веже се за упит SELECT који најчешће враћа више редова.

DECLARE kursor_knjige CURSOR FOR
SELECT knjige.naziv FROM
knjige JOIN izdavaci ON (knjige.id_izdavaca=izdavaci.id)
WHERE izdavaci.naziv = @izdavac;

Уз курсор је важно декларисати и променљиве које ће нам служити да у њих учитамо вредности из табеле на које курсор показује. Како овај упит враћа само назив књиге, довољна нам је једна променљива која је истог типа као одговарајућа колона у табели knjige.

DECLARE @naziv VARCHAR(50);

Да бисмо радили са курсором, неопходни су следећи кораци након декларације:

  1. курсор се отвори,

  2. прочитамо један ред у променљиву коју смо декларисали,

  3. у циклусу се помоћу курсора чита један по један ред док се не прочитају сви редови резултата одговарајућег SELECT упита,

  4. курсор се затвори и ослободи се меморија.

Следе команде којима то постижемо.

--otvaranje kursora i citanje prvog reda
OPEN kursor_knjige;
FETCH NEXT FROM kursor_knjige INTO @naziv;

--ciklus se izvrsava dokle god nema greske pri citanju
WHILE @@FETCH_STATUS = 0
BEGIN
    --mozemo da prikazemo podatak koji smo procitali
    PRINT 'KNJIGA: '+@naziv;

    --OSTALE KOMANDE U CIKLUSU

    --citanje narednog reda
    FETCH NEXT FROM kursor_knjige INTO @naziv;
END

--zatvaranje kursora i oslobadjanje memorije
CLOSE kursor_knjige;
DEALLOCATE kursor_knjige;

Користимо @@FETCH_STATUS да проверимо да ли је дошло до грешке приликом читања. Уколико нема грешке, вредност је нула. Уколико је дошло до неке грешке, на пример, покушавамо да прочитамо ред, а података више нема, вредност ће бити различита од нуле и приказиваће код грешке.

Овај програмски код ћемо спаковати у процедуру sve_knjige_izdavaca_izvestaj. Када се покрене, процедура остаје запамћена у систему.

CREATE PROCEDURE sve_knjige_izdavaca_izvestaj @izdavac varchar(40)
AS
DECLARE kursor_knjige CURSOR FOR
SELECT knjige.naziv FROM
knjige JOIN izdavaci ON (knjige.id_izdavaca=izdavaci.id)
WHERE izdavaci.naziv = @izdavac;
DECLARE @naziv VARCHAR(50);

OPEN kursor_knjige;
FETCH NEXT FROM kursor_knjige INTO @naziv;

WHILE @@FETCH_STATUS = 0
BEGIN
    PRINT 'KNJIGA: '+@naziv;
    FETCH NEXT FROM kursor_knjige INTO @naziv;
END
CLOSE kursor_knjige;
DEALLOCATE kursor_knjige;

Након што се покрене овај програмски код кликом на дугме Execute, процедура остаје сачувана у систему и можемо да је позовемо командом EXEC. На следећој слици се види резултат када покренемо процедуру за једног издавача.

../_images/slika_516a.jpg

Можемо сада да напишемо процедуру svi_primerci_izdavaca_izvestaj коју смо планирали са списком свих примерака. Како у нашем примеру за сваку књигу желимо да прикажемо све примерке, можемо да искористимо комплетан програмски код који смо већ написали унутар претходне процедуре и да у циклусу додамо још један курсор, који ће за једну књигу да излиста све примерке. За овај курсор ћемо такође имати циклус за који кажемо да је угњежден у претходни. Можемо да додамо и упит SELECT, којим ћемо за једну књигу да узмемо број примерака, а ако књига нема примерке, нећемо креирати други курсор и нећемо улазити у угњеждени циклус.

Овај други курсор користи променљиву @naziv да би се издвојили само примерци књиге са тим називом.

DECLARE kursor_primerci CURSOR FOR
SELECT inventarski_broj
FROM primerci JOIN knjige ON (primerci.id_knjige=knjige.id_knjige)
WHERE naziv=@naziv;

Уз овај курсор треба декларисати и променљиву за инвентарски број који прочитамо из базе. Следи комплетан програмски код процедуре. Након покретања програмског кода, процедура остаје запамћена у бази.

CREATE PROCEDURE svi_primerci_izdavaca_izvestaj @izdavac varchar(40)
AS
DECLARE kursor_knjige CURSOR FOR
SELECT knjige.naziv FROM
knjige JOIN izdavaci ON (knjige.id_izdavaca=izdavaci.id)
WHERE izdavaci.naziv = @izdavac;
DECLARE @naziv VARCHAR(50);

OPEN kursor_knjige;
FETCH NEXT FROM kursor_knjige INTO @naziv;

WHILE @@FETCH_STATUS = 0
BEGIN
    PRINT 'KNJIGA: '+@naziv;

    DECLARE @broj_primeraka INT;
    SELECT @broj_primeraka = COUNT(*)
    FROM primerci JOIN knjige ON (primerci.id_knjige=knjige.id_knjige)
    WHERE naziv=@naziv;

    PRINT 'Broj primeraka: '+ CAST(@broj_primeraka AS VARCHAR(10));

    IF @broj_primeraka>0
        BEGIN
            DECLARE kursor_primerci CURSOR FOR
            SELECT inventarski_broj
            FROM primerci JOIN knjige ON (primerci.id_knjige=knjige.id_knjige)
            WHERE naziv=@naziv;
            DECLARE @inventarski_broj INT;

            OPEN kursor_primerci;
            FETCH NEXT FROM kursor_primerci INTO @inventarski_broj;

            WHILE @@FETCH_STATUS = 0
            BEGIN
                PRINT '  Primerak: '+CAST(@inventarski_broj AS VARCHAR(10));
                FETCH NEXT FROM kursor_primerci INTO @inventarski_broj;
            END;
            CLOSE kursor_primerci;
            DEALLOCATE kursor_primerci;
        END

    FETCH NEXT FROM kursor_knjige INTO @naziv;
END
CLOSE kursor_knjige;
DEALLOCATE kursor_knjige;

Када уз неку текстуалну поруку исписујемо број помоћу PRINT, потребно је да употребимо функцију за конверзију CAST која ће број пребацити у текстуални облик, на пример:

CAST(@broj_primeraka AS VARCHAR(10))

Када покренемо процедуру за једног издавача, добијамо прегледан списак свих његових књига и свих примерака.

EXEC svi_primerci_izdavaca_izvestaj @izdavac='CET'
../_images/slika_516b.jpg

Уколико библиотеци повремено, на пример, једном годишње, треба комплетан извештај о свим примерцима свих књига свих издавача, можемо да направимо и такву процедуру. Употребићемо један курсор да прођемо једног по једног издавача. За сваког издавача ћемо креирати курсор за све његове књиге и проћићемо помоћу угњежденог циклуса кроз те књиге. У том угњежденом циклусу имамо и трећи курсор и угњеждени циклус који користимо да за сваку књигу излистамо све примерке.

Ова процедура није ефикасна зато што је кубне сложености. Поред тога, у бази податка са веома великом количином података се процедура можда неће успешно ни извршити уколико се не дода ограничење броја редова који се узимају, било опцијом TOP или неком другом опцијом.

CREATE PROCEDURE svi_primerci_izvestaj
AS
DECLARE kursor_izdavaci CURSOR FOR
SELECT naziv FROM izdavaci;
DECLARE @izdavac VARCHAR(40);

OPEN kursor_izdavaci;
FETCH NEXT FROM kursor_izdavaci INTO @izdavac;

WHILE @@FETCH_STATUS = 0
BEGIN
    PRINT 'IZDAVAC: '+@izdavac;

    DECLARE kursor_knjige CURSOR FOR
    SELECT knjige.naziv FROM
    knjige JOIN izdavaci ON (knjige.id_izdavaca=izdavaci.id)
    WHERE izdavaci.naziv = @izdavac;
    DECLARE @naziv VARCHAR(50);

    OPEN kursor_knjige;
    FETCH NEXT FROM kursor_knjige INTO @naziv;

    WHILE @@FETCH_STATUS = 0
    BEGIN
        PRINT ' KNJIGA: '+@naziv;

        DECLARE @broj_primeraka INT;
        SELECT @broj_primeraka = COUNT(*)
        FROM primerci JOIN knjige ON (primerci.id_knjige=knjige.id_knjige)
        WHERE naziv=@naziv;

        PRINT ' Broj primeraka: '+ CAST(@broj_primeraka AS VARCHAR(10));

        IF @broj_primeraka>0
        BEGIN
            DECLARE kursor_primerci CURSOR FOR
            SELECT inventarski_broj
            FROM primerci JOIN knjige ON (primerci.id_knjige=knjige.id_knjige)
            WHERE naziv=@naziv;
            DECLARE @inventarski_broj INT;

            OPEN kursor_primerci;
            FETCH NEXT FROM kursor_primerci INTO @inventarski_broj;

            WHILE @@FETCH_STATUS = 0
            BEGIN
            PRINT '   Primerak: '+CAST(@inventarski_broj AS VARCHAR(10));
            FETCH NEXT FROM kursor_primerci INTO @inventarski_broj;
            END;
            CLOSE kursor_primerci;
            DEALLOCATE kursor_primerci;
        END

    FETCH NEXT FROM kursor_knjige INTO @naziv;
END
CLOSE kursor_knjige;
DEALLOCATE kursor_knjige;

FETCH NEXT FROM kursor_izdavaci INTO @izdavac;
END
CLOSE kursor_izdavaci;
DEALLOCATE kursor_izdavaci;

Увек треба имати у виду да се TOP, или нека друга опција за ограничавање броја редова који се узимају, обавезно користи у већим базама података.

Када се програмски код покрене, процедура остаје сачувана у бази података. По потреби може да се покрене.

EXEC svi_primerci_izvestaj

На следећој слици се види део резултата.

../_images/slika_516c.jpg
(Created using Swinx, RunestoneComponents and PetljaDoc)
© 2022 Petlja
A- A+