Changes between Initial Version and Version 1 of DatabaseProgramming


Ignore:
Timestamp:
05/29/26 18:49:26 (3 weeks ago)
Author:
231101
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • DatabaseProgramming

    v1 v1  
     1=Функции, процедури и тригери
     2
     3Во овој дел се прикажани SQL функциите, процедурите и тригер-функциите кои се користат во системот за управување со библиотека.
     4Тие ја имплементираат главната бизнис логика на апликацијата, како што се позајмување книги, враќање книги, регистрација на членови, резервација на книги, автоматска проверка на членство и автоматско креирање казна при задоцнето враќање.
     5
     6
     7
     8== 1. Функции ==
     9
     10=== 1.1 borrow_book ===
     11
     12{{{#!sql
     13CREATE OR REPLACE FUNCTION public.borrow_book(
     14p_borrowing_id bigint,
     15p_member_id bigint,
     16p_copy_id bigint,
     17p_employee_id bigint
     18)
     19RETURNS text
     20LANGUAGE plpgsql
     21AS $function$
     22DECLARE
     23v_available INTEGER;
     24v_membership_status VARCHAR;
     25BEGIN
     26
     27```
     28-- Проверка дали книгата е достапна
     29SELECT available
     30INTO v_available
     31FROM bookcopy
     32WHERE copy_id = p_copy_id;
     33
     34IF v_available = 0 THEN
     35    RETURN 'Book copy is not available';
     36END IF;
     37
     38-- Проверка дали членот е активен
     39SELECT membership_status
     40INTO v_membership_status
     41FROM member
     42WHERE member_id = p_member_id;
     43
     44IF v_membership_status != 'ACTIVE' THEN
     45    RETURN 'Member is not active';
     46END IF;
     47
     48-- Креирање borrowing
     49INSERT INTO borrowing(
     50    borrowing_id,
     51    book_id,
     52    borrow_date,
     53    due_date,
     54    copy_id,
     55    membership_id,
     56    borrowed_by
     57)
     58VALUES(
     59    p_borrowing_id,
     60    (SELECT book_id
     61     FROM bookcopy
     62     WHERE copy_id = p_copy_id),
     63    CURRENT_DATE,
     64    CURRENT_DATE + INTERVAL '14 days',
     65    p_copy_id,
     66    p_member_id,
     67    p_employee_id
     68);
     69
     70-- Update availability
     71UPDATE bookcopy
     72SET available = 0
     73WHERE copy_id = p_copy_id;
     74
     75RETURN 'Book borrowed successfully';
     76```
     77
     78END;
     79$function$;
     80}}}
     81
     82'''Опис:'''
     83Функцијата `borrow_book` се користи за позајмување конкретна копија од книга.
     84Најпрво проверува дали копијата е достапна, а потоа проверува дали членот има активен статус.
     85Ако условите се исполнети, се внесува нов запис во табелата `borrowing` и копијата се означува како недостапна.
     86
     87'''Употреба:'''
     88Оваа функција ја имплементира главната логика за позајмување книга во библиотеката.
     89Се користи за да се спречи позајмување на недостапна книга или позајмување од член кој нема активен статус.
     90Со тоа се обезбедува контрола врз процесот на позајмување и ажурирање на достапноста на книгите.
     91
     92
     93
     94=== 1.2 register_member ===
     95
     96{{{#!sql
     97CREATE OR REPLACE FUNCTION public.register_member(
     98p_member_id bigint,
     99p_first_name character varying,
     100p_last_name character varying,
     101p_email character varying,
     102p_phone character varying,
     103p_address text
     104)
     105RETURNS text
     106LANGUAGE plpgsql
     107AS $function$
     108DECLARE
     109v_existing_email INTEGER;
     110v_existing_member INTEGER;
     111BEGIN
     112
     113```
     114-- check for existing member
     115SELECT COUNT(*)
     116INTO v_existing_member
     117FROM member
     118WHERE member_id = p_member_id;
     119
     120IF v_existing_member > 0 THEN
     121    RETURN 'Member is already registered';
     122END IF;
     123
     124-- check for existing email
     125SELECT COUNT(*)
     126INTO v_existing_email
     127FROM member
     128WHERE email = p_email;
     129
     130IF v_existing_email > 0 THEN
     131    RETURN 'Email already exists';
     132END IF;
     133
     134-- create new member
     135INSERT INTO member(
     136    member_id,
     137    first_name,
     138    last_name,
     139    email,
     140    phone,
     141    address,
     142    membership_status,
     143    membership_start_date,
     144    membership_end_date
     145)
     146VALUES(
     147    p_member_id,
     148    p_first_name,
     149    p_last_name,
     150    p_email,
     151    p_phone,
     152    p_address,
     153    'ACTIVE',
     154    CURRENT_DATE,
     155    CURRENT_DATE + INTERVAL '1 year'
     156);
     157
     158RETURN 'Member registered successfully';
     159```
     160
     161END;
     162$function$;
     163}}}
     164
     165'''Опис:'''
     166Функцијата `register_member` се користи за регистрација на нов член во библиотеката.
     167Најпрво проверува дали веќе постои член со истиот `member_id`, а потоа проверува дали внесениот email веќе се користи.
     168Ако членот и email адресата не постојат, се креира нов член со статус `ACTIVE` и членство со важност од една година.
     169
     170'''Употреба:'''
     171Оваа функција ја имплементира логиката за регистрација на корисници во библиотечниот систем.
     172Се користи за да се спречи дуплирање на членови и користење на иста email адреса од повеќе корисници.
     173На овој начин системот обезбедува правилна евиденција на членовите.
     174
     175
     176
     177=== 1.3 return_book ===
     178
     179{{{#!sql
     180CREATE OR REPLACE FUNCTION public.return_book(p_borrowing_id bigint)
     181RETURNS text
     182LANGUAGE plpgsql
     183AS $function$
     184DECLARE
     185v_due_date DATE;
     186v_copy_id BIGINT;
     187v_return_date DATE;
     188v_late_days INTEGER;
     189v_status_id INTEGER;
     190BEGIN
     191
     192```
     193-- take info from borrowing
     194SELECT due_date, copy_id, return_date
     195INTO v_due_date, v_copy_id, v_return_date
     196FROM borrowing
     197WHERE borrowing_id = p_borrowing_id;
     198
     199-- check for existing borrow
     200IF v_copy_id IS NULL THEN
     201    RETURN 'Borrowing record not found';
     202END IF;
     203
     204-- check if book is returned
     205IF v_return_date IS NOT NULL THEN
     206    RETURN 'Book already returned';
     207END IF;
     208
     209-- Update return date
     210UPDATE borrowing
     211SET return_date = CURRENT_DATE
     212WHERE borrowing_id = p_borrowing_id;
     213
     214-- bookstatus
     215SELECT status_id
     216INTO v_status_id
     217FROM bookcopy
     218WHERE copy_id = v_copy_id;
     219
     220-- check for dameged book
     221IF v_status_id = 5 THEN
     222    UPDATE bookcopy
     223    SET available = 0
     224    WHERE copy_id = v_copy_id;
     225
     226    RETURN 'Book returned with damage';
     227END IF;
     228
     229-- book is available
     230UPDATE bookcopy
     231SET available = 1,
     232    status_id = 1
     233WHERE copy_id = v_copy_id;
     234
     235-- check for late retun
     236IF v_due_date IS NOT NULL THEN
     237    v_late_days := CURRENT_DATE - v_due_date;
     238
     239    IF v_late_days > 0 THEN
     240        RETURN 'Book returned late by ' || v_late_days || ' days';
     241    END IF;
     242END IF;
     243
     244RETURN 'Book returned successfully';
     245```
     246
     247END;
     248$function$;
     249}}}
     250
     251'''Опис:'''
     252Функцијата `return_book` се користи при враќање на позајмена книга.
     253Таа проверува дали постои запис за позајмување, дали книгата веќе е вратена и потоа го ажурира датумот на враќање.
     254Дополнително, проверува дали книгата е оштетена и дали е вратена со задоцнување.
     255
     256'''Употреба:'''
     257Оваа функција ја имплементира логиката за враќање книги во библиотеката.
     258Ако книгата е вратена во добра состојба, копијата повторно се означува како достапна.
     259Ако книгата е оштетена, таа останува недостапна, а ако е вратена по рокот, системот враќа информација за бројот на денови на доцнење.
     260
     261'''Забелешка:'''
     262Во оваа функција оштетена книга се проверува со `status_id = 5`.
     263Ако во базата оштетените книги се означуваат со друга вредност, на пример `status_id = 2`, тогаш условот треба да се усогласи со вистинската вредност во табелата `bookcopy`.
     264
     265
     266
     267== 2. Процедури ==
     268
     269=== 2.1 sp_borrow_book ===
     270
     271{{{#!sql
     272CREATE OR REPLACE PROCEDURE public.sp_borrow_book(
     273IN p_book_id integer,
     274IN p_membership_id integer,
     275IN p_due_date date,
     276IN p_borrowed_by integer
     277)
     278LANGUAGE plpgsql
     279AS $procedure$
     280DECLARE
     281v_copy_id INT;
     282BEGIN
     283
     284```
     285-- free copy
     286SELECT copy_id
     287INTO v_copy_id
     288FROM bookcopy
     289WHERE book_id = p_book_id
     290  AND available = 1
     291LIMIT 1;
     292
     293-- doesnt have-error
     294IF v_copy_id IS NULL THEN
     295    RAISE EXCEPTION 'No available copy for this book!';
     296END IF;
     297
     298-- borrowing row
     299INSERT INTO borrowing(
     300    book_id,
     301    borrow_date,
     302    return_date,
     303    due_date,
     304    return_status,
     305    copy_id,
     306    membership_id,
     307    borrowed_by,
     308    returned_by,
     309    reservation_id
     310)
     311VALUES (
     312    p_book_id,
     313    CURRENT_DATE,
     314    null,
     315    p_due_date,
     316    NULL,
     317    v_copy_id,
     318    p_membership_id,
     319    p_borrowed_by,
     320    NULL,
     321    NULL
     322);
     323
     324-- not available
     325UPDATE bookcopy
     326SET available = 0
     327WHERE copy_id = v_copy_id;
     328```
     329
     330END;
     331$procedure$;
     332}}}
     333
     334'''Опис:'''
     335Процедурата `sp_borrow_book` се користи за позајмување книга според `book_id`.
     336Таа најпрво бара слободна копија од дадената книга во табелата `bookcopy`.
     337Ако нема достапна копија, се јавува грешка, а ако има, се креира запис во `borrowing` и копијата се означува како недостапна.
     338
     339'''Употреба:'''
     340Оваа процедура ја имплементира логиката за автоматско избирање достапна копија при позајмување книга.
     341Корисникот или библиотекарот не мора рачно да избира конкретен `copy_id`, туку системот сам ја наоѓа првата достапна копија.
     342Ова ја поедноставува работата на библиотекарот и го намалува ризикот од грешки.
     343
     344
     345
     346=== 2.2 sp_reserve_book ===
     347
     348{{{#!sql
     349CREATE OR REPLACE PROCEDURE public.sp_reserve_book(
     350IN p_member_id integer,
     351IN p_book_id integer
     352)
     353LANGUAGE plpgsql
     354AS $procedure$
     355DECLARE
     356v_copy_id INT;
     357BEGIN
     358
     359```
     360-- check for free copy
     361SELECT copy_id
     362INTO v_copy_id
     363FROM bookcopy
     364WHERE book_id = p_book_id
     365  AND available = 1
     366LIMIT 1;
     367
     368--if doesnt have copy, make reservation
     369IF v_copy_id IS NULL THEN
     370
     371    INSERT INTO reservation(
     372        member_id,
     373        book_id,
     374        requested_date,
     375        expected_date,
     376        status,
     377        copy_id
     378    )
     379    VALUES (
     380        p_member_id,
     381        p_book_id,
     382        CURRENT_DATE,
     383        CURRENT_DATE + 7,
     384        'waiting',
     385        NULL
     386    );
     387
     388ELSE
     389
     390    RAISE NOTICE 'Book is available. No reservation needed.';
     391
     392END IF;
     393```
     394
     395END;
     396$procedure$;
     397}}}
     398
     399'''Опис:'''
     400Процедурата `sp_reserve_book` се користи за резервација на книга.
     401Најпрво проверува дали постои достапна копија од книгата.
     402Ако нема достапна копија, се креира запис во табелата `reservation` со статус `waiting`.
     403
     404'''Употреба:'''
     405Оваа процедура ја имплементира логиката за резервација на книги кои моментално не се достапни.
     406Ако книгата има слободна копија, резервација не е потребна и системот прикажува известување.
     407Ако книгата нема слободна копија, членот се става на листа на чекање.
     408
     409
     410
     411== 3. Trigger функции ==
     412
     413=== 3.1 fn_create_fine_on_return ===
     414
     415{{{#!sql
     416CREATE OR REPLACE FUNCTION public.fn_create_fine_on_return()
     417RETURNS trigger
     418LANGUAGE plpgsql
     419AS $function$
     420DECLARE
     421days_late INT;
     422total_amount INT;
     423fine_per_day INT := 10;
     424BEGIN
     425
     426```
     427IF NEW.return_date IS NOT NULL
     428   AND NEW.return_date > NEW.due_date THEN
     429
     430    days_late := NEW.return_date - NEW.due_date;
     431    total_amount := days_late * fine_per_day;
     432
     433    INSERT INTO fine(
     434        fine_id,
     435        membership_id,
     436        borrowing_id,
     437        amount,
     438        created_date,
     439        payment_id,
     440        fee_type_id
     441    )
     442    VALUES (
     443        (SELECT COALESCE(MAX(fine_id),0)+1 FROM fine),
     444        NEW.membership_id,
     445        NEW.borrowing_id,
     446        total_amount,
     447        CURRENT_DATE,
     448        NULL,
     449        1
     450    );
     451
     452END IF;
     453
     454RETURN NEW;
     455```
     456
     457END;
     458$function$;
     459}}}
     460
     461'''Опис:'''
     462Trigger функцијата `fn_create_fine_on_return` служи за автоматско креирање казна при задоцнето враќање на книга.
     463Таа проверува дали `return_date` е поголем од `due_date`.
     464Ако книгата е вратена по рокот, се пресметува бројот на задоцнети денови и се внесува нов запис во табелата `fine`.
     465
     466'''Употреба:'''
     467Оваа trigger функција ја имплементира логиката за автоматска наплата на казни.
     468Се користи за да не мора библиотекарот рачно да пресметува казна при секое задоцнето враќање.
     469Висината на казната се пресметува според бројот на задоцнети денови, при што во функцијата е поставена вредност од 10 по ден.
     470
     471
     472
     473=== 3.2 check_membership_status ===
     474
     475{{{#!sql
     476CREATE OR REPLACE FUNCTION public.check_membership_status()
     477RETURNS trigger
     478LANGUAGE plpgsql
     479AS $function$
     480BEGIN
     481
     482```
     483--if membership is expiredd
     484IF NEW.membership_end_date < CURRENT_DATE THEN
     485    NEW.membership_status := 'EXPIRED';
     486
     487--if doesn't
     488ELSE
     489    NEW.membership_status := 'ACTIVE';
     490END IF;
     491
     492RETURN NEW;
     493```
     494
     495END;
     496$function$;
     497}}}
     498
     499'''Опис:'''
     500Trigger функцијата `check_membership_status` се користи за автоматска проверка на статусот на членството.
     501Ако датумот `membership_end_date` е помал од тековниот датум, статусот на членот се поставува на `EXPIRED`.
     502Во спротивно, статусот се поставува на `ACTIVE`.
     503
     504'''Употреба:'''
     505Оваа trigger функција ја имплементира логиката за автоматско ажурирање на статусот на членството.
     506Се користи за системот сам да одреди дали членот има активно или истечено членство.
     507На овој начин се избегнува рачно ажурирање на статусот на членовите.
     508
     509
     510
     511
     512