Als onderdeel van de serie over tabeluitdrukkingen, ben ik vorige maand begonnen met de berichtgeving over views. Ik ben met name begonnen met het behandelen van logische aspecten van weergaven en heb hun ontwerp vergeleken met dat van afgeleide tabellen en CTE's. Deze maand ga ik verder met het behandelen van logische aspecten van weergaven, waarbij ik mijn aandacht richt op SELECT * en DDL-wijzigingen.
De code die ik in dit artikel ga gebruiken, kan in elke database worden uitgevoerd, maar in mijn demo's zal ik TSQLV5 gebruiken, dezelfde voorbeelddatabase die ik in eerdere artikelen heb gebruikt. U vindt het script dat TSQLV5 maakt en vult hier, en het ER-diagram hier.
Het gebruik van SELECT * in de innerlijke query van de weergave is een slecht idee
In het conclusiegedeelte van het artikel van vorige maand stelde ik een vraag als stof tot nadenken. Ik heb uitgelegd dat ik eerder in de serie pleitte voor het gebruik van SELECT * in de inner table-expressies die worden gebruikt met afgeleide tabellen en CTE's. Zie deel 3 in de serie voor details als je je geheugen moet opfrissen. Ik heb je toen gevraagd om na te denken of dezelfde aanbeveling nog steeds geldig zou zijn voor de innerlijke tabeluitdrukking die wordt gebruikt om weergave te definiëren. Misschien was de titel van dit gedeelte al een spoiler, maar ik zeg gelijk dat het met views eigenlijk een heel slecht idee is.
Ik zal beginnen met weergaven die niet zijn gedefinieerd met het SCHEMABINDING-attribuut, dat relevante DDL-wijzigingen in afhankelijke objecten voorkomt, en vervolgens uitleggen hoe dingen veranderen wanneer u dit attribuut wel gebruikt.
Ik zal meteen naar een voorbeeld springen, omdat dit de gemakkelijkste manier is om mijn argument te presenteren.
Gebruik de volgende code om een tabel met de naam dbo.T1 en een weergave met de naam dbo.V1 te maken op basis van een query met SELECT * voor de tabel:
GEBRUIK TSQLV5; DROP VIEW INDIEN BESTAAT dbo.V1;DROP TABLE IF BESTAAT dbo.T1;GO CREATE TABLE dbo.T1( keycol INT NOT NULL IDENTITY CONSTRAINT PK_T1 PRIMARY KEY, intcol INT NOT NULL, charcol VARCHAR (10) NOT NULL); INSERT INTO dbo.T1(intcol, charcol) WAARDEN (10, 'A'), (20, 'B');GO MAKEN OF WIJZIGEN WEERGAVE dbo.V1AS SELECT * FROM dbo.T1;GO
Merk op dat de tabel momenteel de kolommen keycol, intcol en charcol heeft.
Gebruik de volgende code om de weergave op te vragen:
SELECTEER * VANUIT dbo.V1;
U krijgt de volgende uitvoer:
keycol intcol charcol----------- ----------- ----------1 10 A2 20 B
Niets bijzonders hier.
Wanneer u een weergave maakt, legt SQL Server metagegevensinformatie vast in een aantal catalogusobjecten. Het registreert wat algemene informatie, die u kunt opvragen via sys.views, de weergavedefinitie die u kunt opvragen via sys.sql_modules, kolominformatie die u kunt opvragen via sys.columns, en meer informatie is beschikbaar via andere objecten. Wat ook relevant is voor onze discussie, is dat u met SQL Server toegangsrechten kunt beheren voor weergaven. Waar ik je voor wil waarschuwen als je SELECT * gebruikt in de innerlijke tabelexpressie van de view, is wat er kan gebeuren als DDL-wijzigingen worden toegepast op onderliggende afhankelijke objecten.
Gebruik de volgende code om een gebruiker met de naam user1 aan te maken en geef de gebruiker toestemming om de kolommen keycol en intcol uit de weergave te selecteren, maar niet charcol:
DROP GEBRUIKER INDIEN BESTAAT gebruiker1; MAAK GEBRUIKER gebruiker1 ZONDER INLOGGEN; GRANT SELECT ON dbo.V1(keycol, intcol) AAN gebruiker1;
Laten we nu enkele van de opgenomen metadata bekijken die betrekking hebben op onze mening. Gebruik de volgende code om het item terug te geven dat de weergave van sys.views vertegenwoordigt:
SELECT SCHEMA_NAME(schema_id) AS schemanaam, naam, object_id, type_descFROM sys.viewsWHERE object_id =OBJECT_ID(N'dbo.V1');
Deze code genereert de volgende uitvoer:
naam schema object_id type_desc----------- ----- ----------- ----------dbo V1 130099504 BEKIJKEN
Gebruik de volgende code om de weergavedefinitie van sys.modules te krijgen:
SELECTEER definitie FROM sys.sql_modulesWHERE object_id =OBJECT_ID(N'dbo.V1');
Een andere optie is om de functie OBJECT_DEFINITION als volgt te gebruiken:
SELECT OBJECT_DEFINITION(OBJECT_ID(N'dbo.V1'));
U krijgt de volgende uitvoer:
CREATE VIEW dbo.V1AS SELECT * FROM dbo.T1;
Gebruik de volgende code om de kolomdefinities van de weergave op te vragen uit sys.columns:
SELECT name AS column_name, column_id, TYPE_NAME(system_type_id) AS data_typeFROM sys.columnsWHERE object_id =OBJECT_ID(N'dbo.V1');
Zoals verwacht krijg je informatie over de drie kolommen keycol, intcol en charcol van de view:
column_name column_id data_type------------ ----------- ----------keycol 1 intintcol 2 intcharcol 3 varchar
Let op de kolom-ID's (ordinale posities) die bij de kolommen horen.
U kunt vergelijkbare informatie krijgen door de standaardinformatieschemaweergave INFORMATION_SCHEMA.COLUMNS op te vragen, zoals:
SELECT COLUMN_NAME, ORDINAL_POSITION, DATA_TYPEFROM INFORMATION_SCHEMA.COLUMNSWHERE TABLE_SCHEMA =N'dbo' AND TABLE_NAME =N'V1';
Om de afhankelijkheidsinformatie van de weergave te krijgen (objecten waarnaar deze verwijst), kunt u een query uitvoeren op sys.dm_sql_referenced_entities, zoals:
SELECT OBJECT_NAME(referenced_id) AS referenced_object, referenced_minor_id, COL_NAME(referenced_id, referenced_minor_id) AS column_nameFROM sys.dm_sql_referenced_entities(N'dbo.V1', N'OBJECT');
U vindt de afhankelijkheid van de tabel T1 en van de drie kolommen:
referenced_object referenced_minor_id kolomnaam------------------ ------------------- ------- ----T1 0 NULLT1 1 keycolT1 2 intcolT1 3 charcol
Zoals je waarschijnlijk wel kunt raden, is de reference_minor_id-waarde voor kolommen de kolom-ID die je eerder hebt gezien.
Als u de machtigingen van gebruiker1 tegen V1 wilt krijgen, kunt u sys.database_permissions opvragen, zoals:
SELECT OBJECT_NAME(major_id) AS referenced_object, minor_id, COL_NAME(major_id, minor_id) AS column_name, permission_nameFROM sys.database_permissionsWHERE major_id =OBJECT_ID(N'dbo.V1') EN grantee_principal_id =USER1');Deze code genereert de volgende uitvoer, waarmee wordt bevestigd dat gebruiker1 inderdaad alleen selectierechten heeft voor keycol en intcol, maar niet voor charcol:
referenced_object minor_id column_name permission_name------------------ ----------- ------------ -- --------------V1 1 keycol SELECTV1 2 intcol SELECTNogmaals, de waarde minor_id is de kolom-ID die u eerder hebt gezien. Onze gebruiker, gebruiker1, heeft rechten voor de kolommen waarvan de ID's 1 en 2 zijn.
Voer vervolgens de volgende code uit om zich voor te doen als gebruiker1 en om te proberen alle kolommen van V1 te doorzoeken:
UITVOEREN ALS GEBRUIKER =N'gebruiker1'; KIES * VANUIT dbo.V1;Zoals je zou verwachten, krijg je een toestemmingsfout vanwege het ontbreken van toestemming om charcol op te vragen:
Msg 230, Level 14, State 1, Line 141
De SELECT-machtiging is geweigerd voor de kolom 'charcol' van het object 'V1', database 'TSQLV5', schema 'dbo'.Probeer alleen keycol en intcol op te vragen:
SELECT keycol, intcol FROM dbo.V1;Deze keer wordt de query met succes uitgevoerd en wordt de volgende uitvoer gegenereerd:
keycol intcol----------- -----------1 102 20Geen verrassingen tot nu toe.
Voer de volgende code uit om terug te keren naar uw oorspronkelijke gebruiker:
TERUGKEER;Laten we nu een paar structurele wijzigingen toepassen op de onderliggende tabel dbo.T1. Voer de volgende code uit om eerst twee kolommen met de naam datecol en binarycol toe te voegen en vervolgens de kolom intcol te verwijderen:
ALTER TABLE dbo.T1 ADD datecol DATE NOT NULL DEFAULT('99991231'), binarycol VARBINARY(3) NOT NULL DEFAULT(0x112233); WIJZIG TABEL dbo.T1 DROP COLUMN intcol;SQL Server heeft de structurele wijzigingen in kolommen waarnaar wordt verwezen door de weergave niet afgewezen, omdat de weergave niet is gemaakt met het kenmerk SCHEMABINDING. Nu, voor de vangst. Op dit moment heeft SQL Server de metadata-informatie van de weergave in de verschillende catalogusobjecten nog niet vernieuwd.
Gebruik de volgende code om de weergave op te vragen, nog steeds met uw oorspronkelijke gebruiker (nog geen gebruiker1):
SELECTEER * VANUIT dbo.V1;U krijgt de volgende uitvoer:
keycol intcol charcol----------- ---------- ----------1 A 9999-12-312 B 9999-12-31Merk op dat intcol feitelijk de inhoud van charcol retourneert en charcol de inhoud van datecol retourneert. Onthoud dat er geen intcol meer in de tabel staat, maar wel datecol. Ook krijg je de nieuwe kolom binarycol niet terug.
Om erachter te komen wat er aan de hand is, gebruikt u de volgende code om de kolommetadata van de weergave op te vragen:
SELECT name AS column_name, column_id, TYPE_NAME(system_type_id) AS data_typeFROM sys.columnsWHERE object_id =OBJECT_ID(N'dbo.V1');Deze code genereert de volgende uitvoer:
column_name column_id data_type------------ ----------- ----------keycol 1 intintcol 2 intcharcol 3 varcharZoals u kunt zien, worden de metagegevens van de weergave nog steeds niet vernieuwd. Je kunt intcol zien als kolom ID 2 en charcol als kolom ID 3. In de praktijk bestaat intcol niet meer, charcol zou kolom 2 moeten zijn en datecol zou kolom 3 moeten zijn.
Laten we eens kijken of er iets is veranderd met toestemmingsinformatie:
SELECT OBJECT_NAME(major_id) AS referenced_object, minor_id, COL_NAME(major_id, minor_id) AS column_name, permission_nameFROM sys.database_permissionsWHERE major_id =OBJECT_ID(N'dbo.V1') EN grantee_principal_id =USER1');U krijgt de volgende uitvoer:
referenced_object minor_id column_name permission_name------------------ ----------- ------------ -- --------------V1 1 keycol SELECTV1 2 intcol SELECTToestemmingsinfo laat zien dat gebruiker1 toestemming heeft voor kolommen 1 en 2 in de weergave. Hoewel metadata denkt dat kolom 2 intcol wordt genoemd, wordt het in de praktijk in feite toegewezen aan charcol in T1. Dat is gevaarlijk, aangezien gebruiker1 geen toegang zou moeten hebben tot charcol. Wat als deze kolom in het echte leven gevoelige informatie bevat, zoals wachtwoorden.
Laten we ons opnieuw voordoen als gebruiker1 en alle weergavekolommen doorzoeken:
UITVOEREN ALS GEBRUIKER ='gebruiker1'; KIES * VANUIT dbo.V1;Je krijgt wel een toestemmingsfout die zegt dat je geen toegang hebt tot charcol:
Msg 230, Level 14, State 1, Line 211
De SELECT-machtiging is geweigerd voor de kolom 'charcol' van het object 'V1', database 'TSQLV5', schema 'dbo'.Kijk echter wat er gebeurt als je expliciet om keycol en intcol vraagt:
SELECT keycol, intcol FROM dbo.V1;U krijgt de volgende uitvoer:
keycol intcol----------- ----------1 A2 BDeze query slaagt, alleen retourneert het de inhoud van charcol onder intcol. Het is de bedoeling dat onze gebruiker, gebruiker1, geen toegang heeft tot deze informatie. Oeps!
Keer nu terug naar de oorspronkelijke gebruiker door de volgende code uit te voeren:
TERUGKEER;SQL-module vernieuwen
Je kunt duidelijk zien dat het gebruik van SELECT * in de innerlijke tabelexpressie van de view een slecht idee is. Maar het is niet alleen dat. Over het algemeen is het een goed idee om de metagegevens van de weergave te vernieuwen na elke DDL-wijziging in objecten en kolommen waarnaar wordt verwezen. U kunt dit doen met sp_refreshview of de meer algemene sp_refreshmodule, zoals:
EXEC sys.sp_refreshsqlmodule N'dbo.V1';Vraag de weergave opnieuw op, nu de metagegevens zijn vernieuwd:
SELECTEER * VANUIT dbo.V1;Deze keer krijg je wel de verwachte output:
keycol charcol datecol binarycol----------- ---------- ---------- ---------1 A 9999 -12-31 0x1122332 B 9999-12-31 0x112233De kolom charcol heeft de juiste naam en toont de juiste gegevens; je ziet geen intcol, en je ziet wel de nieuwe kolommen datecol en binarycol.
Vraag de kolommetadata van de weergave op:
SELECT name AS column_name, column_id, TYPE_NAME(system_type_id) AS data_typeFROM sys.columnsWHERE object_id =OBJECT_ID(N'dbo.V1');De uitvoer toont nu de juiste kolommetadata-informatie:
column_name column_id data_type------------ ----------- ----------keycol 1 intcharcol 2 varchardatecol 3 datebinarycol 4 varbinaryQuery gebruiker1's permissies tegen de weergave:
SELECT OBJECT_NAME(major_id) AS referenced_object, minor_id, COL_NAME(major_id, minor_id) AS column_name, permission_nameFROM sys.database_permissionsWHERE major_id =OBJECT_ID(N'dbo.V1') EN grantee_principal_id =USER1');U krijgt de volgende uitvoer:
referenced_object minor_id column_name permission_name------------------ ----------- ------------ -- --------------V1 1 toetscol KIESDe toestemmingsgegevens zijn nu correct. Onze gebruiker, gebruiker1, heeft alleen machtigingen om keycol te selecteren en de machtigingsinformatie voor intcol is verwijderd.
Laten we, om er zeker van te zijn dat alles goed is, dit testen door ons voor te doen als gebruiker1 en de weergave op te vragen:
UITVOEREN ALS GEBRUIKER ='gebruiker1'; KIES * VANUIT dbo.V1;U krijgt twee toestemmingsfouten vanwege het ontbreken van toestemmingen voor datecol en binarycol:
Msg 230, Level 14, State 1, Line 281
De SELECT-machtiging is geweigerd voor de kolom 'datecol' van het object 'V1', database 'TSQLV5', schema 'dbo'.Msg 230, Level 14, State 1, Line 281
De SELECT-machtiging is geweigerd voor de kolom 'binarycol' van het object 'V1', database 'TSQLV5', schema 'dbo'.Probeer keycol en intcol op te vragen:
SELECT keycol, intcol FROM dbo.V1;Deze keer zegt de fout correct dat er geen kolom is met de naam intcol:
Msg 207, Level 16, State 1, Line 279Ongeldige kolomnaam 'intcol'.
Vraag alleen intcol:
SELECT keycol FROM dbo.V1;Deze query wordt succesvol uitgevoerd en genereert de volgende uitvoer:
keycol-----------12Keer nu terug naar uw oorspronkelijke gebruiker door de volgende code uit te voeren:
TERUGKEER;Is het voldoende om SELECT * te vermijden en expliciete kolomnamen te gebruiken?
Als je een gewoonte volgt die zegt dat er geen SELECT * is in de innerlijke tabeluitdrukking van de view, zou dit dan voldoende zijn om je uit de problemen te houden? Nou, eens kijken...
Gebruik de volgende code om de tabel en weergave opnieuw te maken, maar vermeld deze keer de kolommen expliciet in de innerlijke query van de weergave:
DROP VIEW ALS BESTAAT dbo.V1;DROP TABLE IF BESTAAT dbo.T1;GO MAAK TABEL dbo.T1( keycol INT NOT NULL IDENTITY CONSTRAINT PK_T1 PRIMARY KEY, intcol INT NOT NULL, charcol VARCHAR (10) NOT NULL); INSERT INTO dbo.T1(intcol, charcol) WAARDEN (10, 'A'), (20, 'B');GO MAKEN OF WIJZIGEN dbo.V1AS SELECTEER keycol, intcol, charcol VANUIT dbo.T1;GOVraag de weergave op:
SELECTEER * VANUIT dbo.V1;U krijgt de volgende uitvoer:
keycol intcol charcol----------- ----------- ----------1 10 A2 20 BNogmaals, geef gebruiker1 toestemming om keycol en intcol te selecteren:
VERLENEN SELECTEREN OP dbo.V1(keycol, intcol) AAN gebruiker1;Pas vervolgens dezelfde structurele wijzigingen toe zoals u eerder deed:
ALTER TABLE dbo.T1 ADD datecol DATE NOT NULL DEFAULT('99991231'), binarycol VARBINARY(3) NOT NULL DEFAULT(0x112233); WIJZIG TABEL dbo.T1 DROP COLUMN intcol;Merk op dat SQL Server deze wijzigingen heeft geaccepteerd, ook al bevat de weergave een expliciete verwijzing naar intcol. Nogmaals, dat komt omdat de weergave is gemaakt zonder de optie SCHEMABINDING.
Vraag de weergave op:
SELECTEER * VANUIT dbo.V1;Op dit punt genereert SQL Server de volgende fout:
Msg 207, Level 16, State 1, Procedure V1, Line 5 [Batch Start Line 344]
Ongeldige kolomnaam 'intcol'.Msg 4413, Level 16, State 1, Line 345
Kan weergave of functie 'dbo.V1' niet gebruiken vanwege bindingsfouten.SQL Server heeft geprobeerd de intcol-referentie in de weergave op te lossen, en dat is natuurlijk niet gelukt.
Maar wat als uw oorspronkelijke plan was om intcol te laten vallen en later weer toe te voegen? Gebruik de volgende code om het weer toe te voegen en bevraag vervolgens de weergave:
WIJZIG TABEL dbo.T1 TOEVOEGEN intcol INT NIET NULL STANDAARD (0); KIES * VANUIT dbo.V1;Deze code genereert de volgende uitvoer:
keycol intcol charcol----------- ----------- ----------1 0 A2 0 BHet resultaat lijkt correct.
Hoe zit het met het opvragen van de weergave als gebruiker1? Laten we het proberen:
UITVOEREN ALS GEBRUIKER ='user1';SELECT * FROM dbo.V1;Wanneer u alle kolommen opvraagt, krijgt u de verwachte fout vanwege het ontbreken van machtigingen tegen charcol:
Msg 230, Level 14, State 1, Line 367
De SELECT-machtiging is geweigerd voor de kolom 'charcol' van het object 'V1', database 'TSQLV5', schema 'dbo'.Query keycol en intcol expliciet:
SELECT keycol, intcol FROM dbo.V1;U krijgt de volgende uitvoer:
keycol intcol----------- -----------1 02 0Het lijkt alsof alles in orde is dankzij het feit dat je SELECT * niet hebt gebruikt in de innerlijke query van de view, ook al heb je de metadata van de view niet vernieuwd. Toch kan het voor de zekerheid een goede gewoonte zijn om de metadata van de weergave te vernieuwen nadat DDL is gewijzigd in objecten en kolommen waarnaar wordt verwezen.
Keer nu terug naar uw oorspronkelijke gebruiker door de volgende code uit te voeren:
TERUGKEER;SCHEMABINDEND
Met behulp van het SCHEMABINDING view-attribuut kunt u uzelf veel van de bovengenoemde problemen besparen. Een van de sleutels om de problemen die je eerder zag te voorkomen, is om SELECT * niet te gebruiken in de innerlijke query van de weergave. Maar er is ook het probleem van structurele wijzigingen voor afhankelijke objecten, zoals het laten vallen van kolommen waarnaar wordt verwezen, die nog steeds kunnen leiden tot fouten bij het opvragen van de weergave. Als u het weergavekenmerk SCHEMABINDING gebruikt, mag u SELECT * niet gebruiken in de inner query. Bovendien weigert SQL Server pogingen om relevante DDL-wijzigingen toe te passen op afhankelijke objecten en kolommen. In relevant bedoel ik veranderingen zoals het verwijderen van een tabel of kolom waarnaar wordt verwezen. Het toevoegen van een kolom aan een tabel waarnaar wordt verwezen is uiteraard geen probleem, dus SCHEMABINDING verhindert een dergelijke wijziging niet.
Om dit te demonstreren, gebruikt u de volgende code om de tabel en weergave opnieuw te maken, met SCHEMABINDING in de weergavedefinitie:
DROP VIEW ALS BESTAAT dbo.V1;DROP TABLE IF BESTAAT dbo.T1;GO MAAK TABEL dbo.T1( keycol INT NOT NULL IDENTITY CONSTRAINT PK_T1 PRIMARY KEY, intcol INT NOT NULL, charcol VARCHAR (10) NOT NULL); INSERT INTO dbo.T1(intcol, charcol) WAARDEN (10, 'A'), (20, 'B');GO MAKEN OF WIJZIGEN dbo.V1 MET SCHEMABINDINGAS SELECTEER * VANUIT dbo.T1;GOJe krijgt een foutmelding:
Msg 1054, Level 15, State 6, Procedure V1, Line 5 [Batch Start Line 387]
Syntaxis '*' is niet toegestaan in schemagebonden objecten.Als je SCHEMABINDING gebruikt, mag je SELECT * niet gebruiken in de innerlijke tabelexpressie van de view.
Probeer de weergave opnieuw te maken, alleen deze keer met een expliciete kolomlijst:
CREER OF WIJZIG WEERGAVE dbo.V1 MET SCHEMABINDINGAS SELECTEER keycol, intcol, charcol VANUIT dbo.T1;GODeze keer is de weergave met succes gemaakt.
Verleen gebruiker1 rechten op keycol en intcol:
VERLENEN SELECTEREN OP dbo.V1(keycol, intcol) AAN gebruiker1;Probeer vervolgens structurele wijzigingen op de tabel toe te passen. Voeg eerst een aantal kolommen toe:
TABEL WIJZIGEN dbo.T1 ADD datecol DATE NOT NULL DEFAULT('99991231'), binarycol VARBINARY(3) NOT NULL DEFAULT(0x112233);Het toevoegen van kolommen is geen probleem omdat ze geen deel kunnen uitmaken van bestaande schema-gebonden weergaven, dus deze code wordt met succes voltooid.
Poging om de kolom intcol te laten vallen:
WIJZIG TABEL dbo.T1 DROP COLUMN intcol;U krijgt de volgende foutmelding:
Msg 5074, Level 16, State 1, Line 418
Het object 'V1' is afhankelijk van kolom 'intcol'.Msg 4922, Level 16, State 9, Line 418
ALTER TABLE DROP COLUMN intcol is mislukt omdat een of meer objecten toegang krijgen tot deze kolom.Het verwijderen of wijzigen van kolommen waarnaar wordt verwezen is niet toegestaan als er schemagebonden objecten bestaan.
Als u intcol nog steeds moet verwijderen, moet u eerst de schemagebonden verwijzingsweergave verwijderen, de wijziging toepassen en vervolgens de weergave opnieuw maken en de machtigingen opnieuw toewijzen, zoals:
DROP WEERGAVE INDIEN BESTAAT dbo.V1;GA WIJZIG TABEL dbo.T1 DROP COLUMN intcol;GA CREER OF WIJZIG WEERGAVE dbo.V1 MET SCHEMABINDINGAS SELECTEER keycol, charcol, datecol, binarycol VAN dbo.T1;GA GRANT SELECTEER OP dbo. V1(keycol, datecol, binarycol) NAAR gebruiker1;GOOp dit moment is het natuurlijk niet nodig om de weergavedefinitie te vernieuwen, omdat u deze opnieuw hebt gemaakt.
Nu je klaar bent met testen, voer je de volgende code uit om op te schonen:
DROP VIEW ALS BESTAAT dbo.V1;DROP TABEL IF BESTAAT dbo.T1;DROP GEBRUIKER IF BESTAAT user1;Samenvatting
Het gebruik van SELECT * in de innerlijke tabelexpressie van de view is een heel slecht idee. Nadat structurele wijzigingen zijn toegepast op objecten waarnaar wordt verwezen, kunt u onjuiste kolomnamen krijgen en zelfs gebruikers toegang geven tot gegevens waartoe ze geen toegang zouden moeten hebben. Het is een belangrijke gewoonte om de kolomnamen waarnaar wordt verwezen expliciet te vermelden.
Als u SCHEMABINDING in de weergavedefinitie gebruikt, wordt u gedwongen kolomnamen expliciet op te sommen en worden relevante structurele wijzigingen in afhankelijke objecten afgewezen door SQL Server. Daarom lijkt het misschien alsof het creëren van views met SCHEMBINDING altijd een goed idee is. Er is echter een voorbehoud bij deze optie. Zoals je hebt gezien, wordt het toepassen van structurele wijzigingen op objecten waarnaar wordt verwezen wanneer SCHEMBINDING wordt gebruikt, een langer, uitgebreider proces. Het kan vooral een probleem zijn in systemen die een zeer hoge beschikbaarheid moeten hebben. Stel u voor dat u een kolom die is gedefinieerd als VARCHAR(50) moet wijzigen in VARCHAR(60). Dat is geen toegestane wijziging als er een weergave is gedefinieerd met SCHEMABINDING die naar deze kolom verwijst. De implicaties van het laten vallen van een aantal referentieweergaven, waarnaar door andere weergaven kan worden verwezen, enzovoort, kan problematisch zijn voor het systeem. Kortom, het is niet altijd zo triviaal voor bedrijven om gewoon een beleid aan te nemen dat zegt dat SCHEMABINDING moet worden gebruikt in alle objecten die dit ondersteunen. Het aannemen van een beleid om SELECT * niet te gebruiken in de innerlijke query's van views zou echter eenvoudiger moeten zijn.
Er is nog veel meer te ontdekken met betrekking tot weergaven. Wordt volgende maand vervolgd…