Archiv

Archiv für September, 2009

T-SQL Stringhandling (Extraktion von Token)

25. September 2009 admin Keine Kommentare

Heute möchte ich einmal ein kleines Script bzw. eine kleine Funktion vorstellen die zum Zerlegen von Strings sehr nützlich sein kann.

Wenn man strukturierte Texte vorliegen hat und daraus bestimmte Teile extrahieren soll, so kann man dies sicher mit den Stringfunktionen von T-SQL erledigen. Gerade die Verarbeitung von Listen (Kommasepariert oder sonst irgendwie) bedingt aber die wiederholte Extraktion von Textblöcken (Token) die durch verschiedenste Begrenzungszeichen voneinander getrennt sind.

Als Token verstehe ich in diesem Zusammenhang Teile eines Textes die durch Begrenzer (Delimiter) voneinander logisch getrennt werden. In einem Satz wären das die Worte, in einer Liste die durch z.B. Komma getrennten Artikelnummern oder einfach Bestandteile eines Tabellennamens usw.

Sehen wir uns hierzu mal ein paar Beispiele an:

  • String: ‘Hello World, how are you?’
  • String: ‘123,2345,231234,3456′
  • String: ‘[AdventureWorks].[Person]. [Contact]‘

Extrahieren wir mal das dritte Wort aus Beispiel 1, den zweiten Parameterwert aus Beispiel 2 und den Tabellennamen aus Beispiel 3!

Mit Standardmitteln sicherlich ebenfalls zu realisieren, jedoch mit einer Funktion viel eleganter und Übersichtlicher zu gestalten:

Mehr…

KategorienSQL-Server 2005

T-SQL CASE und die implizite Datentypkonvertierung

23. September 2009 admin Keine Kommentare

Wenn man in einem Ausdruck einen CASE-Block verwendet, so ist dies auf den ersten Blick noch keine Besonderheit. Vergisst man jedoch dabei, dass SQL Server eine implizite Datentypkonvertierung vornimmt, so kann dies zu fehlerhaften Ergebnissen führen die noch dazu sehr schwer zu finden sind.

Betrachten wir hierfür einmal folgendes Beispiel:

 T-SQL |  copy code |? 
01
DECLARE @AlteKndNr VARCHAR(15)
02
DECLARE @Von       VARCHAR(15)
03
DECLARE @Auf       VARCHAR(15)
04
DECLARE @Regel     INT
05
 
06
SET @AlteKndNr = 'K011110999-VIP'
07
 
08
SET @Regel = 1
09
SET @Von   = CASE @Regel WHEN 1 THEN '099' WHEN 2 THEN '0111' ELSE 0 END
10
SET @Auf   = CASE @Regel WHEN 1 THEN '033' WHEN 2 THEN '0000' ELSE 0 END
11
 
12
SELECT NeueKndNr = REPLACE(@AlteKndNr, @Von, @Auf), @Von, @Auf
13
 
14
SET @Regel = 2
15
SET @Von   = CASE @Regel WHEN 1 THEN '099' WHEN 2 THEN '0111' ELSE 0 END
16
SET @Auf   = CASE @Regel WHEN 1 THEN '033' WHEN 2 THEN '0000' ELSE 0 END
17
 
18
SELECT NeueKndNr = REPLACE(@AlteKndNr, @Von, @Auf), @Von, @Auf
19
 
20
-- -------------------------------------------------------------------------
21
-- Ergebnisse:
22
--
23
-- NeueKdNr bei @Regel = 1: K011110339-VIP = OK
24
-- NeueKdNr bei @Regel = 2: K0010999-VIP   = FALSCH
25
--                          K000010999-VIP = Das währe richtig!
26
-- -------------------------------------------------------------------------
27

Mehr…

KategorienSQL-Server 2005

‘virtuelle’ Arrays mit T-SQL

22. September 2009 admin Keine Kommentare

In T-SQL sind per Definition keine Arrays vorgesehen. Es gibt jedoch Fälle in denen der Einsatz eines Arrays von Vorteil wäre.

In einem konkreten Fall soll eine Prozedur einen Datenwert als Parameter erhalten. Dieser Wert wird jedoch in den, für die Abfrage zugrundeliegenden Tabellen nicht direkt verwendet. Vielmehr wird auf den Parameterwert nur indirekt über den Primärschlüssel (IdentityFeld) der Schlüsseltabelle verwiesen.

In der Prozedur müsste jetzt eine Abfrage in der Form:

 T-SQL |  copy code |? 
1
SELECT <feldliste>
2
FROM <komplexe Abfrage>
3
    join Schlüsseltabelle ON Code =
4
<parameterwert></parameterwert></komplexe></feldliste>

erstellt werden.

Grundsätzlich ist dagegen ja nichts einzuwenden. Wenn der Join gegen die Schlüsseltabelle jedoch die Laufzeit des Gesamtstatements spürbar verlängert und zusätzlich in der Prozedur dieser Join mehrfach verwendet wird, dann sollte man darüber nachdenken ob es vielleicht eine performantere Lösung gibt.

Da es kein Array in T-SQL gibt kann man dieses als String simulieren. Dieses virtuelle Array trennt die einzelnen Werte durch einen definierten Delimiter (in meinem Fall ‘|’ der senkrechte Strich). Bei der Abfrage muss jetzt nur der Abfragewert in einen String mit umgebenden Delimitern convertiert werden und über CHARINDEX mit der virtuellen Array-Variablen verglichen werden.

Eine Lösung könnte damit in etwa so aussehen:

 T-SQL |  copy code |? 
1
<erstelle ARRAY mit IdentWerten die durch parameterwert definiert sind>
2
SELECT <feldliste>
3
FROM <komplexe Abfrage>
4
WHERE CHARINDEX('|'+CONVERT(VARCHAR(10),<quellfeld>)+'|',@ARRAY) > 0</quellfeld></komplexe></feldliste></erstelle>

Mehr…

KategorienSQL-Server 2005

Datensatzlänge einer Abfrage schätzen

8. September 2009 admin Keine Kommentare

Gerade wenn man ein bestehendes Datenbanksystem optimieren möchte, könnte die Frage nach der durchschnittlichen Breite einer Abfrage auftauchen. Speziell wenn man keine Tabelle zur Hand hat die in ihren Properties zumindest den verbrauchten Speicherplatz anzeigt, ist die nachfolgende Prozedur vielleicht ganz nützlich.

Es werden für eine gegebene Abfrage die Ergebnisse in eine temporäre Tabelle geschrieben und dann mittels der Funktion DATALENGTH die tatsächliche Länge eines Feldes bestimmt. Die durchschnittliche Summe der Gesamtlänge eines Datensatzes wird in der Rückgabe angezeigt.

Wenn man diese Durchschnittslänge mit der Anzahl der Datensätze multipliziert, erhält man den Nettowert des Datenvolumens das transferiert wird. (zumindest annähernd;))

Wenn ein Feld einen NULL-Wert enthält, setzt die Prozedur eine Feldlänge von 4 Byte ein. Dies wird als Mittelwert einer leeren Feldlänge verwendet und könnte in einer weiteren Ausbaustufe ggf. noch aus den System-Views für die Feldtypen genauer bestimmt werden.


Die Abfrage sollte eine repräsentative Menge an Daten zurückliefern. Es ist vor allem bei sehr großen Ergebnismengen ein wenig Vorsicht angesagt, um nicht die Temp-Datenbank in Bedrängnis geraten zu lassen ;)

Mehr…

KategorienSQL-Server 2005