Bereinigen einer Zeichenkette auf alphanumerische Zeichen via SQL
Heute stand ich vor der Problematik einen String welcher nicht-alphanumerische Zeichen beinhalten könnte auf eine alphanumerische Version “zusammenzuschrumpfen”.
Eine Suche bei google lieferte viele Ergebnisse, aber nicht alle halte ich für wirklich sinnvoll bzw. gut gelöst, sicher liefern sie ein Ergebnis – aber warum soll ich zum Lösen dieses Problems eine Tabelle anlegen – wie z.B. hier: Strim Strips Out Non-Alphanumeric Characters oder hier: Sql Server Tips – Removing or Replacing non-alphanumeric characters in strings beschrieben.
Eine tolle Lösung habe ich dann aber doch noch gefunden und zwar in einem Oracle-Forum *hüstel* RE: Remove non-numeric characters.
Das Ganze in eine StoredProcedure eingebaut könnte dann z.B. so aussehen:
CREATE PROCEDURE SetCompactArticleNumberOnArticle
AS
BEGIN
DECLARE CompactArticleNumberCursor CURSOR FOR
SELECT [GUID]
, VersionNo
, ArticleNumber
FROM dbo.Article
WHERE CompactArticleNumber IS NULL
DECLARE @GUID UNIQUEIDENTIFIER
DECLARE @VersionNo INT
DECLARE @ArticleNumber NVARCHAR(22)
DECLARE @CompactArticleNumber NVARCHAR(22)
DECLARE @Position INT
OPEN CompactArticleNumberCursor
FETCH NEXT FROM CompactArticleNumberCursor into @GUID ,@VersionNo , @ArticleNumber
WHILE @@FETCH_STATUS = 0
BEGIN
SET @CompactArticleNumber = @ArticleNumber;
SELECT @Position = PATINDEX('%[^0-9a-Z]%', @CompactArticleNumber);
WHILE @Position > 0
BEGIN
SELECT @CompactArticleNumber = STUFF(@CompactArticleNumber, @Position, 1, '');
SELECT @Position = PATINDEX('%[^0-9a-Z]%', @CompactArticleNumber);
END;
UPDATE Article
SET CompactArticleNumber = @CompactArticleNumber
WHERE [GUID] = @GUID AND VersionNo = @VersionNo;
FETCH NEXT FROM CompactArticleNumberCursor into @GUID ,@VersionNo , @ArticleNumber
END;
CLOSE CompactArticleNumberCursor
DEALLOCATE CompactArticleNumberCursor
END;
GO
Diese StoredProcedure konvertiert, wann immer sie ausgeführt wird, ArtikelNummern in eine alphanumerische Version dieser. Schlüssel dazu sind die beiden T-SQL Funktionen STUFF und PATINDEX.
Wobei STUFF zum Entfernen der nicht-alphnumerischen Zeichen an einer Position verwendet wird und PATINDEX zum Auffinden der nächsten Position eine solchen Zeichens. Einfach aber effektiv und ganz ohne zusätzliche Tabelle. Sehr schön!
Migration von Parallels zu VMWare Fusion
Wer wie ich von Parallels zu VMWare Fusion wechselt und gern seine virtuellen Maschinen konvertieren will wird wahrscheinlich als erste Aktion google anschmeißen und nach Konvertierungsmöglichkeiten suchen.
Dort wird er fast ausschließlich Anleitungen finden, welche sagen, dass man unter der Parallels VM den VMWare Converter installieren soll und somit die Maschine aus Parallels heraus konvertieren kann. Wie z.B.: auf macworld.com.
Seit der Version 2.0 von Fusion – genauer seit dem Update auf die Version 2.0.1 ist dies für Parallels virtuelle Maschinen bis zu Version 3 einschließlich allerdings nicht mehr notwendig, da das update einen neuen Importer mitbringt, welcher die direkte Konvertierung von Parallels Maschinen zuläßt.
Eine schöne Anleitung in Form eines Screencasts findet sich in den VMWare blogs oder Ihr schaut Ihn Euch schnell hier an:
Einzige Einschränkung – da die Version 2.0.1 vor dem Erscheinen von Parallels 4.0 veröffentlicht wurde – kann sie wie erwähnt nur Maschinen bisVersion 3 umstellen.
Eager Loading mit dem Entity Framework
Wie ich Manuel gerade schon geschrieben habe: Wer meckert muss auch mal loben können!
Und meiner Meinung nach ist das Eager Loading im Entity Framework akzeptabel gelöst. Eager Laoding ist im Gegensatz zum Lazy Loading das Laden, welches Abhängigkeiten direkt mitlädt und nicht erst bei einem Zugriff tarnsparent nachlädt. Wozu das Ganze?! Nun wie ich finde gibt es viele Anwendungsfälle in denen der Zugriff auf Details eines Datensatzes schon feststeht – warum diese also transparent in einem weiteren Datenbankzugriff nachladen, wenn man sie direkt mitladen kann?? Eben!
Ein klassiches Beispiel wäre: Rechnung -> Rechnungsposition -> Einheit
Es gibt also eine Rechnung mit n-Rechnunspositionen und jede dieser Positionen enthält eine Einheit des verkauften Gutes. Datenbanktechnisch ist dies natürlich Normalisiert worde und liegt deshalb in einer zusätzlichen Entität vor.
Typischerweise würden einige sicher das ganz so programmieren (zumindest mit einem ORM-Ansatz):
var rechnungen = from eRechnungen in entities.RechnungSet select eRechnungen;
foreach (Rechnung rechnung in rechnungen)
{
rechnung.Rechnungspositionen.Load();
foreach(Rechnungsposition position in rechnung.Rechnungspositionen)
{
position.EinheitReference.Load();
position.Einheit.....
}
}
Dies wäre eine logische Abbildung des Aufbaus des Datenmodells – nur leider auf Grund der vielen unnötigen Datenbankabfragen eine inperformante Lösung. Bei 1 Rechnung mit 10 Positionen wären dies ganze 21 Datenbankzugriffe – au backe!
Eager Loading vereinfacht dies etwas:
var rechnungen = from eRechnungen in entities.RechnungSet.Include("Rechnungspositionen").Include("Rechnungspositionen.Einheit") select eRechnungen;
foreach (Rechnung rechnung in rechnungen)
{
foreach(Rechnungsposition position in rechnung.Rechnungspositionen)
{
position.Einheit.....
}
}
Durch die Include-Anweisungen wird das generierte SQL-Statement entsprechend erweitert, so dass sowohl die Positionen als auch deren Einheiten beim ersten Datenbankzugriff mitgeldaden werden. Klasse – so werden alle benötigten Daten in 1 Datenbankzugriff geladen!
Die Include-Funktion erwartet eine Pfad-Angabe als String. Diese kann geschachtelt werden, so das über mehrere Ebenen hinweg die Daten bereits mitselektiert werden können. Einziger Nachteil wie ich finde – bei Änderung der Property-Namen entfällt der Kompiletimecheck… aber für den Anfang nicht so schlecht ![]()
Einen Blog-Eintrag aus dem ADO.NET-Team findet sich hier: http://blogs.msdn.com/adonet/archive/2008/10/07/migrating-from-linq-to-sql-to-entity-framework-eager-loading.aspx – zwar als Vergleich zu Linq2SQL, aber man kann das wesentliche zu Eager Loading mittels Entity Framework nachlesen.
Truncate Database – alle Tabellen einer Datenbank löschen
-- First disable referential integrity EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL' GO -- Drop all tables EXEC sp_MSforeachtable @command1 = "DROP TABLE ?" GO -- Now enable referential integrity again EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL' GO
Mit Hilfe dieser paar Zeilen lassen sich in einer Microsoft SQL Server Datenbank alle Tabellen löschen, unabhängig von der Reihenfolge und der Constraints mit welchen sie verknüpft sind. Dazu werden in der ersten Zeile alle Contsraints disabled – danach alle Tabellen gelöscht. Die darauf folgende Anweisung, die Constraints wieder zu enablen, kann man sich eigentlich schenken, da keine Tabellen mehr in der Datenbank enthalten sein sollten. Ich habe es nur der Vollständigkeit halber miterwähnt, da man dieses Skript auch für andere Aufgaben missbrauchen kann: z.B.: alle Tabellen der Datenbank leeren, ebenfalls unabhängig der foreign-key constraints.
Schlüssel zum Erfolg ist die undokumentierte Stored Procedures sp_MSForEachTable. Eine kurze Erläuterung findet sich im databasejournal.com
S#arp Architecture
Da Manuel mich ja heute mahnte “auf Deinem blog ist ja auch nichts mehr los” hier noch ein kleiner Tip zu später Stunde:
Dabei handelt es sich um ein Framework, welches eine Basis für das Erstellen von Web-Applikationen mit Hilfe von ASP.NET MVC und NHibernate bildet.
Beide Frameworks sowohl ASP.NET MVC als auch NHibernate halte ich derzeit für eine perfekte Grundlage, auf der man Aufbauen sollte, um eigene Software zu schreiben.
Ein Blick in den bin Ordner der Bibliothek offenbart, dass ebenfalls Teile des Castle Projects inkludiert sind. Der Active-Record Part aber nicht – obwohl es dazu das wirklich gelungen Visual Studio Pluign Active Writer gibt, welches einen visuellen Designer für das Active Record Pattern auf NHibernate Basis zur Verfügung stellt. Warum kann ich derzeit nicht sagen – da ich mich auch noch nicht in die Tiefe gearbeitet habe.
Hier noch der Link zu dem Blog des Main Developers: Billy MacCafferty – vorbeischauen lohnt sich sicher, um die neusten News zu dem Projekt zu erwischen.
Nachtrag:
Im Dikussionsforum findet sich auch die Antwort, warum nicht auf Active Record gesetzt wurde.