[ mayana @ 29.01.2009. 07:27 ] @
dobro jutro. dakle, zanima me da li u sql-u postoji neka funkcija il sta vec koja ce prebaciti odredjene podatke iz jedne tabele u drugu, ne kopirati ih nego ih prebaciti (cut)? npr, da imam tabelu racuni i tabelu arhiva placenih racuna, da kad platim neki racun, on ide u tabelu arhiva i automatski se brise iz tabele racuni. znam da mogu select into i onda delete iz prve tabele, nije problem samo pitam da li neka funkcija to radi automatski? hvala
[ .:Marvin:. @ 29.01.2009. 08:11 ] @
Ja za takvu f-ju ne znam. A i nisam siguran da je bas potrebna. Po meni, najbolje je da to resis na klijentu (aplikaciji). A ako postoji neki razlog zasto to ne moze, onda mozes da napravis trigger, tako da brise sve slogove prebacene u arhivu.
[ mayana @ 29.01.2009. 08:37 ] @
ok. samo ne znam sta je trigger i kako radi. ja cu onako kako sam rekla select into drugu tabelu i delete from prve sa where. hvala svakako
[ Fedya @ 29.01.2009. 09:04 ] @
Ako sam te razumeo trebi treba upit koji ce premestiti podatke. SQL ne sadrzi takvu funkciju, ali se to kao sto i sama rekla lako obavlja sa transakcijom koja radi INSERT INTO SELECT pa DELETE FROM. I to je preporuceni nacin kako to uraditi.


Trigger ti je 'funkcija' koja se izvrsava svaki put kada se nesto desi (insert, update, delete) sa podacima u tvojoj tabeli. U tvom slucaju mogla bi definisati trigeer nesto kao:

CREATE TRIGGER ON Arhiva FOR INSERT
AS

DECLARE @Id BIGINT
SELECT @Id = Id FROM INSERTED

IF EXISTS(SELECT * FROM Racuni WHERE Id = @Id)
BEGIN
DELETE FROM Racuni WHERE Id = @Id
END


(Kod sam pisao iz glave mozda ima gresaka, ali vidis poentu)

Znaci ovde svaki put kada nesto upises u tabelu Arhiva upit proveri da li postoji takav upit u Racuni-ma i obrise zapis ako postoji. Uzmi u obzir da ako ovo izvrsis vise neces moci da upises nesto u arhivu a da se to pri tome ne obrise iz Racuna. U svakom slucaju bolje uraditi sa INSERT+DELETE.

Ja bih tvoj problem resio tako sto bih definisao storovanu koja prima Id, i onda transakciono prebacuje podatke i brise stare.
[ mayana @ 29.01.2009. 09:26 ] @
hvala na pomoci!
[ mmix @ 29.01.2009. 09:37 ] @
Samo mala dopuna,

trigere nikad ne treba pisati kao da su za single-row insert. inserted tabela moze da ima vise od jednog reda kad se radi batch insert, tj. ne poziva se triger pojedinacno za svaki red vec jednom za sve insertovane redove
[ sparc @ 29.01.2009. 11:48 ] @

???
1. Ja sam mnogo propatio sa "more than 1 records porukom" u subquery-jima ako radim za sve insertovane redove
tako da ovde treba voditi racuna o uslovima koji se zadaju
2. Sam proces brisanja i dodavanja slogova je bitan naime treba voditi racuna o sledecem:
2.1 u insert trigeru za tabelu arhiva brises red iz redovne tabele
2.2 sta ako "pukne" zapis u tabelu arhiva, gde je slog u redovnoj tabeli
Po meni je regularnije da vrsis brisanje sloga iz redovne tabele a da trigerski upisujes slog u tabelu arhiva, ako pukne zapis u arhivi ostaje ti zbog greske neobrisan slog u redovnoj tabeli.
Ovo je prica iz iskustva, mozda nisam u pravu, .......
[ mmix @ 29.01.2009. 13:16 ] @
Pa napatio si se zbog trigera koji su formirani sa pogresnom pretpostavkom da inserted/updated tabele mogu imati samo jedan red pa se prave konstrukcije koje se svode na WHERE nesto = select drugo from inserted sto neminovno vodi ka gresci koju dobijas. Kad se prave trigeri da valjaju prave se tako da rade i u batch mode-u sto znaci da bi za ovaj primer triger trebao da bude npr ovakav (ili nesto slicno):

delete from Racuni
where Id in (Select ID from inserted)

ili

delete from Racuni
inner join inserted on inserted.Id = Racuni.Id

i sa ovakvim trigerom nikad neces dobiti "more than 1 records" gresku.


za 2.2, jasno mi je odakle dolazis (sa stanovista poslovne logike), ali ako gledamo ovo striktno sa SQL stanovista svejedno je. Kako god da obrnes morace da se desi oba, cak iako se triger poziva iz implicitne transakcije posto SQL nece okinuti AFTER trigger ako operacija koja ga izaziva ne zavrsi svoj posao. Efektivno triger radi u istoj transakciji kao operacija (sto je jedan od razloga zasto ne bi trebalo koristiti triger da rollbackujes operaciju)