Se create correttamente sono un ausilio perfetto per reperire i dati in modo semplice e performante.... Sempre che si mettano in opera alcuni semplicissimi accorgimenti.
Creo un db di esempio
Use Master Go create database TestMetaData Go Use TestMetaData Go Create table TestTable1 ( T1id int ,T1campo1 varchar(25) ,T1campo2 varchar(25) ,T1campo3 varchar(25) ) Create table TestTable2 ( T2id int ,T2campo1 varchar(25) ,T2campo2 varchar(25) ,T2campo3 varchar(25) ) ;with cte as (Select 1 Riga union all Select 1) ,cte4 as (select A.Riga from cte A, Cte B) ,results as (select Row_number() Over(Order by Riga)Riga from cte4) Insert into TestTable1 Select Riga ,'Campo1 - ' + Cast(Riga as varchar(5)) ,'Campo2 - ' + Cast(Riga as varchar(5)) ,'Campo3 - ' + Cast(Riga as varchar(5)) from results ;with cte as (Select 1 Riga union all Select 1) ,cte4 as (select A.Riga from cte A, Cte B) ,results as (select Row_number() Over(Order by Riga)Riga from cte4) Insert into TestTable2 Select Riga ,'Campo1 - ' + Cast(Riga as varchar(5)) ,'Campo2 - ' + Cast(Riga as varchar(5)) ,'Campo3 - ' + Cast(Riga as varchar(5)) from results Create View TestView as Select * from dbo.TestTable1 Go
Caso 1 : La vista va in errore dopo avere modificato una tabella
Creo ora una vista denominata TestViewDropColumn che restituisce tutte le colonne e tutte le righe della tabella TestTable1
Create View TestViewDropColumn as Select * from dbo.TestTable1 Go
Come vedete l'ho creata con una Select *, mi aspetto quindi che tutte le colonne della tabella vengano restituite dalla vista, ed in effetti è così...
Cosa succede se elimino una colonna dalla tabella TestTable1 dopo aver creato la vista e faccio una query sulla vista stessa?
Alter table dbo.TestTable1 drop column T1campo3 GO Select * from TestViewDropColumn
Succede che la vista va in errore.....
Caso 2 : La vista non restituisce tutte le colonne contenute in una tabella
Creo una vista sulla tabella dbo.TestTable2
Create View TestViewAddColumn as Select * from dbo.TestTable2 Go
Anche in questo caso la vista è creata con Select *.
Aggiungo ora una colonna di tipo int e autoincrementate alla tabella dbo.TestTable2
Alter table dbo.TestTable1 add NewField int identity
Vediamo cosa succede se eseguo una select sulla vista e poi sulla tabella
In questo caso la vista non restituisce la nuova colonna mentre la seconda select, direttamente sulla tabella, funziona alla perfezione.....
Caso 3 : La vista restituisce dati incongruenti
In questo caso creo una vista contenente una join tra dbo.TestTable1 e dbo.TestTable2
Create View TestViewJoin as Select T1.*, T2.* from dbo.TestTable1 T1 inner join dbo.TestTable2 T2 on T1.T1id = T2.T2id Go
Aggiungo una nuova colonna alla tabella dbo.TestTable1
Alter table dbo.TestTable1 add ComputedColumn as (T1campo1 + T1Campo2)
Eseguo la vista
Select * from TestViewJoin
ed ecco il risultato
Come vedete la vista non da errore ma restituisce i valori in modo totalmente errato.
Questo secondo me è il caso peggiore perché rischia di compromettere in modo devastante e totalmente imprevedibile le applicazioni che fanno riferimento alla vista.
Il valore "Campo1 - 4Campo2 - 4" è il valore relativo alla colonna "ComputedColumn" aggiunta alla tabella dbo.TestTable1, non è di certo il valore della colonna T2id della tabella dbo.TestTable2.
Come facciamo a porre rimedio ai problemi ?
In modo semplice, richiamando la stored procedure di sistema sp_refreshview che aggiorna i metadati della vista specificata.
Nel mio caso devo aggiornare tutte 3 le viste create per risolvere i problemi
Exec sp_refreshview TestViewDropColumn Exec sp_refreshview TestViewAddColumn Exec sp_refreshview TestViewJoin
Se rieseguo le select dalle viste tutto funzionerà in modo corretto
Select * from TestViewDropColumn Select * from TestViewAddColumn Select * from TestViewJoin
Come vedete ora le tre viste restituiscono i risultati aspettati.
Per evitare che i casi d'esempio si verifichino abbiamo 3 strade:
1. Eseguire una ALTER VIEW a seguito di aggiornamenti delle tabelle referenziate
2. Eseguire un refresh con la sp_refreshview a seguito di aggiornamenti delle tabelle referenziate
3. Creare le viste con l'opzione SCHEMABINDING che impedisce qualunque modifica strutturale alle tabelle referenziate dalla vista.
Ciao
Luca
Nessun commento:
Posta un commento