[ Miloš Baić @ 09.04.2007. 16:35 ] @
Pozivanje funkcije iz baze.

Za primer neka imamo tabele:

1) NASTAVNIK (ID_Nastavnik, Ime, Prezime, Zanimanje)
2) PREDMET (ID_Predmet, Naziv)
3) PREDAJE (ID_Predmet, ID_Nastavnik)

Imamo Uskladistenu funkciju:
Code:

create or replace
function povezi (ime_      in varchar2,
                 prezime_  in varchar2, 
                 naziv_  in varchar2)
  return integer as
  
  nasID   integer;
  predID  integer;

begin
 select ID_Nastavnik into nasID from NASTAVNIK
  where ime = ime_ and prezime = prezime_;
 select ID_Predmet into predID from PREDMET
  where Naziv = naziv_;
 insert into PREDAJE (ID_Predmet, ID_Nastavnik)
  values (predID, nasID);
 return 1; -- ako ima nastavnik i predmet vrsi se insert
exception
 when no_data_found then
  return 0; -- kad nema
end povezi; 

koja je školski primer, sad već se ne sećam da li je SQL Server u pitanju!?!
Nije ni bitno, pokušao sam je prebaciti u PostgreSQL, ali nisam u potpunosti uspeo.
Treba mi pomoć da je prebacim u PostgreSQL i pozovem iz Delphija?

Hvala unapred.
[ chachka @ 09.04.2007. 21:29 ] @
Ovo je prevod funkcije:
Code:

CREATE OR REPLACE FUNCTION povezi
  (ime_ VARCHAR, prezime_ VARCHAR, naziv_ VARCHAR)
RETURNS
  integer
AS
$body$
DECLARE

  nasID   integer;
  predID  integer;

begin

  select into nasID ID_Nastavnik from NASTAVNIK
   where ime = ime_ and prezime = prezime_;
  select into predID ID_Predmet from PREDMET
   where Naziv = naziv_;
   
  BEGIN
    insert into PREDAJE (ID_Predmet, ID_Nastavnik)
    values (predID, nasID);
    return 1; -- ako ima nastavnik i predmet vrsi se insert
  EXCEPTION
    WHEN not_null_violation THEN
      return 0; -- kad nema
  END;

end;
$body$
LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;

Gornja funkcija se moze napraviti i bez upotrebe EXCEPTION bloka (upotrebom IS NULL provere). Na zalost ovde moze da dodje do jos jedne greske, a to je da je nastavnik vec povezan sa predmetom. Ova greska se najlakse prevazilazi bas upotrebom EXCEPTION bloka, pa ga nema smisla izbegavati i dobijamo
Code:

CREATE OR REPLACE FUNCTION povezi
  (ime_ VARCHAR, prezime_ VARCHAR, naziv_ VARCHAR)
RETURNS
  integer
AS
$body$
DECLARE

  nasid  INTEGER;
  predid INTEGER;

BEGIN

  SELECT INTO nasid
         id_nastavnik
    FROM nastavnik
   WHERE ime = ime_
     AND prezime = prezime_;

  SELECT INTO predid
         id_predmet
    FROM predmet
   WHERE naziv = naziv_;
   
  BEGIN
    INSERT INTO predaje
           (id_predmet, id_nastavnik)
    VALUES (predid, nasid);
    RETURN 1; -- nastavnik je uspesno povezan sa predmetom
  EXCEPTION
    WHEN not_null_violation THEN
      RETURN 0; -- nije pronadjen predmet ili nastavnik
    WHEN unique_violation THEN
      RETURN 2; -- nastavnik je vec povezan sa predmetom
  END;

END;
$body$
LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;

[ Miloš Baić @ 10.04.2007. 10:45 ] @
Hvala na rešenom problemu.
Da, može doći do izuzetka kojeg si naveo, dobro si to uočio, te na taj način izmenjena funkcija je korektnija.
Samo jedna napomena, može se desiti da ćete morati pre kreiranja funkcije odraditi:
Code:
CREATE LANGUAGE plpgsql;
[ chachka @ 11.04.2007. 08:10 ] @
Sto se tice povezivanja sa Delphi-jem:
1. Postavi se neka od StoredProcedure komponenti
2. poveze se sa konekcijom ka bazi
3. postavi joj se ime procedure iz baze
4. ako treba, postave joj se ostali propertiji
5. postave joj se ulazni parametri
6. izvrsi se
7. iscitaju se izlazni parametri.