Changes between Version 5 and Version 6 of DatabaseProgramming


Ignore:
Timestamp:
06/16/26 14:21:23 (14 hours ago)
Author:
231025
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • DatabaseProgramming

    v5 v6  
    33
    44
    5 Во оваа фаза се надоградуваме со функции и процедури што ќе помогнат дел од честите операции во базата-отворање записник, додавање прекршок, наплата на казна, додавање категорија на возачка-да се извршуваат преку еден повик, со сите потребни проверки веќе вградени во нив. Исто така искористивме и тригери за работите што треба да се случуваат автоматски, како пресметката на вкупниот износ во уплатата и строга контрола на интегритетот, без рачно ажурирање.[[BR]]
     5Во оваа фаза се надоградуваме со функции и процедури што ќе помогнат дел од честите операции во базата-отворање записник, додавање прекршок, наплата на казна, затворање записник по платена казна, додавање категорија на возачка-да се извршуваат преку еден повик, со сите потребни проверки веќе вградени во нив. Исто така искористивме и тригери за работите што треба да се случуваат автоматски, како пресметката на вкупниот износ во уплатата и строга контрола на интегритетот, без рачно ажурирање.[[BR]]
    66[attachment:programming.sql programming.sql]
    77
     
    9393=== Тригер 3: trigger_proverka_registracija===
    9494
    95 Овој тригер е задолжен за проверка на интегритетот на податоците пред да се изврши вметнување или ажурирање во табелата `Registracija`. Тој прави соодветна валидација за постоење на сопственикот (граѓанинот) и самото возило преку нивните примарни клучеви. Како клучен дел од валидацијата, тригерот користи регуларен израз (REGEX) за да осигура дека регистарската табличка го следи официјалниот македонски стандард (на пр. SK-1234-AA или BT-888-ZZ).
     95Овој тригер е задолжен за проверка на интегритетот на податоците пред да се изврши вметнување или ажурирање во табелата `Registracija`. По новата шема, `Registracija` повеќе не ги содржи директно граѓанинот и возилото-таа референцира `Sopstvenost` (преку `id_sopstvenost`) и `Registerska_tablica` (преку `id_tablica`). Затоа тригерот прави валидација дека сопственоста постои и дека, доколку е доделена табличка, таа табличка постои. Како клучен дел од валидацијата, тригерот користи регуларен израз (REGEX) врз составениот запис на табличката (регион-број-код) за да осигура дека таа го следи официјалниот македонски стандард (на пр. SK-1234-AA или BT-888-ZZ).
    9696
    9797{{{#!sql
     
    100100LANGUAGE plpgsql
    101101AS $$
    102 BEGIN
    103 IF NOT EXISTS (SELECT 1 FROM Gragjanin WHERE EMBG = NEW.EMBG) THEN
    104 RAISE EXCEPTION 'Граѓанинот со ЕМБГ % не постои во системот!', NEW.EMBG;
    105 END IF;
    106 
    107 IF NOT EXISTS (SELECT 1 FROM Vozilo WHERE broj_na_sasija = NEW.broj_na_sasija) THEN
    108     RAISE EXCEPTION 'Возилото со број на шасија % не постои во системот!', NEW.broj_na_sasija;
    109 END IF;
    110 
    111 IF NEW.registerska_tablica IS NOT NULL AND NOT (UPPER(NEW.registerska_tablica) ~ '^[A-Z]{2}-[0-9]{3,4}-[A-Z]{2}$') THEN
    112     RAISE EXCEPTION 'Регистарската табличка "%" не е во валиден формат! Очекуван формат: ZZ-0000-ZZ (напр. SK-1234-AA)', NEW.registerska_tablica;
     102DECLARE
     103v_tablica text;
     104BEGIN
     105IF NOT EXISTS (SELECT 1 FROM Sopstvenost WHERE id_sopstvenost = NEW.id_sopstvenost) THEN
     106RAISE EXCEPTION 'Сопственоста со id % не постои во системот!', NEW.id_sopstvenost;
     107END IF;
     108
     109IF NEW.id_tablica IS NOT NULL THEN
     110    SELECT region || '-' || broj || '-' || kod
     111    INTO v_tablica
     112    FROM Registerska_tablica
     113    WHERE id_tablica = NEW.id_tablica;
     114
     115    IF v_tablica IS NULL THEN
     116        RAISE EXCEPTION 'Регистарската табличка со id % не постои!', NEW.id_tablica;
     117    END IF;
     118
     119    IF NOT (UPPER(v_tablica) ~ '^[A-Z]{2,3}-[0-9]{3,4}-[A-Z]{2}$') THEN
     120        RAISE EXCEPTION 'Регистарската табличка "%" не е во валиден формат! Очекуван формат: ZZ-0000-ZZ (напр. SK-1234-AA)', v_tablica;
     121    END IF;
    113122END IF;
    114123
     
    127136
    128137=== Процедура 1: kreiraj_zapisnik_so_prekrsok ===
    129 Отвора нов записник со прв прекршок и веднаш креира празна уплата со статус 'Neplateno'. Износот го пополнува тригерот штом ќе се вметне првата ставка. Прво проверува дали постојат граѓанинот, полицаецот, возилото, прекршокот и случајот.
     138Отвора нов записник со прв прекршок и веднаш креира празна уплата со статус 'Neplateno'. Записникот се отвора со `status_zapisnik = 'Otvoren'` (преку default). Износот го пополнува тригерот штом ќе се вметне првата ставка. Прво проверува дали постојат граѓанинот, полицаецот, возилото, прекршокот и случајот.
    130139
    131140{{{#!sql
     
    340349}}}
    341350
     351=== Процедура 5: zatvori_zapisnik_po_uplata ===
     352Го затвора записникот (`status_zapisnik` → 'Zatvoren') откако казната за него е платена. Дозволува затворање само ако постои уплата за записникот и нејзиниот статус е 'Plateno'; не дозволува повторно затворање на веќе затворен записник. Вообичаено се повикува веднаш по `plati_kazna`.
     353
     354{{{#!sql
     355CREATE OR REPLACE PROCEDURE zatvori_zapisnik_po_uplata(
     356p_id_zapisnik int
     357)
     358LANGUAGE plpgsql
     359AS $$
     360DECLARE
     361v_status_uplata    varchar(30);
     362v_status_zapisnik  varchar(20);
     363BEGIN
     364SELECT status_zapisnik INTO v_status_zapisnik
     365FROM Zapisnik WHERE id_na_zapisnik = p_id_zapisnik;
     366
     367IF v_status_zapisnik IS NULL THEN
     368    RAISE EXCEPTION 'Zapisnikot so id % ne postoi!', p_id_zapisnik;
     369END IF;
     370IF v_status_zapisnik = 'Zatvoren' THEN
     371    RAISE EXCEPTION 'Zapisnikot % e vekje zatvoren!', p_id_zapisnik;
     372END IF;
     373
     374SELECT status INTO v_status_uplata
     375FROM Uplata WHERE id_zapisnik = p_id_zapisnik;
     376
     377IF v_status_uplata IS NULL THEN
     378    RAISE EXCEPTION 'Ne postoi uplata za zapisnik %!', p_id_zapisnik;
     379END IF;
     380IF v_status_uplata <> 'Plateno' THEN
     381    RAISE EXCEPTION 'Zapisnikot % ne moze da se zatvori bidejki uplatata e so status "%" (mora da bide Plateno)!',
     382        p_id_zapisnik, v_status_uplata;
     383END IF;
     384
     385UPDATE Zapisnik
     386SET status_zapisnik = 'Zatvoren'
     387WHERE id_na_zapisnik = p_id_zapisnik;
     388
     389RAISE NOTICE 'Zapisnik % e zatvoren po izvrshena uplata.', p_id_zapisnik;
     390END;
     391$$;
     392}}}
     393
     394Повик:
     395{{{#!sql
     396CALL plati_kazna(30000005, 'E-bankarstvo');
     397CALL zatvori_zapisnik_po_uplata(30000005);
     398}}}
     399
    342400[[BR]]
    343401== 3. Дополнителна функција ==
    344402Функција што ги обработува задоцнетите неплатени казни: на неплатените постари од 8 дена им го зголемува износот за 50% (само ако сè уште не се зголемени), а на тие постари од 2 месеци им го менува статусот во 'Sudska_postapka'. Враќа порака дека постапката е успешно извршена.
    345403
    346 Прво ја прошируваме табелата `Uplata` со новиот статус и со колона за обележување дали казната е веќе зголемена:
     404Статусот 'Sudska_postapka' и колоната `kazna_zgolemena` веќе се дел од најновата DDL (Фаза 2). Подолу се повторени `ALTER` наредбите поради идемпотентност (`IF NOT EXISTS` / `DROP ... IF EXISTS`), за функцијата да се изврши и врз постара верзија на базата:
    347405{{{#!sql
    348406ALTER TABLE Uplata DROP CONSTRAINT IF EXISTS uplata_status_check;