Ažuriranje (update) view – a

Objavljeno: 10-03-2014 | Autor: Žana (Jovana) Baćović | Kategorija: T-SQL, View-ovi

Ознаке:

0

View može da služi samo za čitanje podataka (read only view) ili da bude promjenljiv, odnosno da nad njim mogu da se pišu dml (Data Manipulation Language) naredbe update, insert i delete.

Read only view

Postoji više načina da view bude read only, navešću samo jedan pošto nisu tema ovog članka.
Read only svojstvo view-a može da se postigne i tako što se na kraju upita koji ga kreira doda union all sa uslovom koji neće biti zadovoljen.
Primjer: Nad Kefalo bazom izvršiti sledeći upit:

CREATE VIEW dbo.NadimciAutoraReadOnly (AutorID, Nadimak)
AS
SELECT AutorID, Nadimak
FROM dbo.Autori
UNION ALL
SELECT 0,''
WHERE 1=0

Ukoliko pokušate da izvršite update:

UPDATE dbo.NadimciAutoraReadOnly
SET Nadimak = 'Peyo nadimak'
WHERE AutorID = 1001;

SQL Server će prijaviti grešku da view ima izvedeno ili konstantno polje i neće izmijeniti podatke.

View nad samo jednom tabelom

Kada view sadrži podatke iz samo jedne tabele i ne sadrži agregatne funkcije (a pri tome nije read only), može da se radi ažuriranje (update) view-a.
Primjer: Ako uzmemo view iz prethodnog primjera, bez union all dijela, naredbe update, insert i delete nad njim će se izvršiti bez problema.

CREATE VIEW dbo.NadimciAutora (AutorID, Nadimak)
AS
SELECT AutorID, Nadimak
FROM dbo.Autori

Update iz prethodnog primjera, nad view-om koji nije read only će se izvršiti bez greške:

UPDATE dbo.NadimciAutora
SET Nadimak = 'Peyo nadimak'
WHERE AutorID = 1001;

Nakon update-a view-a, podaci su izmijenjeni u izvornoj tabeli, pa tako upit:

SELECT * 
FROM  dbo.Autori
WHERE AutorID = 1001;

daje sledeći rezultat:

Azuriranje view-a_1

Naredbe INSERT i DELETE će takođe biti izvršene i izazvaće izmjene u izvornoj tabeli, što možete da provjerite izvršavanjem sledeća četiri upita jedan za drugim:

INSERT INTO dbo.NadimciAutora  (AutorID, Nadimak)
VALUES
	(1020,'Test1');

SELECT * FROM 
dbo.Autori
WHERE AutorID = 1020;

DELETE FROM dbo.NadimciAutora
WHERE AutorID = 1020;

SELECT * FROM 
dbo.Autori
WHERE AutorID = 1020;

View nad dvije ili više tabela

Ukoliko view ima kolone iz više od jedne tabele, moguće je ažuriranje view-a ukoliko se u jednoj naredbi mijenjaju kolone samo iz jedne tabele.
Izmjena kolona iz različitih tabela nije moguća u jednom update upitu.
Primjer: Nad Kefalo bazom kreirati sledeći view:

CREATE VIEW dbo.AutoriCrtaca (AutorID, Ime, Prezime, Crtac)
AS
SELECT A.AutorID, A.Ime, A.Prezime, F.Naziv AS Crtac 
FROM dbo.Autori A
INNER JOIN dbo.CrtaniFilmovi_Rel_Autori R ON R.AutorID = A.AutorID 
INNER JOIN dbo.CrtaniFilmovi F ON F.CrtacID = R.CrtacID

Update koji mijenja podatke nad jednom od tabela će se izvršiti.
Primjer: Izmjena kolona Ime i Prezime iz tabele dbo.Autori, kao i izmjena kolone Crtac iz dbo.CrtaniFilmovi je moguća u dva odvojena update upita:

UPDATE dbo.AutoriCrtaca
SET Ime = 'Novo ime Pjera', Prezime = 'Novo prezime Kulifora'
WHERE AutorID = 1001;
GO
UPDATE dbo.AutoriCrtaca
SET Crtac = 'Novo ime crtaca'
WHERE AutorID = 1001;

