Zapis podataka u tablicu pomoću stored procedure


Ova procedura ima dvojaku ulogu, zapisuje slog ukoliko se radi o novom zapisu i radi izmjenu sloga ako se radi o postojećem zapisu.

Zadatak procedure za zapis i iumjenu u našoj tablici MP_VALUTA je

  • prihvat svih podataka potrebnih za zapis u tablicu
  • provjera postojanja primarnog ključu pomoću procedure mp_valuta_exists
  • ako je novi slog radi se INSERT, za postojeći slog se radi UPDATE
  • u pomoćnu varijablu zapisati upješnost izvršenja radnje

Evo kako bi ta procedura izgledala:


CREATE PROCEDURE dbo.mp_valuta_insert
 @valuta        CHAR(3),
 @naziv        VARCHAR(60)    = '',
 @oznaka        CHAR(3)        = '',
 @insert        TINYINT,
 @postoji    TINYINT        OUT
AS
SET NOCOUNT ON

DECLARE @ima        INT,
 @err        INT,
 @pomerr        INT

SET @err = -1

SET @pomerr = 1
EXEC @pomerr = dbo.mp_valuta_exists
 @valuta        = @valuta,
 @out_ima    = @ima        OUT
SET @err = @err + CASE @pomerr WHEN -1 THEN 0 ELSE 1 END
SET @postoji = 0

IF @ima = 0
 BEGIN
 INSERT    INTO    MP_VALUTA (
 VALUTA,
 NAZIV,
 OZNAKA)
 VALUES    (
 @valuta,
 @naziv,
 @oznaka)
 SET @err = @err + @@ERROR
 END
ELSE
 IF @insert = 0
 BEGIN
 UPDATE    MP_VALUTA
 SET    NAZIV        = @naziv,
 OZNAKA        = @oznaka
 WHERE    VALUTA        = @valuta
 SET @err = @err + @@ERROR
 END
 ELSE
 SET @postoji = 1

RETURN @err
GO

Prihvaćaju se podaci u varijable

 @valuta        CHAR(3),
 @naziv        VARCHAR(60)    = '',
 @oznaka        CHAR(3)        = '',
 @insert        TINYINT,

rade se deklaracije pomoćnih varijabli, poziva se procedura mp_valuta_exists koja vraća @ima = 1 ako postoji slog sa istom šifrom valute odnosno @ima = 0 ako šifre nema.

