Alle SQL PASSler aus Sachsen (und die, die es werden möchten) sind zum Jubiläumstreffen 5 Jahre PASS Deutschland der Regionalgruppe Sachsen am Montag, den 25.01.2010 um 18:30 Uhr einladen.
Der PASS Deutschland e.V. wurde am 31.08.2004 gegründet und feierte deshalb im August/September 2009 in allen Regionen das fünfjährige Bestehen. Zu diesem Jubiläum wurden in allen Regionen Treffen der Regionalgruppen mit besonderen Inhalt veranstaltet. Für die Regionalgruppe Sachsen war folgender Vortrag anberaumt:
SQL Server 2008 R2: Neues vom SQL Server; Georg Urban, Microsoft
Self Service Analysis mit Excel In-Memory Online Analytic Processing & Self Service Reporting mit Report Builder 3.0 sind wichtige Themen – aber es gibt noch mehr zu berichten.
Da Georg Urban zu dem ersten Versuch im September kurzfristig krank geworden war, hat er sich für den 25. Januar bereit erklärt, die Session nachzuholen. Es darf gehofft werden, dass er nun auch die neueste CTP vom November hat und die Teilnehmenden so in den Genuss von „Hot News“ kommen!
Die PASS Regionalgruppe Dresden trifft sich an gewohnter Stelle im IT-Trainingshaus am Waldschlösschen. Nähere Informationen zum Termin und eine Anfahrtsbeschreibung findet man auf der Website der Regionalgruppe.
Am 07.09.2009 fand in Dresden die bereits im Vorfeld hier erwähnte Jubiläumsveranstaltung der SQL Pass Group statt. Thema sollte die bevorstehende Release 2 von SQL Server 2008 (Codename Madison) mit ihren Möglichkeiten zu Self Service BI, SQL Server Data Warehouse Scale Out und weiteren Neuheiten sein.
Leider musste Sprecher Georg Urban wegen Krankheit kurzfristig absagen, weshalb die Veranstaltung wohl hätte ins Wasser fallen müssen, wenn PASS-Organisator Ralf Dietrich nicht einen vollwertigen Ersatz “besorgt” hätte: Andreas Wolter informierte über Reporting Services 2008 Berichtsdesign Features.
Berichte auf Basis der Reporting Services 2008 sehen auf den ersten Blick mit RS 2005 fast identisch aus. Unter der Haube aber ergeben sich ganz neue Möglichkeiten. Andreas Wolter stellte neue bzw. verbesserte Features wie Tablix, Charts und Gauges (KPI) mit möglichen Anwendungsszenarien vor. Zum Schluss gab es mit dem aktuellen Report Builder 3.0 CTP doch noch einen Vorab-Blick auf Release 2, dort stachen insbesondere die wirklich gut integrierten Bing Maps sehr positiv hevor.
Am Ende waren sich alle darin einig, dass es ein äußerst informativer Vortrag (dafür ein Dankeschön an Andreas) zu einem interessanten Thema und deutlich mehr als ein “Lückenbüßer” (und dafür noch eines an Ralf, der dies noch so kurzfristig “heranorganisierte”) war!
Am 20.11.2009 ist das nächste Treffen der PASS Regionalgruppe Sachsen angesetzt, Thema wird SQL Server Sizing mit einer kurzen Einführung und anschließender Diskussion/ Erfahrungsaustausch sein. Der am Montag ausgefallende Vortrag von Georg Urban soll nicht aufgehoben, sondern nur aufgeschoben sein: geplant ist Januar 2010, der konkrete Termin wird dann rechtzeitig auf der Webseite der Regionalgruppe Sachsen bekannt gegeben.
Das nächste SQL Pass Treffen der Regionalgruppe Sachsen
findet bereits am 07.09.2009 18:30 wie gewohnt im IT Trainingshaus
(mittlerweile in den neuen Räumlichkeiten im 4. Obergeschoss) statt.
Es gibt eine Jubiläumsveranstaltung anlässlich des 5-jährigen Bestehens von PASS Deutschland e.V. und einen Vortrag zum Thema “SQL Server 2008 R2: Self Service BI, SQL Server Data Warehouse Scale Out und weitere Neuheiten”.
Anmelden kann man sich wie immer mit einer kurzen Mail an Ralf Dietrich (rdi@sqlpass.de) oder an Ulrich Walter (uwa@sqlpass.de). Weitere Informationen gibt es auf der Homepage der Regionalgruppe Sachsen.
|
|
Communardo ist Partner der SQLdays, die von 29.-30. September 2009 in Rosenheim stattfinden. Sichern Sie sich am besten noch heute Ihre Teilnahme und sparen Sie so mit Promocode „SQL-Com89“ mindestens 100,- EUR auf den Konferenzpreis (bis 31. August 2009)! |
.
Seien auch Sie 2009 bei den SQLdays mit dabei – wenn es heißt „Von Profis für Profis“. So erfahren Sie im Detail, was der innovative Datenbank Server von Microsoft zu bieten hat, welche Trends aktuell sind und von welchen Tipps & Tricks Sie persönlich profitieren.
Und das sind die Highlights der SQLdays 2009:
Aktuelle Infos zu den SQLdays, zu allen Sessions, allen Sprechern, den Workshops und Anmeldung unter www.SQLdays.net.
Genau wie der Datentyp HierarchyId, so sind auch die neuen räumlichen Datentypen geometry und geography CLR-Datentypen, die in jeder Datenbank verfügbar sind – unabhängig davon, ob CLR-Funktionen aktiviert sind.
Der geometry-Datentyp erlaubt die Darstellung von Daten im kartesischen Koordinatensystem und die Durchführung von Berechnungen mit diesen Daten.
Das möchte ich an einem Beispiel verdeutlichen:

