Ein View, der mittels * alle Spalten einer verwendeten Tabelle zurückgibt, wie z.B.
CREATE VIEW dbo.testView
AS
SELECT u.*, k.name as Kunden_Name, k.AnzahlKinder
FROM umsatz u
INNER JOIN kunde k
ON k.kunde_id = u.kunde_id
verhält sich überaschend, wenn sich die Tabellenstruktur der zugrunde liegenden Tabellen ändert. Die Metainformationen aktualisieren sich nämlich nicht automatisch, was sogar zu Datentypsverletzungen führen kann.
Nehmen wir an, die Tabelle umsatz aus obigen Beispiel habe folgenden Inhalt:
Damit liefert die Abfrage des Views
SELECT * FROM testView
folgende Daten:
Wird nun in der Tabelle umsatz eine Spalte Rabatt hinzugefügt (und mit Werten gefüllt), liefert das SELECT überaschender Weise:
Dabei fällt auf, dass die Spaltentitel die ursprünglichen Inhalte haben, d.h. Rabatt ist nirgends zu sehen, die Werte der Spalten sind aber falsch: In der Spalte Kundenname steht nun der Rabatt und im Feld AnzahlKinder (Datentyp ist eigentlich int!) steht nun der Kundenname.
Das Aktualisieren der Views geht einfach: Nach
exec sp_refreshview 'testview'
sieht wieder alles richtig aus.
Hat man mehrere Views, in einer Datenbank, kann man über
sich die notwendigen SQL-Statements automatisch generieren lassen, die man dann einfach ausführt.select 'exec sp_refreshview ''' + name + '''' from sysobjects
where xtype = 'V'
Einige Hinweise:
-
Views können natürlich verschachtelt sein, d.h. ein View greift auf einen anderen View zu. Dann müssen die Refresh-View-Statements in der richtigen Reihenfolge oder einfach mehrfach ausgeführt werden.
-
Clustered / Indexed Views können nicht refresht werden – das Statement liefert einen Fehler und muss aus der Liste der auszuführenden Statements gelöscht werden. Das Aktualisieren eines indizierten Views ist aber auch unnötig, da die zugrunde liegenden Tabellen nicht geändert werden können (da der View mit Schema Binding angelegt wurde)
Im obigen Statement kann noch das Schema ergänzt werden, wenn die Views z.B. nicht unter dem Standard-Schema (dbo) angelegt wurden.
Und dann kann man auch gleich noch die Views mit SCHEMABinding ausfiltern. Dann sieht das Statement so aus:
select ‚exec sp_refreshview “‘ + s.name + ‚.‘ + o.name + ““ from sys.views o
inner join sys.schemas s on o.schema_id = s.schema_id
and not exists(
SELECT * from syscomments c
where c.id = o.object_id
and CHARINDEX(‚SCHEMABINDING‘,c.text, 1) >0 –Views mit Schemabinding kann man nicht refreshen
)