Ako šifre nema, radi se INSERT podataka, a ako šifra postoji radi se UPDATE ukoliko smo to željeli (@insert = 0). Ako smo željeli zapisati novi slog (@insert = 1), a šifra valute je već zapisana, output varijabla @postoji će biti postavljena na 1 i neće se izvršiti niti INSERT niti UPDATE.


  1. #1 by Gusar on 23.10.2009 - 12:20

    malo je komplicirano ovo rješenje.

    a dali je ovako ok?

    prvi query
    sad neznam kako se u sql serveru puni varijabla
    select count(*) from valuta where valuta = @valuta
    upišemo vrijednost u varijablu

    if varijabla=0 then
    insert
    else
    update
    end

  2. #2 by admin on 23.10.2009 - 12:33

    To rješenje koje navodite je za tablice koje imaju generičku šifru. Taj primjer će biti uskoro obrađen.

    U ovom slučaju, slučaju tablice MP_VALUTA koja ima određene vrijednosti, u proceduru šaljemo varijablu @insert koja ima vrijednost 1 ako želimo upisati novu valutu. Shodno tome, ako se želi upisati postojeća valuta, vrijednost varijable @postoji se stavlja na 1 i zapis neće biti napravljen.

  3. #3 by Gusar on 25.10.2009 - 22:17

    komplicira se nepotrebno
    evo recimo taj primjer na mysql, jednostavno bez puno kompliciranja.užasno komplicirate.ovako bi izgledalo i na postgresql-u i na firebirdu i na oraclu i na nekoj drugoj bazi.ovo radi bez obzira dali je polje varchar, integer , autoincrement…….

    DELIMITER $$

    CREATE

    PROCEDURE `mojabaza`.`proba`(a varchar(10),b varchar(10),c varchar(20))

    BEGIN
    declare z int DEFAULT 0;
    select count(*) into z from proba where A=b;
    if z=0 then
    insert into proba(A,B,C) values(a,b,c);
    else
    update proba set B=b,C=c where A=a;
    end if;
    END$$

    DELIMITER ;

  4. #4 by Gusar on 25.10.2009 - 22:20

    greška, ovo je ispravno, sory
    select count(*) into z from proba where A=a;

  5. #5 by admin on 26.10.2009 - 10:56

    Vaše rješenje dozvoljava da se konstantno radi zapis “novog” sloga premda takav slog već postoji. Nema povratne informacije koja je u procedurama jako bitna kao ni error handling koji je također bitan u proceurama.

  6. #6 by Gusar on 26.10.2009 - 20:55

    nije istina.
    sa count se provjeri, ako vrati 0 ide insert, ako vrati 1 ide update.

    isprobano i 100 % radi.

  7. #7 by Gusar on 26.10.2009 - 20:56

    za to ne treba error handlong, jer count vraća 0 i takav imamo uvjet.

  8. #8 by Gusar on 26.10.2009 - 20:58

    ili 1

  9. #9 by Gusar on 26.10.2009 - 20:59

    DELIMITER $$

    CREATE

    PROCEDURE `mojabaza`.`proba`(a varchar(10),b varchar(10),c varchar(20))

    BEGIN
    declare z int DEFAULT 0;
    select count(*) into z from proba where A=a; -> vraća 0 ili 1
    if z=0 then -> ako je nula ide insert
    insert into proba(A,B,C) values(a,b,c);
    else -> ako je 1 ide update
    update proba set B=b,C=c where A=a;
    end if;
    END$$

    DELIMITER ;

    i ne treba nam error handling.

    treba pametno napraviti procedure i ne bude problema.

  10. #10 by Gusar on 26.10.2009 - 21:02

    a ovako koristiti sve i svašta i pozivati jednu ili više procedura iz neke druge nije pametno.

    svaka linija sql coda troši resurse.

  11. #11 by admin on 26.10.2009 - 22:40

    Ako proceduru gledaš kao LEGO kockicu, vidjet ćeš da svaka LEGO kockica ima modus kako se spaja sa ostalim kockicama. Isto tako, rijetko koja procedura živi sama za sebe, često se poziva jedna procedura iz druge. Jedini način da se to ispravno učini je da postoji error handling.

  12. #12 by Smeđi on 09.11.2009 - 19:31

    krivo!!!
    zbog optimizacije baze nikad ne pozivati proceduru iz procedure i sve treba odraditi u jednoj proceduri.
    ako hočeš kvalitetu i brzinu od baze koristi postgresql.
    besplatan u sve svrhe.
    mana -> ne podržava clustering i replikaciju u core-u.
    ima alata za replikaciju , recimo dbreplicator radi dobro.
    također ima firebird, isto besplatan u sve svrhe.
    neke firme koriste firebird za knjigovodstvene programe.
    jednostavna baza, mala, a ima sve što ti treba od procedura nadalje.

    hočeš još bolje performance, stavi postgresql na 64 bitni linux ili freebsd pa da vidiš kako leti.

    linux -> jedno do 40 % brži od windowsa, a freebsd brži jedno 60 % od windowsa.

    jedna i druga baza imaju cdrivere za popularne jezike.
    .net, javu, perl, python, itd…

  13. #13 by admin on 10.11.2009 - 11:37

    Ne bi se složio da sve treba odraditi u jednoj proceduri. Naravno da treba pokušati napraviti sve u jednoj ali ako to proces ne dozvoljava ili se neki dio ponavlja, logično je da se neki dio izdvoji u posebnu procku i onda se po potrebi poziva.
    U bazi koristim 3000+ procedura. Neke su zanemarivo male, neke su prilično složene. Da sam išao logikom “sve u jednu proceduru”, sigurno broj ne bi bio tako velik ali bi održavanje bilo garantirano kompliciranije.
    Hvala na informacijama o bazama ali mi se čini da sam se “zahaklo” na MS SQL Server i nema mi pomoći. Dosta dugo radim s njim i nisam siguran da ću preći na neku drugu bazu. Ali,… nikad ne reci nikad.

  14. #14 by Smeđi on 10.11.2009 - 11:52

    čitam knjige od oracle stručnjaka i jedan od primjera je provjera dali nešto postoji u drugoj tablici.
    on je to odradio sve u hodu.

  15. #15 by admin on 10.11.2009 - 11:58

    To je samo primjer. Ako ikada u knjizi dođe do složenijih stvari, treba vidjeti da li će sve odraditi u hodu ili će se ipak odlučiti na grananje s dodatnom procedurom.

(will not be published)