Glorf.it

Glorf IT

Bedenkliches aus dem IT-Alltag

30. Januar 2007 um 22:35

PowerShell-Spickzettel

Es gibt jetzt einen netten Powershell-Spickzettel auf dem PowerShell-Team-Blog. Natürlich ist das keine vollständige Referenz. Statt dessen enthält er die wichtigsten Handgriffe, um sich zurecht zu finden. Echt prima.

Zuerst gab es in den Kommentaren etwas Aufregung, weil er nur im WinWord2007-Format bereitgestellt wurde, aber nach kurzer Zeit wimmelte es in den Kommentaren nur so von anderen Versionen, z.B. für alte Winwords oder als PDF

30. Januar 2007 um 22:32

SQL: Strings zerhacken

Gestern kam mein Kollege Alexander mit einer ganz spannenden SQL-Fragestellung zu mir. weil die Anwendung auch noch den SQL-Server-2000 unterstützt, mussten wir etwas in die Trickkiste greifen. Ich habe die Fragestellung jetzt daheim noch mal unter dem SQL-Server-2005 nachvollzogen und konnte dabei ein paar der schicken, neuen Features nutzen…

Die Frage ist, wie man Strings, die über eine Legacy-Schnittstelle kommen und so in die Datenbank geschrieben wurden, aufteilen kann. Beispielsweise soll die Zeichenfolge "1234#12#bla#blub#132" mit SQL anhand des Trenners "#" in die Einzelbestandteile aufgeteilt und dann weiterverarbeitet werden.

So könnte die Tabelle aussehen:

LfdNr Zeichenkette
1 13242#22#blabla#233242#blubblub#12321#1312#1131##13123
2 13332#12#blibla#233242#blubblub#12321#1312#1131##13123
3 13353#21#blabli#233242#blubblub#12321#1312#1131##13123
4 13242#12#blibli#233242#blubblub#12321#1312#1131##13123

Eine Lösung, die mir persönlich besonders gut gefällt, hat sich der große Itzik Ben Gan ausgedacht: Dabei wird eine Hilfstabelle benötigt, die nur eine Spalte hat, und für jede Zahl einen Datensatz enthält.

n
1
2
3
4

Dann kann man mit einem Cross-Join zwischen den Tabellen in der Where-Klausel diejenigen Sätze rausfischen, die an der n-ten Position ein "#" haben:

...
from LegacyInput
cross join hilfstabelle
where substring('#'+Zeichenkette+'#', n, 1)='#'
and n <= len(Zeichenkette)+2

Damit das erste Teilstück bei 1 anfängt, wird noch ein "#" vor den Anfang angefügt. Außerdem müssen nur die Datensätze untersucht werden, die kleiner/gleich der Länge der Zeichenkette sind. Das ist eigentlich doppelt gemoppelt und kann daher auch entfallen.

Im SELECT werden dann die Einzelbestandteile rausgelöst: von n bis zum nächsten "#", wobei "n" eine Position ist, an der der ein "#" gefunden wurde.

substring('#'+Zeichenkette, n+1, charindex('#',Zeichenkette+'#',n)-n)

Das gesamte Statement sieht dann so aus:

select lfdNr,
n-len(replace(substring('#'+Zeichenkette, 1, n), '#', '')) as "TeilNr",
substring('#'+Zeichenkette, n+1, charindex('#',Zeichenkette+'#',n)-n) as "Teilstück",
Zeichenkette
from LegacyInput
cross join hilfstabelle
where substring('#'+Zeichenkette, n, 1)='#'
and n <= len(Zeichenkette)+1

Und so das Ergebnis:

LfdNr TeilNr Teilstück
1 1 13242
1 2 12
1 3 blabli
1 4 233242

Das ist aus Datenbanksicht, aber nicht optimal. Wünschenswert wäre ein pivotiertes Ergebnis:

LfdNr attr1 attr2 attr3 attr4 attr5 attr6 attr7 attr8 attr9 attr10
1 13242 22 blabla 233242 blubblub 12321 1312 1131 13123
2 13332 12 blibla 233242 blubblub 12321 1312 1131 13123
3 13353 21 blabli 233242 blubblub 12321 1312 1131 13123
4 13242 12 blibli 233242 blubblub 12321 1312 1131 13123

Das kann man dann ganz einfach mit dem PIVOT-Konstrukt erreichen:

SELECT *
FROM (select
LfdNr,
'attr'+convert(varchar,n-len(replace(substring('#'+Zeichenkette, 1, n), '#', ''))) as "Attribute",
substring('#'+Zeichenkette, n+1, charindex('#',Zeichenkette+'#',n)-n) as "Teilstück"
from LegacyInput
cross join hilfstabelle
where substring('#'+Zeichenkette, n, 1)='#'
and n <= len(Zeichenkette)+1 ) AS ATR PIVOT ( MAX("Teilstück") FOR attribute IN([attr1], [attr2], [attr3], [attr4], [attr5], [attr6], [attr7], [attr8], [attr9], [attr10]) ) AS PVT

Das komplette Beispiel steht auch zum Download bereit.

|