sparksofl
1/9/2017 - 11:59 PM

oracle.sql

create or replace synonym my_books;

create or replace package main_package as
    function find_book(str varchar2) return varchar2;
    function total_books(genre_name varchar2) return number;
    procedure ban_user(u_id number);
    function genre_books(g_id number) return varchar2;
    procedure update_salary(exp number, percent number);
    procedure add_to_salary(worker_id number, new_salary number);
end main_package;

create or replace package body main_package as
    function find_book(str varchar2) return varchar2 as
        result varchar2(1024);
        cursor finded is
            select id from books where title like str;
        begin

        for book in finded loop
          result := result||book.id||', ';
        end loop;

        return result;
        end;

    function total_books(genre_name varchar2) return number
        is
            result number;
            begin
                select count(title) into result from books, books_genres, genres where genres.name=genre_name and books_genres.books_id = books.id and books_genres.genres_id = genres.id;
                return result;
            end;

    procedure ban_user(u_id number) as
        begin
            update users set banned=1 where id=u_id;
        end;

    function genre_books(g_id number) return varchar2 as
        result varchar2(1024);
        cursor c1(g_id number) is
            select title, genres.name from books, genres, books_genres where genres.id=1 and books.id=books_genres.books_id and books_genres.genres_id=genres.id;
        begin

        for book in c1(g_id) loop
          result := result||book.title||',';
        end loop;

        return result;
        end;

    procedure update_salary(exp number, percent number) as
        cursor get_workers(exp number) is
            select id from workers where exp_month > exp for update;
        begin
            for worker in get_workers(exp) loop
                update workers set salary = salary * percent where current of get_workers;
            end loop;
        commit;
        end;

    procedure add_to_salary(worker_id number, new_salary number) as
        negative_salary exception; pragma exception_init(Negative_salary, -20001);
        too_big_increase exception; pragma exception_init(Too_big_increase, -20002);
        to_big_decrease exception; pragma exception_init(To_big_decrease, -20003);
        old_salary number := 0;
        exp number := 0;

    begin
        select workers.salary into old_salary from workers where workers.id = worker_id;
        select workers.exp_month into exp from workers where workers.id = worker_id;

        if (new_salary - old_salary < 0) then Raise_application_error(-20001, 'A salary could not be negative.');
        elsif (new_salary > old_salary * 0.5) then Raise_application_error(-20002, 'The salary increase is more than 50%.');
        elsif (-new_salary > old_salary * 0.5) then Raise_application_error(-20003, 'The salary decrease is more than 50%.');
        end if;

        #update workers set workers.exp_month = 'abc'
        update workers set workers.salary = old_salary + new_salary
        where workers.id = worker_id;
        commit;

        exception
        when Negative_salary Then DBMS_OUTPUT.put_line(SQLERRM);
        when Too_big_increase Then DBMS_OUTPUT.put_line(SQLERRM);
        when To_big_decrease Then DBMS_OUTPUT.put_line(SQLERRM);
        when VALUE_ERROR then DBMS_OUTPUT.put_line(SQLERRM);

    end add_to_salary;
end main_package;

create sequence check_seq;
create sequence books_seq;

create or replace trigger copy_each_second before delete on books for each row
begin
 if (Mod(check_seq.Nextval, 2) = 0) then
   insert into journal(title, info, created_at) values(books_seq.Nextval, 'Delete', sysdate);
 end if;
end;

create or replace trigger copy_each_third before update on books for each row
begin
  if (Mod(check_seq.Nextval, 3) = 0) then
    insert into journal(title, info, created_at) values(books_seq.Nextval, 'Insert', sysdate);
  end if;
end;

create or replace trigger forbid_lending before update on users for each row
begin
  if (:old.banned = 1) then
    raise_application_error(-20000, 'This user is banned');
  end if;
end;

create or replace trigger forbid_books_title_changes before update on books for each row
begin
  if (:new.title <> :old.title) then
    raise_application_error(-20000, 'You cannot change the book title');
  end if;
end;

create or replace trigger set_minimum_salary before update on workers for each row
begin
  if (:new.salary < 50) then
    raise_application_error(-20000, 'You cannot set the salary less than 50');
  end if;
end;


CREATE trigger FOR dml_event_clause ON view
COMPOUND TRIGGER
INSTEAD OF EACH ROW IS BEGIN
  statement;
END INSTEAD OF EACH ROW;

create or replace trigger tr_turtles_ue
  for update of essence
  on turtles
  compound trigger
    bUpdPainters  boolean;
 
  before each row is
  begin
    if :new.name = 'Сплинтер' and :old.essence = 'Крыса' and :new.essence = 'Сэнсэй' then
      bUpdPainters := true;
    end if;
  end before each row;
  
  after statement is
  begin
    if bUpdPainters then
      update Turtles
         set essence = 'Ниндзя'
       where essence = 'Художник';
    end if;
  end after statement;
end tr_turtles_ue;