Wenn man "select *" verwendet, dann erwartet man immer alle Attribute einer Tabelle in der Ergebnismenge. Das ist für AdHoc-Abbfragen sehr praktisch, aber für den Einsatz in Programmen ungeeignet.

  • Wenn man später die Tabelle um eine weitere Spalte ergänzt, dann leifert der Befehl plötzlich eine um das Feld erweiterte Ergebnismenge, mit der die Anwendung nicht rechnet.
  • Außerdem erwartet meine Anwendung die Spalten in einer bestimmten Reihenfolge. Nach einer Datenbankänderung kann sich die Reihenfolge aber ändern.

In beiden Fällen muss ich meine Anwendung ändern und das ist sicher mehr Aufwand als die Spalten auszuformulieren, zumal das Visual-Studio for DB-Pros jetzt auch im Refactoring das "*" durch die aktuellen Spalten ersetzen kann.

In Views führt ein "select *" zu einem "eigenwilligen" Verhalten. Es werden hier nämlich nicht immer alle Attribute einer Tabelle in der Ergebnismenge angezeigt!

  • Wenn eine neue Spalte in einer Basistabelle hinzukommt, dann ändert sich die View-Definition bzw. die Struktur seiner Ergebnismenge dadurch nicht. Es werden danach weiterhin nur die "alten" Attribute angezeigt.
  • Wenn eine vorhandene Spalte geändert wird, dann ändert sich die View nicht, es werden die gleichen Spalten (inkl. Typen) zurückgeliefert, wie vor der Änderung. Die Werte werden jedoch aus dem neuen in den alten Datentyp konvertiert.
  • Wird eine vorhandene Spalte entfernt und die View enthält nun mehr Spalten als die Tabelle, dann kommt eine Fehlermeldung.
  • Wird hingegen eine neue Spalte angefügt und eine vorhandene Spalte entfernt, dann wird die View nicht compiliert und die Werte werden aus den falschen Spalten angezeigt. Die Neue wird hinten angefügt und die Fehlende einfach weggelassen.

Blöderweise wird darauf in den Books-Online nicht explizit hingewiesen. Stattdessen wird in allen Beispielen bei "CREATE VIEW" das "*" verwendet! Bei MS liest sich das so:

If a view is not created with the SCHEMABINDING clause, sp_refreshview should be run when changes are made to the objects underlying the view that affect the definition of the view. Otherwise, the view might produce unexpected results when it is queried.

Hier ein paar Samples, zum selber ausprobieren:

use tempdb
go

– Aufräumen, wenn nötig
if object_id('blabla') IS NOT NULL drop table blabla
if object_id('vlavla') IS NOT NULL drop view vlavla
go
– Testtabelle anlegen
create table blabla (id integer identity(1,1), bla varchar(200), z integer)
go
– und füllen
insert into blabla (bla, z) values ('2007-31-12 12:12', 1)
insert into blabla (bla, z) values ('2007-31-12 12:12', 2)
insert into blabla (bla, z) values ('2007-31-12 12:12', 3)
insert into blabla (bla, z) values ('2007-31-12 12:12', 4)
insert into blabla (bla, z) values ('2007-31-12 12:12', 5)
go
– View anlegen
create view vlavla
as select * from blabla
go
– So sieht das Ergebnis im Original aus
select * from vlavla
go

– Tabelle ändern: neue Spalte hinzu
ALTER TABLE blabla ADD muh datetime null
go
UPDATE blabla SET muh = getdate()
go
select * from vlavla
go

– Tabelle ändern: Datentyp ändern
ALTER TABLE blabla ALTER COLUMN bla datetime
go
select * from vlavla
go

– Tabelle ändern: Spalte entfernen (Aber es sind noch so viele Spalten in der Tabelle, wie in der View-Definition)
ALTER TABLE blabla DROP COLUMN bla
go
– So sieht in der View aus
select * from vlavla
– Und so die echte Tabelle
select * from blabla
go

– Tabelle ändern: noch eine Spalte entfernen (Nun sind weniger Spalten in der Tabelle als in der bisherigen View-Definition)
ALTER TABLE blabla DROP COLUMN muh
go
select * from vlavla
–> Jetzt kommt ein Fehler!