Sparse columns in SQL server 2008
Sparse columns in SQL server 2008 Object persistentie eenvoudig gemaakt
Bert Dingemans, e-mail :
[email protected] www : http://www.dla-os.nl
1
www.dla-os.nl
Sparse columns in SQL server 2008
Content SPARSE COLUMNS IN SQL SERVER 2008 ......................................................................... 1 OBJECT PERSISTENTIE EENVOUDIG GEMAAKT.............................................................................1 CONTENT ...............................................................................................................2 INLEIDING ...............................................................................................................3 SPARSE COLUMNS........................................................................................................3 STORED PROCEDURES....................................................................................................5 SAMENVATTING..........................................................................................................6 OVER DE AUTEUR........................................................................................................6
2
www.dla-os.nl
Sparse columns in SQL server 2008
Inleiding Bij het toepassen van object oriëntatie in een ontwikkeltraject waarbij de domeinobjecten als klasse geïmplementeerd worden speelt een probleem van object relationele mappings. Met name het ophalen en wegschrijven van gegevens is lastig omdat er steeds een vertaalslag gemaakt moet worden van de representatie in de database naar de representatie in de applicatie. Het wordt nog lastiger op het moment dat men overerving gaat toepassen in de klasse structuur. Een voorbeeld van het probleem wordt gegeven in onderstaande afbeelding. Persoon Voornaam Achternaam
Medewerker Beroep Maandsal
Klant Klantpas Krediet
Probleem wat hier ontstaat is dat men bij het vertalen naar een tabel in een relationele database altijd zes kolommen nodig heeft terwijl er altijd maar vier ingevuld worden. Onderstaande tabel geeft een strokendiagram dat dit weergeeft. Object 1 2
Voornaam Jan Piet
Achternaam Jansen Van Dijk
Beroep Ontwikkelaar
Maandsal. 3500
Klantpas
Krediet
400120
1200
Bij het opslaan van de gegevens in de database zullen kolommen gedefinieerd moeten worden zonder dat zij ooit gevuld worden. Bijkomend probleem is dat bij een kleine wijziging in het object model dit doorgevoerd moet worden in het relationele model in de database. Een soortgelijk probleem doet zich voor bij de implementatie van condities in werkprocessen. Het implementeren van vertakkingen kent een soortgelijk patroon Sinds SQL server 2008 is het mogelijk om sparse columns te definiëren. In dit artikel ga ik in op de mogelijkheden van deze functionaliteit voor object mappings. Stapsgewijs geef ik uitbreidingen aan op de werkwijze in de vorm van SQL statements, te beginnen bij inserts en updates en eindigend bij stored procedures die in één enkele stap een lijst van object definities implementeren. Waar nodig wordt de resultaat set getoond bij een opdracht.
Sparse columns Sparse columns worden gedefinieerd voor gegevens in de database die niet altijd ingevuld worden (bijvoorbeeld voor de vertakkingen zoals hierboven beschreven). In onderstaand commando ziet u hoe een tabel met sparse columns gedefinieerd en een tweetal statements CREATE TABLE [dbo].[Person]( [Id] [int] IDENTITY(1,1) NOT NULL, [status] [varchar](50) NOT NULL, [Name] [varchar](100) SPARSE NULL, [Birthdate] [date] SPARSE NULL, [Address] [varchar](50) SPARSE NULL, [Place] [varchar](20) SPARSE NULL, ) ON [PRIMARY]
3
www.dla-os.nl
Sparse columns in SQL server 2008
GO UPDATE Person SET Birthdate = GETDATE()-(45*365) WHERE Id = 1; SELECT * FROM Person; In het Create table statement worden de sparse columns gewoon gedefinieerd als de andere kolommen met een toevoeging van het trefwoord sparse. Daarnaast moet de kolom gedefinieerd worden als NULL wat logisch is omdat de gegevens gebaseerd zijn op een vertakking. Vervolgens kunnen de gegevens in de sparse columns gewoon gewijzigd en opgevraagd worden met de standaard SQL commando’s. Dat laatste is bijzonder want fysiek worden de gegevens van de sparse columns helemaal niet in kolommen opgeslagen maar in een kolom van het type XML. Dit maken we zichtbaar met de volgende twee commando’s. CREATE TABLE [dbo].[Person]( [Id] [int] IDENTITY(1,1) NOT NULL, [status] [varchar](50) NOT NULL, [Name] [varchar](100) SPARSE NULL, [Birthdate] [date] SPARSE NULL, [Address] [varchar](50) SPARSE NULL, [Place] [varchar](20) SPARSE NULL, [AllXML] [xml] COLUMN_SET FOR ALL_SPARSE_COLUMNS NULL ) ON [PRIMARY]; GO SELECT * FROM Person GO Verrassend is nu dat de resultaatset er als volgt uitziet: Id 1
Status Person_aanmaken
2
Person_aanmaken
3
Person_aanmaken
allxml
Bert Dingemans1962-0921Johanna Naberstraat 48Culemborg Anneke Hubert1965-1015Johanna Naberstraat 48Culemborg Jeroen Dingemans1995-0831Johanna Naberstraat 48Culemborg
Het blijkt dat nu bij een * wildcard niet meer de sparse columns getoond worden maar alleen de fysieke kolommen. Verder is te zien hoe de sparse columns in een XML kolom worden opgeslagen als een XML string. Wel is het mogelijk om de sparse columns te muteren en of op te vragen door ze op te nemen in de specificatie, zoals hieronder: UPDATE Person SET allxml = '
Bert Dingemans1962-0921Wildforster 37Ede' WHERE Id = 1 GO SELECT Name, Address, Place, Birthdate FROM Person WHERE year(birthdate) < 1965 Name Bert Dingemans
Address Wildforster 37
Place Ede
4
Birthdate 1962-09-21
www.dla-os.nl
Sparse columns in SQL server 2008
Het voorbeeld toont dat het mogelijk is om met een update statement de XML kolom te muteren en vervolgens met de sparse columns de gegevens op te vragen en omgekeerd. Dit biedt hele interessante mogelijkheden voor object persistentie en het werken met stored procedures zoals u zult zien in de volgende paragraaf.
Stored procedures Stored procedures in sql server hebben onder andere als voordeel dat zij meerdere opdrachten tegelijkertijd op de database kunnen uitvoeren. Met name in onze situatie is dat wenselijk. In het voorbeeldscript zijn een aantal voorbeeld stored procedures opgenomen. In dit artikel lichten we er twee uit die laten zien dat SQL server 2008 extra functionaliteiten bieden. In de eerste stored procedure wordt als parameter een XML string gebruikt om de nieuwe waarden van een rij te bewerken. CREATE PROCEDURE [dbo].[Person_bewerken_XML]( @p_xml xml, @Id Int ) AS BEGIN --exec Person_bewerken @xml = '#allxml', @Id=#id# UPDATE [Person] SET [allxml] = @p_xml , STATUS = 'Person_bewerken_xml' WHERE id = @id END GO De opzet is eenvoudig en bestaat uit een enkel statement dat de update uitvoert op basis van de primaire sleutel in de tabel, de status is een extra kolom die aangeeft welke methode als laatste is uitgevoerd op het object. Dit gegevens is relevant in onze situatie van object persistentie. Voordeel van het werken met een XML string in plaats van met de afzonderlijke sparse columns is dat we ongestraft in onze applicatie elementen aan ons object model kunnen toevoegen of muteren zonder dat dit gevolgen heeft voor de werking van onze stored procedure. Ook als we de gegevens willen opvragen voor het vullen van ons object model in de toepassing kunnen we dat opnieuw doen op basis van de XML kolom. Alleen bij rapportages en het bevragen van ons model voor specifieke objecten maken we gebruik van de sparse columns in de select of where component van een statement. Nadeel van deze opzet is dat je nog steeds per object naar de database moet om een bewerking uit te voeren op de tabellen in de database. Sinds SQL Server 2008 is dat niet meer het geval, het is nu namelijk mogelijk om met parameter tables te werken. Dat is een soort van parameter collection die je als read only waarde kunt meegeven aan de stored procedure. Hiertoe dient een type gedefinieerd te worden en deze wordt voor de aanroep van de stored procedure gevuld te worden met de gewenste waarden. In het code voorbeeld zie je de definitie en vervolgens één stored procedure aanroep die drie rijen wijzigt in de tabel. CREATE TYPE dla_parametertable AS TABLE (id int , p_xml xml , p_status varchar(50) ); GO CREATE PROCEDURE [dbo].[Person_aanmaken_valuepara]( @p_xml dla_parametertable readonly ) AS BEGIN DELETE FROM [Person];
5
www.dla-os.nl
Sparse columns in SQL server 2008
INSERT INTO [Person] ( [allxml], status ) SELECT p_xml, p_status FROM @p_xml END GO declare @table dla_parametertable; insert into @table values (1, '
Bert Dingemans 1962-09-21 Rhodosdreef 154 Utrecht', 'Person_aanmaken_para') , (2, '
Anneke Hubert 1965-10-15 Rhodosdreef 154 Utrecht', 'Person_aanmaken_para') , (3, '
Jeroen Dingemans 1995-08-31 Rhodosdreef 154 Utrecht', 'Person_aanmaken_para'); exec dbo.person_aanmaken_valuepara @table; Het voordeel van deze werkwijze zal duidelijk zijn, aan de client side van de toepassing wordt dit statement opgebouwd en vervolgens is er slechts één aanroep naar de database die vervolgens een refresh uitvoert op de objecten die meegegeven worden aan de stored procedure aanroep. Uitbreidingen van de werkwijze zijn natuurlijk denkbaar zoals het daadwerkelijk bijwerken van rijen in plaats van een delete en insert. Voorbeelden hiervan zijn te vinden op mijn website waar ik werk aan een Object Relational Mapper in Vulcan.Net.
Samenvatting Met de komst van SQL server 2008 worden een aantal nieuwe concepten geïntroduceerd die het mogelijk maken om op eenvoudige wijze Object Relational Mappers te introduceren. Met name sparse columns, XML columns en parameter tables worden in dit artikel uitgewerkt en toegelicht. Bij dit artikel is een voorbeeldscript opgenomen waarin extra voorbeelden zijn opgenomen en de source code als compleet script is uitgewerkt.
Over de auteur Bert is als software architect werkzaam binnen het maatschap FreeIT, een maatschap van ICT professionals. In die rol voert hij freelance opdrachten uit bij diverse organisaties. Bert heeft een voorliefde voor Model Driven Development en het genereren van software. Zo heeft hij CASE tools ontwikkeld in Visual Objects als DLArchitect en DLA Work in Process. Bert heeft een weblog op www.dla-os.nl.
6
www.dla-os.nl