Bücher für Anfänger in T-SQL gibt es mittlerweile viele. Darunter sind sowohl gute als auch weniger gute. Die Wahl des "richtigen" Buches ist naturgemäss nicht einfach und schnell kann es passieren, dass der Leser durch das für ihn falsche Buch das Interesse an SQL Server's SQL-Dialekt verliert. Aus diesem Grund halte ich es sogar für schwieriger ein Buch für Anfänger zu schreiben als eines für "Experten". Denn: Wie vermittelt man eine Programmiersprache die weitgehend auf anderen Paradigmen basiert als "klassische" Programmiersprachen? Mit einer klaren Struktur und einer verständlichen Wortwahl, die sich nicht in technischen Fachbegriffen verliert. Mit vielen Beispielen, die sich leicht nachvollziehen lassen und Übungen, mit denen sich jederzeit der individuelle Lernstand überprüfen lässt.
Es ist keine grosse Neuigkeit, dass an immer mehr Stellen immer mehr Daten gesammelt werden und dementsprechend auch die dahinterliegenden Datenbanken immer grösser und komplexer werden. Gleichzeitig ist es auch keine Neuigkeit, dass diese Daten mehr oder weniger gut geschützt sind. Immer wieder berichtet die Presse über spektakuläre Datendiebstähle und eklatante Sicherheitslücken.
Eine dieser berühmt-berüchtigten "Kleinigkeiten", über die ich mir bisher wenig Gedanken gemacht habe, ist die Sichtbarkeit von Metadaten innerhalb einer SQL Server Datenbank. Sie waren bisher einfach immer und überall verfügbar, sprich abfragbar. Bis jetzt, als wir dann eine Applikation troubleshooten mussten, die Datenmodifikationen nicht mehr korrekt trackte. Man stelle sich einmal folgendes Szenario vor:
In diesem Beitrag haben wir uns mit der Rückgabe von Werten einer Spalte als separierte Liste beschäftigt. Vielfach sieht man aber auch die Anforderung, diese Liste auf der Basis eines bestimmten Schlüsselwertes zu generieren.
Startup Prozeduren werden beim Start von SQL Server ausgeführt. Typische Verwendungszwecke sind zum Beispiel:
Um eine Prozedur als Startup Procedure festzulegen, muß man die Systemprozedur sp_procoption ausführen. Nähere Erläuterungen zur Verwendung dieser Prozedur stehen in BOL.
Startup Prozeduren werden beim Start von SQL Server ausgeführt. Typische Verwendungszwecke sind zum Beispiel:
Um eine Prozedur als Startup Procedure festzulegen, muß man die Systemprozedur sp_procoption ausführen. Nähere Erläuterungen zur Verwendung dieser Prozedur stehen in BOL.
In SQL Server 2000 und früher funktioniert folgendes:
SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMNPROPERTY(OBJECT_ID(TABLE_SCHEMA+'.'+TABLE_NAME), COLUMN_NAME,'IsIdentity')=1;
SELECT su.name AS TABLE_NAME, so.name AS TABLE_NAME, sc.name AS COLUMN_NAME FROM dbo.syscolumns AS sc JOIN dbo.sysobjects AS so ON sc.id = so.id JOIN dbo.sysusers AS su ON so.uid = su.uid WHERE sc.status & 0x80 = 0x80;
Im SQL Server 2005 sollte man folgendes verwenden:
SELECT su.name AS SCHEMA_NAME, so.name AS TABLE_NAME, sc.name AS COLUMN_NAME FROM sys.columns AS sc JOIN sys.objects AS so ON sc.object_id = so.object_id JOIN sys.schemas su ON su.schema_id = so.schema_id WHERE sc.is_identity = 1;
Multipliziert man zwei Zahlen, die in Addition sowohl bei den Vorkomma- als auch bei den Nachkommastellen, den derzeit "maximalen" Datentyp DECIMAL(38,10) überschreitet, kann man unter Umstände eine Überraschung erleben. Das Ergebnis weicht ab von dem, was man vielleicht erwarten würde.
Allerdings nur oberflächlich betrachtet. Es gibt klar definierte Regeln, die man jedoch kennen muß.
Beispiel:
DECLARE @Multiplikant AS DECIMAL(38, 10)
DECLARE @Multiplikator AS DECIMAL(38, 10)
DECLARE @Result AS DECIMAL(38, 10)
SET @Multiplikant = .1235589123
SET @Multiplikator = 0.55456
SET @Result = @Multiplikant * @Multiplikator
SELECT @Multiplikant, @Multiplikator, @Result
Bevor wir das Ergebnis betrachten, erst einmal ein paar Erläuterungen zu diesem Skript. Wir wollen 2 Zahlen miteinander multiplizieren. Dafür haben wir 3 Variablen vom Typ DECIMAL(38,10) deklariert. Als Ergebnis (in Excel auf 10 Nachkommastellen gerundet) würde man 0,0685208304 erwarten. Läßt man nun das Skript laufen, erhält man folgendes Ergebnis:
------------- ------------- -------------
0.1235589123 0.5545600000 0.0685210000
(1 row(s) affected)
Was ist passiert?
Nun, die deklarierten Variablen Multiplikant und Multiplikator sind jeweils vom Typ DECIMAL(38,10). SQL Server "addiert" Vorkomma- und Nachkommastellen. Das Ergebnis der obigen Rechenoperation müßte also vom Typ DECIMAL(76,20) sein. Dies übersteigt jedoch sowohl die Result Variable als auch den maximal zulässigen DECIMAL Datentyp. Das Ergebnis ist nun, daß SQL Server den Nachkommastellenbereich rundet, um zu vermeiden, daß der Integralpart des Ergebnisses abgeschnitten wird. Dies heißt dann in aller Regel, daß nach 6 Nachkommastellen gerundet wird.
Um nun aus dem obigen Skript ein "korrektes" Ergebnis mit einer hinreichenden Anzahl von Nachkommastellen zu erhalten, muß man die verwendeten Datentypen modifizieren, unter Beachtung der SQL Server-spezifischen Regeln für Precision und Scale.
Bei Multiplikation wird Precision nach der Formel p1 + p2 + 1 errechnet. Scale wird s1 + s2 gerechnet.
Auf das Skript angewendet, könnte man dies folgendermaßen umformulieren:
DECLARE @Multiplikant AS DECIMAL(19, 10)
DECLARE @Multiplikator AS DECIMAL(19, 5)
DECLARE @Result AS DECIMAL(38, 10)
SET @Multiplikant = .1235589123
SET @Multiplikator = 0.55456
SET @Result = @Multiplikant * @Multiplikator
SELECT @Multiplikant, @Multiplikator, @Result
------------- -------- -------------
0.1235589123 0.55456 0.0685208304
(1 row(s) affected)
Wie man sieht, gleich das Ergebnis nun dem mit Excel errechneten. Vom tatsächlich "richtigen" Ergebnis von 0,068520830405088 wurde nur ein nicht signifikanter Anteil an Nachkommastellen abgeschnitten.
Fazit: Manchmal ist weniger mehr. Und gerade wenn man meint, durch Datentypen von vermeindlich hoher Genauigkeit ein hohes Maß an Exaktheit zu erreichen, sollte man sich über die Implikationen bewußt sein.