In diesem Koordinatensystem befinden sich 2 geometrische Figuren. Ein Strahl mit den Endpunkten (0; 0), (100; 200) und ein Quadrat mit den Eckpunkten (-40; -40), (100; -40), (100; 100), und (-40, 100).
Die Deklaration einer Tabelle zur Speicherung der Daten ist recht trivial. Hierzu erzeugt man einfach eine Tabellenspalte vom Typ Geometry in die man die Daten schreibt.
Ich möchte hier allerdings auf die Möglichkeiten des Datentyps eingehen. Daher werden in den folgenden Beispielen nur Variablen dieses Datentyps erzeugt. Mit Hilfe der statischen Methode STGeomFromText kann aus einem normalsprachlichen Text (dem sogenannten “Well Known Text” = WKT) eine geometrische Instanz erzeugt werden. Im Beispiel ist das:
| DECLARE @line geometry; SET @line = geometry ::STGeomFromText(‘LINESTRING (0 0, 100 200)’,0) DECLARE @rectangle geometry; SET @rectangle = geometry ::STGeomFromText(‘POLYGON ((-40 -40, 100 -40, 100 100, -40 100, -40 -40))’,0) |
Wie man sieht, wird hier die Art der geometrischen Figur angegeben und Punkte, die die Figur näher beschreiben. Das Quadrat ist verallgemeinert ein Polygon, daher ist der WKT hier POLYGON. Zu beachten ist bei Polygonen, dass Start- und Endpunkt übereinstimmen müssen.
Soweit ganz gut. Das Erzeugen und Speichern von Daten an sich ist recht langweilig. Was können die Methoden, die geometry zur Verfügung stellt?
STAsText: STAsText gibt den WKT für ein geometry-Objekt zurück.
STArea: Diese Funktion berechnet die Oberfläche von geometrischen Objekten. Im Fall der Linie ist die Oberfläche 0, aber das ist ehrlich gesagt auch nicht verwunderlich. Im Fall des Quadrats hat die Methode korrekt 140 * 140 = 19600 zurückgegeben.
STIntersection: Mit STIntersection wird die Überschneidung zweier Objekte berechnet. Das Ergebnis der Berechnung im Beispiel ist eine Linie mit den Endpunkten (0; 0) und (50; 100) – und genau das kann man auch sehr schön im Diagramm ablesen.
STLength: Ein letztes Beispiel an dieser Stelle soll STLength sein. Wie der Name schon vermuten lässt, kann damit die Länge bzw. der Umfang der Objekte berechnet werden.
Die Anwendungsfälle dafür können sehr vielfältig sein. Beispielsweise könnte hier die Entfernung zwischen Gebäuden oder Objekten berechnet werden.
Die Berechnung von Entfernungen mit STLength oder Flächen mit STArea auf geraden Flächen ist nur dann sinnvoll, wenn es sich um kurze Distanzen handelt. Möchte man Entfernungen in der realen Welt berechnen, ist der geometry-Datentyp aufgrund der Krümmung der Erde nicht mehr geeignet. Der geography-Datentyp schafft hier Abhilfe:
Wie schon vom Geometry-Datentyp bekannt, kann ein Objekt mittels der statischen Methode STGeomFromText erzeugt werden. Allerdings spielt hier die dort recht unwichtige SRID hier eine wesentliche Rolle. Sie definiert, anhand welchen Standards Berechnungen durchgeführt werden. In der MSDN findet man zum Thema folgendes:
geometry Instances Default to Zero SRID
The default SRID for geometry instances in SQL Server is 0. With geometry spatial data, the specific SRID of the spatial instance is not required to perform calculations; thus, instances can reside in undefined planar space. To indicate undefined planar space in the calculations of geometry data type methods, the SQL Server Database Engine uses SRID 0.
geography Instances Must Use Supported SRID
SQL Server supports SRIDs based on the EPSG standards. A SQL Server-supported SRID for geography instances must be used when performing calculations or using methods with geography spatial data. The SRID must match one of the SRIDs displayed in the sys.spatial_reference_systems catalog view. As mentioned previously, when you perform calculations on your spatial data using the geography data type, your results will depend on which ellipsoid was used in the creation of your data, as each ellipsoid is assigned a specific spatial reference identifier (SRID).
SQL Server uses the default SRID of 4326, which maps to the WGS 84 spatial reference system, when using methods on geography instances. If you use data from a spatial reference system other than WGS 84 (or SRID 4326), you will need to determine the specific SRID for your geography spatial data.
Im Gegensatz zu Geometry muss für die Initialisierung der Geography-Objekte also zwingend eine SRID angegeben werden. Der Standard ist aktuell 4362. Eine Übersicht der gültigen SRIDs erhält man, wenn man die Systemsicht sys.spatial_reference_systems aufruft:

