{"id":718,"date":"2007-09-14T19:27:06","date_gmt":"2007-09-14T17:27:06","guid":{"rendered":"http:\/\/www.glorf.it\/blog\/2007\/09\/14\/sql-talk\/sql-server-select-in-views"},"modified":"2007-10-01T10:19:38","modified_gmt":"2007-10-01T08:19:38","slug":"sql-server-select-in-views","status":"publish","type":"post","link":"http:\/\/www.glorf.it\/blog\/2007\/09\/14\/sql-talk\/sql-server-select-in-views","title":{"rendered":"SQL-Server: select * in Views"},"content":{"rendered":"<p>Wenn man &quot;select *&quot; verwendet, dann erwartet man immer alle Attribute einer Tabelle in der Ergebnismenge. Das ist f&#252;r AdHoc-Abbfragen sehr praktisch, aber f&#252;r den Einsatz in Programmen ungeeignet.<\/p>\n<ul>\n<li>Wenn man sp&#228;ter die Tabelle um eine weitere Spalte erg&#228;nzt, dann leifert der Befehl pl&#246;tzlich eine um das Feld erweiterte Ergebnismenge, mit der die Anwendung nicht rechnet.<\/li>\n<li>Au&#223;erdem erwartet meine Anwendung die Spalten in einer bestimmten Reihenfolge. Nach einer Datenbank&#228;nderung kann sich die Reihenfolge aber &#228;ndern.<\/li>\n<\/ul>\n<p>In beiden F&#228;llen muss ich meine Anwendung &#228;ndern und das ist sicher mehr Aufwand als die Spalten auszuformulieren, zumal das Visual-Studio for DB-Pros jetzt auch im Refactoring das &quot;*&quot; durch die aktuellen Spalten ersetzen kann.<\/p>\n<p>In <strong>Views<\/strong> f&#252;hrt ein &quot;select *&quot; zu einem &quot;eigenwilligen&quot; Verhalten. Es werden hier n&#228;mlich nicht immer alle Attribute einer Tabelle in der Ergebnismenge angezeigt!<\/p>\n<ul>\n<li>Wenn eine neue Spalte in einer Basistabelle hinzukommt, dann &#228;ndert sich die View-Definition bzw. die Struktur seiner Ergebnismenge dadurch nicht. Es werden danach weiterhin nur die &quot;alten&quot; Attribute angezeigt. <\/li>\n<li>Wenn eine vorhandene Spalte ge&#228;ndert wird, dann &#228;ndert sich die View nicht, es werden die gleichen Spalten (inkl. Typen) zur&#252;ckgeliefert, wie vor der &#196;nderung. Die Werte werden jedoch aus dem neuen in den alten Datentyp konvertiert.<\/li>\n<li>Wird eine vorhandene Spalte entfernt und die View enth&#228;lt nun mehr Spalten als die Tabelle, dann kommt eine Fehlermeldung.<\/li>\n<li>Wird hingegen eine neue Spalte angef&#252;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&#252;gt und die Fehlende einfach weggelassen.<\/li>\n<\/ul>\n<p>Bl&#246;derweise wird darauf in den Books-Online nicht explizit hingewiesen. Stattdessen wird in allen Beispielen bei &quot;CREATE VIEW&quot; das &quot;*&quot; verwendet! Bei MS liest sich das so:<\/p>\n<blockquote><p>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.<\/p><\/blockquote>\n<p>Hier ein paar Samples, zum selber ausprobieren:<\/p>\n<p><code lang=\"sql\">use tempdb<br \/>\ngo<\/p>\n<p>&#8211; Aufr&#228;umen, wenn n&#246;tig<br \/>\nif object_id(&#x0027;blabla&#x0027;) IS NOT NULL drop table blabla<br \/>\nif object_id(&#x0027;vlavla&#x0027;) IS NOT NULL drop view vlavla<br \/>\ngo<br \/>\n&#8211; Testtabelle anlegen<br \/>\ncreate table blabla (id integer identity(1,1), bla varchar(200), z integer)<br \/>\ngo<br \/>\n&#8211; und f&#252;llen<br \/>\ninsert into blabla (bla, z) values (&#x0027;2007-31-12 12:12&#x0027;, 1)<br \/>\ninsert into blabla (bla, z) values (&#x0027;2007-31-12 12:12&#x0027;, 2)<br \/>\ninsert into blabla (bla, z) values (&#x0027;2007-31-12 12:12&#x0027;, 3)<br \/>\ninsert into blabla (bla, z) values (&#x0027;2007-31-12 12:12&#x0027;, 4)<br \/>\ninsert into blabla (bla, z) values (&#x0027;2007-31-12 12:12&#x0027;, 5)<br \/>\ngo<br \/>\n&#8211; View anlegen<br \/>\ncreate view vlavla<br \/>\nas select * from blabla<br \/>\ngo<br \/>\n&#8211; So sieht das Ergebnis im Original aus<br \/>\nselect * from vlavla<br \/>\ngo<\/p>\n<p>&#8211; Tabelle &#228;ndern: neue Spalte hinzu<br \/>\nALTER TABLE blabla ADD muh datetime null<br \/>\ngo<br \/>\nUPDATE blabla SET muh = getdate()<br \/>\ngo<br \/>\nselect * from vlavla<br \/>\ngo<\/p>\n<p>&#8211; Tabelle &#228;ndern: Datentyp &#228;ndern<br \/>\nALTER TABLE blabla ALTER COLUMN bla datetime<br \/>\ngo<br \/>\nselect * from vlavla<br \/>\ngo<\/p>\n<p>&#8211; Tabelle &#228;ndern: Spalte entfernen (Aber es sind noch so viele Spalten in der Tabelle, wie in der View-Definition)<br \/>\nALTER TABLE blabla DROP COLUMN bla<br \/>\ngo<br \/>\n&#8211; So sieht in der View aus<br \/>\nselect * from vlavla<br \/>\n&#8211; Und so die echte Tabelle<br \/>\nselect * from blabla<br \/>\ngo<\/p>\n<p>&#8211; Tabelle &#228;ndern: noch eine Spalte entfernen (Nun sind weniger Spalten in der Tabelle als in der bisherigen View-Definition)<br \/>\nALTER TABLE blabla DROP COLUMN muh<br \/>\ngo<br \/>\nselect * from vlavla<br \/>\n&#8211;> Jetzt kommt ein Fehler!<\/code><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wenn man &quot;select *&quot; verwendet, dann erwartet man immer alle Attribute einer Tabelle in der Ergebnismenge. Das ist f&#252;r AdHoc-Abbfragen sehr praktisch, aber f&#252;r den Einsatz in Programmen ungeeignet. Wenn man sp&#228;ter die Tabelle um eine weitere Spalte erg&#228;nzt, dann leifert der Befehl pl&#246;tzlich eine um das Feld erweiterte Ergebnismenge, mit der die Anwendung nicht [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[16,3],"tags":[],"_links":{"self":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts\/718"}],"collection":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/comments?post=718"}],"version-history":[{"count":0,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts\/718\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/media?parent=718"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/categories?post=718"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/tags?post=718"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}