Weergaven (InterBase en Firebird)
Alexey Kovyazin, laatste update 13-april-2012
Degenen die bekend zijn met de SQL-taal hebben geen gedetailleerde uitleg over dit onderwerp nodig, maar om de volgorde van presentatie te behouden, introduceren we een korte definitie van views.
VIEW is een virtuele tabel die is gemaakt op basis van een query op gewone tabellen. Een view wordt geïmplementeerd als de query, opgeslagen op een server en elke keer uitgevoerd wanneer we naar een view verwijzen.
Laten we verschillende varianten van het gebruik van views bekijken. Views maken het mogelijk om niveaus van datastructuur te creëren, waardoor de implementatie van gegevensopslag kan worden gescheiden van hun type. We kunnen bijvoorbeeld een view maken die gegevens uit meerdere tabellen selecteert. Als klanten deze view gebruiken in plaats van rechtstreeks naar de onderliggende tabellen te verwijzen, kan de databaseontwikkelaar de query achter de view wijzigen, aanpassen (bijvoorbeeld optimaliseren), en de klant merkt er niets van - het blijft voor hem dezelfde view. Afgezien van het feit dat ze de implementatie van gegevensopslag isoleren van de gebruiker, maken views het mogelijk om gegevens op een handigere en eenvoudigere manier te organiseren. Het probleem van het “vereenvoudigen” van de datastructuur ontstaat wanneer het aantal tabellen in een database groot genoeg wordt en de onderlinge relaties gecompliceerd. Een view maakt het mogelijk om een deel van de gegevens te elimineren (of juist toe te voegen) die niet nodig zijn voor de specifieke databaseklant (of - wel nodig).
Bovendien maken views het mogelijk om beveiliging in een InterBase-database eenvoudiger te organiseren. Sommige gebruikers kunnen alleen rechten hebben om gegevens in de view te lezen/bij te werken, maar hebben geen rechten (en zelfs geen idee) over de tabellen die aan de view ten grondslag liggen! Voor meer details over beveiliging in InterBase, zie het hoofdstuk “Beveiliging in InterBase: gebruikers, hun functies en rechten” (deel 4).
DDL-syntax voor het werken met views
Nu zullen we de opdrachten bekijken voor het maken en verwijderen van views die zijn gedefinieerd door DDL (Data Definition Language - SQL-subset, zie de woordenlijst). Om een view in InterBase te maken, moeten we de zin met de volgende syntax gebruiken:
CREATE VIEW viewnaam [(view_kolom[, view_kolom…])] AS [WITH CHECK OPTION]; Hier is viewnaam de naam van de view die uniek moet zijn binnen een database, en daarna volgt een groep van niet altijd verplichte namen van de velden die in de view zijn opgenomen: [(view_kolom [, view_kolom …])]. Het is essentieel om de statement te definiëren die de gegevens selecteert die in de view zijn opgenomen. We zullen de optionele parameter WITH CHECK OPTION iets later bespreken in het deel “Gewijzigde views”.
Om de view te wijzigen, moeten we deze opnieuw creëren, d.w.z. verwijderen en opnieuw aanmaken. Bij het verwijderen van de view is het noodzakelijk om ook alle afhankelijke objecten te verwijderen - de triggers, opgeslagen procedures en andere views. Dit is een van de grootste nadelen van het werken met views: de noodzaak om de boom van objecten die de view gebruiken opnieuw te creëren (er zijn hulpprogramma’s die dit gemakkelijker maken, bijvoorbeeld IBAlterView, zie de applicatie “Administrator en InterBase-ontwerptools”). We moeten de volgende DDL-opdracht gebruiken als we een view willen verwijderen:
DROP VIEW viewnaam;
Voorbeelden van views
Hier is een voorbeeld van een eenvoudige view:
CREATE VIEW MyView AS SELECT NAME, PRICE_1 FROM Table_example;
In dit voorbeeld maken we een view op basis van een query op de tabel Table_example die we hebben besproken in het hoofdstuk “Tabellen. Primaire sleutels en generatoren”. In dit geval zal de view uit twee velden bestaan - NAME en PRICE_1, die zonder voorwaarden uit de tabel Table_example worden geselecteerd, d.w.z. het aantal records in de view MyView zal gelijk zijn aan het aantal records in Table_example. Views zijn echter niet altijd zo eenvoudig. Ze kunnen gebaseerd zijn op gegevens uit meerdere tabellen en zelfs op basis van andere views. Bovendien kunnen views gegevens bevatten die zijn verkregen op basis van verschillende expressies - inclusief op basis van aggregatiefuncties. Om het gebruik van deze view-toepassing in meer detail te bekijken, laten we twee tabellen maken die zijn verbonden door een één-op-veel-relatie (zo’n relatie wordt vaak master-detail genoemd). Hier is het DDL-script voor het maken van deze tabellen:
/\* Tabel: WISEMEN */
CREATE TABLE WISEMEN ( ID_WISEMAN INTEGER NOT NULL, WISEMAN_NAME VARCHAR(80));
/\* Definitie van primaire sleutels */
ALTER TABLE WISEMEN ADD CONSTRAINT PK_WISEMEN PRIMARY KEY (ID_WISEMAN);
/\* Tabel: WISEBOOK */
CREATE TABLE WISEBOOK ( ID_BOOK INTEGER NOT NULL, ID_WISEMAN INTEGER, BOOK VARCHAR(80));
/\* Definitie van primaire sleutels */
ALTER TABLE WISEBOOK ADD CONSTRAINT PK_WISEBOOK PRIMARY KEY (ID_BOOK);
/\* Definitie van externe sleutels */
ALTER TABLE WISEBOOK ADD CONSTRAINT FK_WISEBOOK FOREIGN KEY (ID_WISEMAN) REFERENCES WISEMEN (ID_WISEMAN);
We hebben dus twee tabellen gemaakt - WISEMEN en WISEBOOK, verbonden door een master-detail-relatie met behulp van een externe sleutelbeperking - FOREIGN KEY. Laten we aannemen dat deze tabellen informatie opslaan over de grote Chinese wijzen en hun werken. Nu kunnen we een paar views maken op basis van deze tabellen. Laten we bijvoorbeeld een view maken die laat zien hoeveel werken elke wijze heeft:
CREATE VIEW WiseBookCount (WISEMAN, HOW_WISEBOOKS) AS SELECT M.WISEMAN_NAME, COUNT(B.BOOK) FROM WISEMEN M, WISEBOOK B WHERE (M.ID_WISEMAN = B.ID_WISEMAN) GROUP BY M.WISEMAN_NAME
Let op dat bij het gebruik van berekende expressies zoals aggregatiefuncties COUNT (), SUM (), MAX (), enz., het essentieel is om definitieve namen van view-velden te gebruiken, d.w.z. namen te geven aan alle velden die door de query worden geretourneerd. Zoals we uit dit voorbeeld kunnen zien, hoeven deze namen niet noodzakelijk overeen te komen met de namen van de query-velden, maar hun aantal moet overeenkomen met het aantal velden dat door de query wordt geretourneerd. De definitie van welk veld dat door de query wordt geretourneerd overeenkomt met welk veld van de view wordt gemaakt op basis van een volgnummer - het eerste query-veld wordt weerspiegeld in het eerste veld van de view, het tweede in het tweede, enz.
En als we zouden willen weten welke van de wijzen de meeste boeken heeft geschreven? We zullen proberen de expressie voor sorteren - ORDER BY toe te voegen aan de query die aan de view ten grondslag ligt. Deze poging zal echter mislukken: het gebruik van sortering ORDER BY in views is niet toegestaan en bij het proberen een view te maken met een query die ORDER BY bevat, zal er een fout optreden. Als we de resultaten die door de view worden geretourneerd willen sorteren, moeten we dat namens de klant doen:
SELECT * FROM WiseBookCount ORDER BY HOW_WISEBOOKS
Het uitvoeren van deze SQL-query zal tot een gewenst resultaat leiden. Afgezien van de beperking voor het gebruik van de expressie ORDER BY in views, kunnen we ook geen gegevensset gebruiken die is verkregen als resultaat van het uitvoeren van opgeslagen procedures als gegevensbron (zie het hoofdstuk “Opgeslagen procedures” hieronder).
Misschien is het de moeite waard om nog een voorbeeld te geven dat de toepassing van views illustreert. Laten we aannemen dat we een lijst moeten uitvoeren van wijzen wiens naam begint met de letter “K”. In dit geval gebruiken we de view met voorwaarden:
CREATE VIEW WiseMen2 (WISEMAN) AS SELECT M.WISEMAN_NAME FROM WISEMEN M WHERE M.WISEMAN_NAME LIKE ‘K%’
Zo is het eenvoudig om views te maken die een rol spelen van voortdurend bijgewerkte gegevensleveranciers, die gegevens uit een database selecteren volgens bepaalde voorwaarden.
Gewijzigde views
We hebben hierboven vermeld dat er een mogelijkheid is om gewijzigde gegevensviews te maken. Het is echt zo - er is een mogelijkheid om niet alleen gegevens uit de view te lezen, maar ze ook te wijzigen!
Er zijn twee manieren om de view gewijzigd te maken. De eerste manier wordt toegepast wanneer de view is gemaakt op basis van een unieke tabel (of andere gewijzigde view), en alle kolommen van de gegeven tabel moeten de aanwezigheid van NULL toestaan. De query waarop de view is gebaseerd mag dus geen subqueries, aggregatiefuncties, UDF, opgeslagen procedures, DISTINCT en HAVING-statements bevatten. Als aan al deze voorwaarden is voldaan, wordt de view automatisch gewijzigd, d.w.z. we kunnen de queries DELETE, INSERT en UPDATE ervoor uitvoeren, die de gegevens in een brontabel zullen wijzigen.
De lijst met voorwaarden is behoorlijk indrukwekkend en beperkt de toepassing van dergelijke gewijzigde views sterk, waardoor ze vrij zelden worden gebruikt.
Om een gewijzigde view te maken die een van de bovenstaande voorwaarden schendt, wordt het mechanisme van triggers toegepast. Voor meer details over de trigger, zie het hoofdstuk “Triggers” (deel 1). Nu zullen we alleen de algemene principes van het organiseren van gegevenswijziging in VIEW bekijken.
Voor de implementatie van een bijgewerkte view met behulp van triggers moet het volgende worden gedaan. Maak 3 triggers voor de gegeven view voor gebeurtenissen: BEFORE DELETE, BEFORE UPDATE en BEFORE INSERT. Beschrijf in deze triggers wat er met de gegevens moet gebeuren bij verwijderen, bijwerken en invoegen.
Vervolgens moeten we de gegeven view gebruiken in wijzigingsqueries - DELETE, INSERT of UPDATE. Wanneer InterBase deze query ontvangt, controleert het of er geschikte triggers voor de gegeven view zijn, d.w.z. BEFORE DELETE/INSERT/UPDATE. Als de trigger voor de uitvoerbare actie bestaat, zal InterBase deze aanroepen voor het wijzigen van echte gegevens in de tabellen die aan de view ten grondslag liggen (hoewel het andere gegevens kunnen zijn - er zijn geen tekstbeperkingen voor deze triggers), en vervolgens de string (of strings) waarover de wijziging is uitgevoerd opnieuw lezen.
Er is dus een mogelijkheid om complexe ketens van gegevensupdates in views te realiseren.
Optie WITH CHECK OPTION werd genoemd in de beschrijving van de syntax voor het maken van de view. Als deze optie is ingesteld bij het maken van een gewijzigde view, wordt elke gegevensstring die in deze view wordt ingevoegd of gewijzigd gecontroleerd op een voorwaarde van het terechtkomen in de view. Het kan zo worden uitgelegd: als een nieuw record dat door de gebruiker is ingevoegd of is verkregen als resultaat van het bijwerken van het bestaande record niet voldoet aan de voorwaarden van de query, die de gegevensleverancier voor VIEW is, wordt het invoegen van dit record geannuleerd en zal er een fout optreden.
Conclusie
Ondanks de schijnbare eenvoud van het maken en gebruiken van views, bieden ze grote mogelijkheden voor het verbeteren van de gegevensorganisatie in een database en maken ze het mogelijk om een hiërarchie van gegevensorganisatie te creëren.
Sommige ontwerpers van databaseapplicaties gebruiken views zeer vaak in hun werk, anderen vermijden hun toepassing, gemotiveerd door een complexiteit van het wijzigen van views en de neiging om het databaseschema zo eenvoudig en effectief mogelijk te houden. Het is aan u hoe u views in uw werk zult toepassen. Het belangrijkste punt is om te onthouden dat er zo’n krachtig hulpmiddel bestaat als een view, en om te weten hoe u het moet gebruiken.