Es gibt noch eine weitere Einschränkung: Geography-Instanzen dürfen die Hemisphäre nicht überschreiten. Diese Einschränkung spielt natürlich erst dann eine Rolle, wenn man nicht mehr nur geographische Punkte speichert, sondern Berechnungen durchführen möchte und z.B. Entfernungen berechnet. Eine in meinen Augen gute Erklärung für diese Einschränkung liefert ein Blogeintrag von Steve Kass zum Thema. Darin wird auch gut beschrieben, weshalb die Punkte von Polygonen immer entgegen des Uhrzeigersinns angegeben werden müssen.
Möchte man hierarchische Daten ablegen – wie z.B. Organisationsstrukturen in Unternehmen, so war das Standard-Vorgehen dazu bisher, 2 Felder zu verwenden – zunächst die Id des eigentlichen Elements und in einem weiteren Feld die Id des Elternknotens.

Damit lassen sich Abfragen wie: “Wer ist direkter Vorgesetzter des Mitarbeiters X?” oder “Welche Mitarbeiter sind direkt dem Vorgesetzten Y unterstellt?” recht einfach beantworten. Umfangreichere Aussagen wie: “Was sind alle direkten und indirekten Mitarbeiter des Managers X?” oder “Wer ist Ebene-3-Manager des Mitarbeiters Y?” sind damit schon schwieriger zu ermitteln.
Nun kommt der HierarchyId-Datentyp ins Spiel. Mit ihm können solche Zusammenhänge dargestellt und einfach abgefragt werden. Als Besonderheit gilt es zu beachten, dass dieser Datentyp als CLR-Datentyp implementiert ist, der allerdings auch dann zur Verfügung steht, wenn CLR-Integration deaktiviert ist. Daraus resultierend leitet sich auch die Darstellung der Funktionen ab. Dazu aber später mehr. Zunächst möchte ich die oben gezeigte Struktur mit diesem Datentyp aufbauen. Dazu erstelle ich eine neue Tabelle.