SELECT upiti:

SELECT * 
FROM dbo.Autori
WHERE AutorID = 1001;
GO
SELECT F.CrtacID, F.Naziv, R.AutorID
FROM dbo.CrtaniFilmovi F
INNER JOIN dbo.CrtaniFilmovi_Rel_Autori R ON R.CrtacID = F.CrtacID
WHERE R.AutorID = 1001;

daju sledeće rezultate:

Select azuriranog view-a

Ukoliko pokušamo da uradimo update kolona iz dvije različite tabele, SQL server će nam javiti grešku, jer nije dozvoljena izmjena nad više osnovnih tabela istovremeno.

Primjer: Sledeći upit:

UPDATE dbo.AutoriCrtaca
SET Ime = 'Pjer', Crtac = N'Strumpfovi'
WHERE AutorID = 1001;

vraća grešku:
View or function ‘dbo.AutoriCrtaca’ is not updatable because the modification affects multiple base tables.

Instead of trigger nad view–om

Postavljanjem instead of trigger–a nad view–om, moguće je izmijeniti kolone iz dvije različite tabele. U tom slučaju, parametre update komande preuzima trigger koji sadrži logiku koja omogućava izmjenu dvije ili više tabela.
Primjer: Kreirajte sledeći trigger:

USE SQL_KEFALO
GO
CREATE TRIGGER InsOfTrUpdAutoriCrtaca 
ON dbo.AutoriCrtaca

INSTEAD OF UPDATE AS
BEGIN
IF (UPDATE(AutorID)) -- Ako se update-uje PK koji je FK drugoj tabeli
BEGIN
RAISERROR (N'Ne mozete da modifikujete PK u tabeli Autori, Transakcija je neuspjesna', 16, 1)
RETURN
END

IF (UPDATE(Ime)) -- Ako se update-uje kolona Ime
BEGIN
UPDATE dbo.Autori
SET Ime = I.Ime 
FROM inserted I 
INNER JOIN dbo.Autori A ON A.AutorID = I.AutorID 
WHERE A.AutorID = I.AutorID
END 

IF (UPDATE(Prezime)) -- Ako se update-uje kolona Prezime
BEGIN
UPDATE dbo.Autori
SET Prezime = I.Prezime 
FROM inserted I 
INNER JOIN dbo.Autori A ON A.AutorID = I.AutorID 
WHERE A.AutorID = I.AutorID
END 

IF (UPDATE(Crtac)) -- Ako se update-uje kolona Crtac
BEGIN
UPDATE dbo.CrtaniFilmovi
SET Naziv = I.Crtac 
FROM inserted I 
INNER JOIN dbo.CrtaniFilmovi_Rel_Autori R ON R.AutorID = I.AutorID
INNER JOIN dbo.CrtaniFilmovi F ON F.CrtacID = R.CrtacID
WHERE F.CrtacID = R.CrtacID
END 
END

Nakon kreiranja instead of update trigera, možemo da provjerimo njegovu funkcionalnost izvršavanjem update-a koji mijenja podatke u dvije osnovne tabele.
Primjer: Sledeći upit modifikuje sve kolone view-a:

UPDATE dbo.AutoriCrtaca
SET Ime = N'Pjer', Prezime =N'Kulifor', Crtac= N'Strumpfovi'
WHERE AutorID = 1001;

Izvršavanjem select naredbe nad osnovnim tabelama, možete da potvrdite da su podaci izmijenjeni:

SELECT * 
FROM dbo.Autori
WHERE AutorID = 1001;
GO
SELECT F.CrtacID, F.Naziv 
FROM dbo.CrtaniFilmovi F
INNER JOIN dbo.CrtaniFilmovi_Rel_Autori R ON R.CrtacID = F.CrtacID
WHERE R.AutorID = 1001;

Ovakav triger može da se koristi i za ažuriranje read only view-a.
Analogno naredbi update, odgovarajući instead of trigeri mogu da se kreiraju za naredbe insert i delete.