Im nächsten Schritt wird diese mit Daten gefüllt.

Lässt man sich nun die Daten einmal anzeigen, ergibt sich folgendes Bild:

Man erkennt, dass die Daten vorliegen – allerdings ist OrgNode eine hexadezimale Darstellung, die nicht ganz so benutzerfreundlich ist. Dafür gibt es Abhilfe, denn die Methode ToString gibt die kanonische Darstellung des OrgNodes zurück:

Nun erkennt man die hierarchischen Beziehungen schon besser.
Um die Vorteile auch komplett ausnutzen zu können, sollte man einen Blick auf die Methoden des HierarchyId-Datentyps werfen:
Spalten des Datentyps HierarchyId achten nicht selbst auf die Eindeutigkeit. Aus diesem Grund ist es sinnvoll, einen eindeutigen Index auf die Spalte zu legen. Je nach Anwendungsfall unterscheidet man hier Depth-First-Index und Breadth-First-Index. Beim Depth-First-Index wird zuerst in die Tiefe gegangen – also zuerst alle Kindelemente des Knotens 1 indiziert, bevor zu Knoten 2 übergegangen wird. Beim Breadth-First-Index wird Ebene für Ebene indiziert.
Das Anlegen eines Depth-First-Index ist recht trivial – dazu indiziert man einfach eine bestehende HierarchyId-Spalte.
![]()
Für die Anlage eines Breadth-First-Indexes benötigt man noch eine zusätzliche Spalte in der Tabelle, in der der Level persistiert und die dann in den Index mit einbezogen wird.

Große BLOBs (Videos, Word-Dokumente etc.) konnte man in MS SQL Server bisher entweder in der Datenbank (langsam) oder im Filesystem (unsicher, keine Transaktionen) ablegen. FILESTREAM Storage vereint die Vorteile von beiden.
Das Konzept von FILESTREAM integriert das SQL ServerDatenbankmodul in ein NTFS-Dateisystem: BLOB-Daten vom Typ varbinary(max) werden im Dateisystem gespeichert. Dadurch greift nicht die für varbinary(max) definierte Größenbeschränkung auf 2 GB, sondern die Größe der Dateien ist lediglich durch den verfügbaren Speicherplatz auf dem Laufwerk begrenzt. Ansonsten können FILESTREAM-Daten ganz normal mit Transact-SQL-Anweisungen abgefragt, eingefügt, geändert oder gelöscht werden – das alles natürlich wie gehabt incl. Transaktionen und Datenbanksicherheit (mittels Berechtigungen auf Tabellen- oder Spaltenebene – nur das SQL Server Dienstkonto erhält Zugriff auf die Daten im Dateisystem). Desweiteren können alle Verwaltungsfunktionen genutzt werden, z.B. zum Sichern und Wiederherstellen.
Und wie geht das?
Zuerst muss FILESTREAM Storage aktiviert werden.
Dies kann man entweder bereits bei der Installation von SQL Server 2008 erledigt haben:

… oder man muss es nachträglich im SQL Server Configuration Manager tun:

Dann kann eine FILESTREAM-aktivierte Datenbank erstellt werden:
CREATE DATABASE Test
ON
PRIMARY ( NAME = test1,
FILENAME = ‘c:\data\testdat1.mdf’),
FILEGROUP FileStreamGroup1 CONTAINS FILESTREAM( NAME = test3,
FILENAME = ‘c:\data\filestream1′)
LOG ON ( NAME = testlog1,
FILENAME = ‘c:\data\testlog1.ldf’)
GO
Wenn FILESTREAM nachträglich für eine bereits vorhandene Datenbank aktiviert werden soll, müssen folgende Abfragen ausgeführt werden:
ALTER DATABASE Test ADD
FILEGROUP FileStreamGroup1 CONTAINS FILESTREAM;
GO
ALTER DATABASE Test ADD FILE (
NAME = FSGroup1File,
FILENAME = ‘c:\data\filestream1′)
TO FILEGROUP FileStreamGroup1;
GO
Achtung!
Das Verzeichnis “filestream1″ darf noch nicht vorhanden sein, es wird automatisch angelegt und ist erst einmal leer bis auf die Datei filestream.hdr und den Ordner $FSLOG.
Zu guter Letzt muss eine Tabelle zum Speichern von FILESTREAM-Daten erstellt werden:
CREATE TABLE Test.dbo.Documents (
DocumentID INT IDENTITY PRIMARY KEY,
Document VARBINARY (MAX) FILESTREAM NULL,
DocumentGuid UNIQUEIDENTIFIER NOT NULL ROWGUIDCOL UNIQUE)
FILESTREAM_ON FileStreamGroup1;
GO
Eine Spalte mit FILESTREAM-Daten ist eine varbinary(max)-Spalte mit FILESTREAM-Attribut. Eine ROWGUIDCOL-Spalte ist nur für die Verwendung von FILESTREAM-Daten mit Win32-APIs erforderlich.
Nun können nach Belieben mit Transact SQL Daten eingefügt, abgefragt etc. werden:
INSERT INTO Test.dbo.Documents
VALUES (1, newid (), CAST (‘Das ist ein Test’ as varbinary(max)));
GO
UPDATE Test.dbo.Documents
SET Document = CAST (‘Das ist noch ein Test’ as varbinary(max)))
WHERE DocumentID = 1;
GO
DELETE Test.dbo.Documents WHERE DocumentID = 1;
GO
Anmerkung:
Das Ändern großer Datenmengen ist mit Transact SQL zwar möglich, aber nicht empfehlenswert. Zum Schreiben großer Datenmengen verwendet man besser die Win32-API (aber das ist eine andere Geschichte, die soll ein andermal erzählt werden…)
Zum Abschluss noch einige Überlegungen zum Einsatz von FILESTREAM:
Um gleich mal zu Beginn übertriebene Erwartungen zu dämpfen (und eventuellen Normalform-Fetischisten den Wind aus den Segeln zu nehmen): in 99% aller Fälle sind Sparse Columns NICHT unbedingt erforderlich.
SQL Server 2008 kann jetzt bis zu 16.384 Spalten in einer Tabelle speichern (zum Vergleich: bisher waren maximal 1024 Spalten in einer Tabelle möglich). Nun fragt man sich angesichts solcher Größenordnungen schon: “Wann, um alles in der Welt, benötige ich in einer relationalen Datenbank eine solche Menge an Spalten?”
Hier mal ein Beispiel-Szenario: Wir designen gerade eine Tabelle für Getränke und haben jede Menge an Attributen zu speichern, die nur bei einzelnen Getränke-Kategorien zutreffen: bei alkoholischen Getränken im Allgemeinen den Alkoholgehalt, bei Wein im Speziellen die Farbe, den Süßegrad, die Rebsorte, das Anbaugebiet, … (Weinkennern fällt bestimmt noch einiges ein), bei Saft die Obstsorte und den Fruchtgehalt, bei Milch den Fettgehalt und ob Frisch- oder H-Milch etc. pp.
Nun wird der eingefleischte Datenbank-Designer feststellen, dass man das alles mit Hilfe von separaten Tabellen für jede Getränkekategorie und 1:1-Verknüpfungen doch hübsch sauber in einer relationalen Struktur abbilden kann, ohne eine Unmenge an Spalten zu benötigen. Sicher – kann man. Aber Hand aufs Herz: manchmal schießt man damit einfach über das Ziel hinaus und erschwert sich unnötig das Leben durch die daraus resultierenden komplexen Abfragen.
Und hier setzen nun Sparse Columns (“spärlich belegte Spalten”) an: In SQL Server 2008 kann man Spalten mit dem Attribut SPARSE versehen, dann verbrauchen sie, wenn sie leer bleiben, auch keinen Platz.
Ob man die so erlaubten 16.384 Spalten tatsächlich einmal erreicht, sei dahingestellt – dieses Konzept lohnt sich aus Sicht der Speicherplatzersparnis auch mit wenigen Spalten, wenn man in einer Tabelle viele Zeilen hat, für die bestimmte Spalten sehr selten belegt sind.
… oder wie bei Microsoft das Basteln abgeschafft wurde
Wer schon einmal vor dem Problem stand, an eine SQL Server Prozedur oder Funktion eine Liste von Werten oder gar eine Tabelle zu übergeben, der wird für dieses Problem bestimmt eine Lösung gefunden haben: Ob man nun die Werte mit einem geeigneten Trennzeichen versehen (ich bevorzuge Pipes
) alle in eine varchar(max)-Variable packt und mittels einer benutzerdefinierten Funktion wieder “auseinanderschnipselt” oder gleich den XML-Datentyp verwendet - es gibt die verschiedensten Bastellösungsansätze, dieser Problematik Herr zu werden.
SQL Server 2008 offeriert mit Table Valued Parameters diese Funktionalität nun gänzlich ohne Bastelei. Die Technik dafür ist denkbar simpel:
Es wird angenommen, dass eine Tabelle Employees mit folgender Struktur existiert:

Nun muss man


Fertig ![]()
Für alle, die es gerne schnell mal ausprobieren möchten, hier nochmal zum Kopieren:
CREATE TABLE Employees(
EmployeeID int NOT NULL,
LastName nvarchar(50) NOT NULL,
FirstName nvarchar(50) NOT NULL)
go
CREATE TYPE T_Employees AS TABLE (EmployeeID int, LastName nvarchar(50), FirstName nvarchar(50))
go
CREATE PROCEDURE P_InsertEmployees
@employees T_Employees READONLY
AS
INSERT INTO Employees (EmployeeID, LastName, FirstName)
SELECT EmployeeID, LastName, FirstName
FROM @employees
go
DECLARE @emps T_Employees
INSERT INTO @emps (EmployeeID, LastName, FirstName) VALUES (1, ‘Davolio’, ‘Nancy’)
INSERT INTO @emps (EmployeeID, LastName, FirstName) VALUES (2, ‘Fuller’, ‘Andrew’)
EXEC P_InsertEmployees @emps
Hier noch ein paar Dinge, die zu beachten bzw. wissenswert sind:
Und zum Abschluss noch ein kleiner Leckerbissen für ADO.Net Programmierer: TVP werden auch hier vollständig unterstützt, ein Beispiel für den Aufruf der oben erstellte Prozedur in C# könnte so aussehen:
SqlConnection sqlConn…
DataTable dt = new DataTable();
dt.Columns.Add….
dt.Rows.Add…..
SqlCommand cmd = new SqlCommand(“P_InsertEmployees”, sqlConn);
cmd.Parameters.AddWithValue(“@employees”, dt);
cmd.ExecuteNonQuery();
Wer sich schon immer mal darüber geärgert hat, dass mehrere SQL-Anweisungen nötig waren, um in einer Tabelle, abhängig von den Bedingungen in einer anderen Tabelle, Daten einzufügen, zu ändern und/oder zu löschen, der wird über die neue MERGE-Anweisung in SQL Server 2008 hocherfreut sein – … vorausgesetzt, er kann sich für komplexe SQL-Anweisungen begeistern
.
Das absolute Standard-Szenario für die Anwendung von MERGE ist die Aktualisierung von Daten in einem Data Warehouse auf Basis der Daten aus dem Produktivsystem: Im Data Warehouse sollen
Dafür waren bisher 3 Anweisungen der folgenden Art nötig (je eine für INSERT, UPDATE und DELETE):
Mit dem MERGE-Befehl nun ist das alles in einer Anweisung unterzubringen:
Das kommt nicht nur deutlich eleganter daher, sondern ist auch ressourcensparend, da nur eine anstelle mehrerer Lookup-Operationen durchgeführt wird.
Wichtig: Die MERGE-Anweisung muss immer mit einem Semikolon abgeschlossen werden.
Natürlich ist die MERGE-Anweisung noch deutlich flexibler als hier abgebildete Variante, z.B. kann die USING-Klausel auch eine Unterabfrage (dann mit einem Alias) enthalten oder die MATCHED-Klausel beliebig mit weiteren logischen Ausrücken kombiniert werden, des Weiteren sind beliebig viele MATCHED-Klauseln von jeder Art möglich. Ein etwas komplexeres Beispiel könnte z.B. so aussehen:
Ausführliche Syntaxinformationen finden sich unter http://msdn.microsoft.com/de-de/library/bb510625.aspx.