Apr 292011
 

Diese Aufgabe treffe ich immer wieder an. Ich habe eine Datenbank mit etlichen Tabellen und irgend aus einem Grund enthält eine Tabelle doppelte Einträge. Doppelte Einträge heisst in dem Fall, dass Records bis auf ein paar bestimmte Felder gleich sind. Diese sollen nun gelöscht werden.

Wenn im Internet nach einer Lösung gesucht wird finden sich etliche Lösungen. 95% davon nutzen aber eine Temporäre Tabelle, und das will ich nicht. Ich will alles mit einem einzigen Query löschen.

Wie das gemacht werden kann will ich nun kurz Zeigen. Um Daten zu haben, die gelöscht werden können, habe ich die Tabelle be_Posts von BlogEngine.NET ein wenig angepasst und 200 Doppelte Postings generiert. Naiverweise gehe ich davon aus das keine Beziehungen zu anderen Tabellen bestehen. Das soll uns zum jetzigen Zeitpunkt nicht interessieren.

Schritt 1 – Finden der doppelten Einträge

Zuerst muss bestimmt werden ob es überhaupt doppelte Einträge gibt. Dazu muss man nicht alle Felder der Tabelle heranziehen. Es reicht ein paar Felder zu bestimmen die einen Eintrag als doppelt kennzeichnen. Diese Felder werden gruppiert und es wird gezählt wie viele Einträge die Gruppe hat. Bei den Postings habe ich jetzt mal bestimmt das ein Posting eindeutig ist wenn es den selben “Title”, “PostContent” und das selbe “DateCreated” hat. Beim Datum muss man allerdings vorsichtig sein. Je nach dem wie der doppelte Eintrag entstanden ist können hier Sekundenbruchteile Diverenzen vorhanden sein und schon ist der Datensatz nicht mehr gleich. Auch das “Rating” Feld nehme ich nicht rein. Es könnte ja gut sein das ein Posting der Doublette schon bewertet wurde. Man muss also gut überlegen anhand welcher Felder ein Record als identisch gekennzeichnet wird.

SELECT COUNT(*) AS Zähler,
       Title,
       PostContent,
       DateCreated
FROM   be_Posts
GROUP  BY Title,
          PostContent,
          DateCreated
HAVING ( COUNT(*) > 1 ) 

Schritt 2 – Ermitteln der ID’s die gelöscht werden können

Jetzt ist zwar bekannte welche Datensätze doppelt in der Tabelle sind. Aber es ist noch nicht bekannt welchen man genau löschen darf. Von den doppelten Einträgen darf ja nur einer gelöscht werden. Um nun die passenden ID’s zu finden geht man wie folgt vor.

Zuerst wird eine neue View erstellt worin die Tabelle der Posts ist. Dann wird in der View eine “Neue abgeleitet Tabelle hinzufügen” hinzugefügt. In den lehren Rumpf kopiert man das Query von Schritt 1. Danach wird noch ein Join auf die drei Felder gemacht und die “PostID” ausgegeben. Damit aber nur eine ID pro doppelten Eintrag kommt muss die ganze Geschichte noch gruppiert werden. Auf das Feld “PostID” setzt man im Feld “Gruppieren nach” die Funktion “Min”. Somit wird pro Doublette nur eine ID zurückgegeben. Beim Ausführen der Abfrage wird aber noch ein Fehler geworfen. Auf einem Feld vom Typ “uniqueidentifier” kann kein “Min” angewendet werden. Daher bediene ich mich eines CAST und mache ein VARCHAR(40) daraus. Zu sehen in der Zeile 1.

Das sieht dann in etwa so aus.

Query im Designer

PostID ist nicht selektiert, da ein MIN(CAST(… auf dem Feld ist.

Wenn diese Abfrage ausgeführt wird kommen 200 Records zurück. Wir haben ja 200 Doubletten in der Tabelle.

SELECT MIN(CAST(dbo.be_Posts.PostID AS VARCHAR(40))) AS PostID
FROM   dbo.be_Posts
       INNER JOIN (SELECT COUNT(*) AS Zähler,
                          Title,
                          PostContent,
                          DateCreated
                   FROM   dbo.be_Posts AS be_Posts_1
                   GROUP  BY Title,
                             PostContent,
                             DateCreated
                   HAVING ( COUNT(*) > 1 )) AS Doubletten
         ON dbo.be_Posts.Title = Doubletten.Title
            AND dbo.be_Posts.PostContent = Doubletten.PostContent
            AND dbo.be_Posts.DateCreated = Doubletten.DateCreated
GROUP  BY dbo.be_Posts.Title
ORDER  BY dbo.be_Posts.Title 

Ab Zeile 3 sieht man sehr schon das Query von Schritt 1.

Schritt 3 – Löschen der doppelten Einträge

Jetzt ist man im Besitz aller nötigen Daten um die Doubletten zu löschen. Es ist bekannt was genau doppelt ist und es ist die ID bekannt. Wir haben also 200 Records die gelöscht werden müssen.

Also wird einfach ein “DELETE FROM be_Posts WHERE (PostID IN (…” gemacht. Das sieht das so aus.

DELETE FROM be_posts
WHERE  ( PostID IN (SELECT MIN(CAST(dbo.be_Posts.PostID AS VARCHAR(40))) AS
                           PostID
                    FROM   dbo.be_Posts
                           INNER JOIN (SELECT COUNT(*) AS Zähler,
                                              Title,
                                              PostContent,
                                              DateCreated
                                       FROM   dbo.be_Posts AS be_Posts_1
                                       GROUP  BY Title,
                                                 PostContent,
                                                 DateCreated
                                       HAVING ( COUNT(*) > 1 )) AS Doubletten
                             ON dbo.be_Posts.Title = Doubletten.Title
                                AND dbo.be_Posts.PostContent =
                                    Doubletten.PostContent
                                AND dbo.be_Posts.DateCreated =
                                    Doubletten.DateCreated
                    GROUP  BY dbo.be_Posts.Title) ) 

Wenn diese Abfrage nun ausgeführt wird sollte folgende Meldung kommen: (200 Zeile(n) betroffen)

Ergebnis des DELETE Querys

 

Wie man nun sieht kann das löschen von Doubletten mit einer einzigen Abfrage gemacht werden. Es muss nur bekannt sein was genau gelöscht werden muss. Ich hoffe das hilft dem Einen oder Anderen.

Wenn es noch einfacher gehen sollte lasst es mich wissen.

Anmerkungen

Wenn das jemand nachmachen will, mit der be_Posts von BlogEngine.NET wird er beim Schritt 3 enttäuscht. Es wird ein Fehler geworfen da die Tabelle noch Abhängigkeiten vorweist. Ich habe die für den Test einfach gelöscht. Aber in Wirklichkeit müsste man diese natürlich berücksichtigen.

Fehlendes SP1 für die Installation von SQL Server 2008

 Entwicklung, Software  Kommentare deaktiviert für Fehlendes SP1 für die Installation von SQL Server 2008
Apr 242009
 

Vor kurzem wollte ich die Admin Tools vom SQL Server 2008 auf meinem PC installieren. Bei der Prüfung der Installationsregeln kam immer die Meldung, ich solle doch SP1 vom Visual Studio 2008 installieren. Das habe ich schön brav gemacht. Ich hatte das ja eh drauf, aber machte es trotzdem nochmals.

Das Setup vom SQL Server 2008 war aber immer noch sehr hartnäckig und erlaubte mir die Installation nicht. Was habe ich nicht alles Probiert?!

Heute nun hat sich ein Kollege mächtig geärgert weil bei ihm das selbe Problem auftauchte. Jetzt nervte ICH mich noch mehr. Ich erinnerte mich noch an einen Hack für die Registry. Allerdings weiss ich nicht mehr wo ich den Hinweis gefunden habe.

Da regedit sich die letzte Session aber merkt wusste ich noch wo ich in etwa suchen muss. Aber das letzte mal funktionierte es ja auch nicht. Also wie so dieses mal?

Weil ich mutig bin. Man passe die Registry an. ABER AUF EIGENE GEFAHR.

Registry

Zu finden ist alles hier.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DevDiv\VS\Servicing\9.0

Hier findet man immer wieder die Key’s SP und SPIndex. Das setzt sich auch in den Unterverzeichnissen fort. Bei mir waren einige auf 0 statt auf 1 gesetzt. Das habe ich mal angepasst. Es wurde alles auf 1 gesetzt.

Und dann gibt es noch einen Key mit dem Namen SPName. Hier habe ich die Einträge SP1 und RTM gefunden. Alle RTM habe ich durch SP1 ersetzt. Danach habe ich das Setup für SQL Server 2008 gestartet und gespannt auf die Installationsregeln gewartet.

Na ja, was soll ich sagen.

Auf meinem PC ist jetzt SQL Server 2008 installiert und Visual Studio 2008 scheint auch noch zu funktionieren. 🙂

Aber wie gesagt. Auf eigene Gefahr. Bei mir hat’s geklappt. Ob es irgend welche Konsequenzen hat weiss ich noch nicht.

DotNetKicks-DE Image
Mrz 192009
 

Wer kennt das nicht. Man erstellt in einem aktuellen Projekt einen neu Tabelle und füllt diese wärend der Entwicklung mit Daten. Diese sind auch sinnvoll und könnten so ins Livesystem übernommen werden.

Aber wie bekommt man die ohne grosse mühen ins Livesystem?

Bei uns kursierte bis vor kurzem eine Transact SQL wo man die Tabelle angeben konnte. Danach wurde einem noch ein Transact SQL generiert wo man noch die WHERE Klausel anpassen musste. Danach hatte man eine menge Insert’s die aber bei gewissen Spaltennamen nicht funktionierten. Das war einfach nur …

Auf der Suche nach einem Tool fand ich dann den SQL Dumper von Ruizata Project.

Absolut genial. Man gibt den Server an, die Datenbank und wählt dann aus was man exportieren will.

 SQL Dumper Dialog

Generiert wird einem etwas in folgender Form (Beispiele sind von der Webseite des Projekts).

INSERT INTO dbo.TABLE VALUES( 98, 'Pedro Rubina')
INSERT INTO dbo.TABLE VALUES( 96, 'John Riley')
INSERT INTO dbo.TABLE VALUES( 27, 'Sandra Moutinho')

Oder:

SET IDENTITY_INSERT dbo.TABLE ON

INSERT INTO dbo.TABLE(code, name) VALUES( 98, 'Pedro Rubina')
INSERT INTO dbo.TABLE(code, name) VALUES( 96, 'John Riley')
INSERT INTO dbo.TABLE(code, name) VALUES( 27, 'Sandra Moutinho')

SET IDENTITY_INSERT dbo.TABLE OFF

Ach ja. Kosten tut das Tool nichts. 🙂

Reporting Services – SQL Server 2005 – Optionale Parameter

 Entwicklung  Kommentare deaktiviert für Reporting Services – SQL Server 2005 – Optionale Parameter
Okt 012008
 

Ich darf mit dem Reporting Service vom SQL Server 2005 Reports erstellen. Das heisst, ich lasse sie vom Kollegen erstellen. 🙂

Wir haben in einem Webformular 7 Felder wo man Werte eingeben kann. Anhand dieser Felder soll dann der Report generiert werden. Es müssen aber nicht alle Felder mit Werten belegt werden. Sie dürfen auch leer bleiben. Das verursachte jetzt einige Probleme.

Der Reporting Server setzte die Parameter, die keinen Wert haben, auf NULL. Im Query wurde dann der Parameter @BRK=NULL gesetzt. Das führt natürlich immer zu 0 Resultaten.

Die Lösung lies dann auch eine Zeit auf sich warten. Aber per Zufall fand ich dann eine.

WHERE    
(Status.SKey = @SSK OR @SSK IS NULL) AND
(KvpLocation.KvpLocationKey = @KLK OR @KLK IS NULL)

Ganz wichtig ist, dass zuerst auf ein Wert geprüft wird. Erst nach dem OR auf NULL prüfen. Wenn es anders rum ist kann es zu ganz komischen Fehlern kommen. Dann kann es dazu kommen, dass SKey angeblich eine GUID ist und man doch bitte einen gültigen Wert übergeben soll.

Wenn man die Reihenfolge einhält sollte es klappen.

Ach ja, Parameter die nicht gebraucht werden müssen aus der Aufruf URL raus.

Das hier tut nicht:
http://SERVER/Reportserver$development?/KVP%2FeinfacheListe&ADat=01.01.1900%2000:00:00&BRK=&ASN=&SSK=KAPAU&KTK=2&PN=&KLK=&rs%3aClearSession=true&rs%3aFormat=PDF&rs%3aCommand=Render&rc%3aToolbar=False

Wenn man die rot markierten Parameter weg lässt, die sind ja leer, dann funktioniert die Abfrage. Ansonsten wird man immer 0 Records finden.

Jedenfalls bei uns.

Oder geht es einfacher?

SQL Server – ‚model‘ Datenbank ist ‚read-only‘

 Entwicklung  Kommentare deaktiviert für SQL Server – ‚model‘ Datenbank ist ‚read-only‘
Feb 142008
 

Bei einem SQL 2000 Server sind die Festplatten vollgelaufen.
Dabei wurden einige Datenbanken auf ‚read-only‘ gesetzt.

Wenn man in den Optionen der Datenbank das Flag entfernen wollte
kam folgende Meldung.

Error 5063: Database ‚model‘ in in warm standby.

Es gab noch etliche andere Datenbanken die diesen Status hatten.

Als erstes wurde natürlich Platz geschaffen damit der Server wieder
tut wie er sollte. Danach sollten alle Datenbanken wieder aus dem
‚read-only‘ Modus geholt werden. Das war aber gar nicht mal so einfach.

Es kam immer wieder diese Fehlermeldung. Nach einem neustart
des Server’s waren die selben Datenbanken noch immer im ‚read-only‘
Status. Was machen?

Per Zufall merkte ich, dass ein detach und attach der Datenbank
das Problem löste. Ob es richtig ist weiss ich nicht. Im Internet findet
man immer wieder folgenden Tipp.

restore log <DATENBANK> with recovery

Das wollte ich aber nicht wirklich auf einer produktiven Datenbank machen.
Dazu fehlte mir schlicht die Erfahrung. Das detach und attach getraute
ich mich aber zu machen.

Aber die ‚model‘ Datenbank brachte ich so nicht aus dem Status raus.
Die konnte ich nicht detachen. Aber hier half nach dem restart des Server’s
folgender Befehl im Query Analyzer.

use master
restore log model with recovery

Schön, die ‚model‘ Datenbank ist jetzt auch wieder im richtigen Status. 🙂

es läuft: Lucie Silvas – Breathe In – Twisting The Chain

Tech@Night Event – SQL Server 2008

 Entwicklung  Kommentare deaktiviert für Tech@Night Event – SQL Server 2008
Feb 082008
 

Gestern war ich das erste mal an einer Tech@Night Veranstaltung
hier in Luzern. Es ging um den neuen SQL Server 2008 der im
Q3 2008 veröffentlicht werden soll.

Die Tech@Night’s stehen, so viel ich weiss, nur MS Partner zur
Verfügung. Mir kam es vor wie eine Werbeveranstaltung.

Es wurden viele neue, coole, „das muss ich haben“ Sachen gezeigt.
Es wurde aber kein Wort darüber verloren was noch nicht
gemacht wurde oder was nicht gemacht wird aber von allen
sehnlichst erwartet wird.

Hier ein paar Sachen die ich als Cool ansehe.

1. Installation
Ist komplett überarbeitet. Jetzt können diverse Einstellungen
schon bei der Installation des Servers gemacht werden. Nicht erst
danach. Z.B. die Speicherorte der diversen Datenbankdateien.

2 .Filestream Datentyp
Den finde ich cool. Früher packte man alles in ein Blob (Heisst das Ding
wirklich so?).
Das war aber auf 2 GB begrenzt. Sonst packte man alles ins Filesystem und
machte im SQL Server eine Referenz auf die Datei. Der Filestream
macht das auch so, aber es wird alles vom SQL Server gemanagt. Die
Dateien kommen beim Backup mit, sind mit Transaktionen geschützt
und werden mit der DB gelöscht. Ohne nachzufragen. 🙂 Gefällt
mir das Ding.

3. Backup komprimiert
Neu kann der SQL Server 2008 die Backupdateien komprimieren. Und
das nicht zu knapp. Eine Test DB war danach statt 183MB nur noch
40MB gross. Kommt natürlich auf den Inhalt an, aber so im Schnitt
Faktor 2-3 ist drin. Dadurch wird auch das Backup viel schneller. Für
die 183MB brauchte das System 36 Sekunden. Für die Komprimierte
Version noch 15 Sekunden.

4. Ressource Governor
Das Teil ist auch Cool. Man kann auf Instanzenebene Ressourcen einschränken.
Wieviel CPU kommt eine Ressource , wie viel Speicher u.s.w. Das ganze wird
auf Resourcenpools verteilt. Man kann die Ressourcen im laufenden Betrieb
ändern. Das sogar via Script (TSQL).

5. DB Verschlüsseln
Heute ist es ja so, dass wenn man eine mdf Datei bekommt, kann man die einfach
in an einen SQL Server anhängen. Neu kann man die DB Verschlüsseln. Dann geht
das nicht mehr. Man muss einfach darum bemüht sein den Schlüssel auch zu
sichern. Sonst, na ja, viel Spass bei einem Backuprestore.

6. Reportingservice
Braucht neu keinen IIS mehr. Wird direkt über HTTP.sys gemacht. Zudem hat MS
noch das DUNDAS Reporting eingebaut. Gibt schone Reports. Der Reportdesigner
ist auch umgebaut. Sieht jetzt aus wie Word.

7. Management
Auch hier wurde vieles gemacht. Vor allem geht es jetzt einfacher mehrere
SQL Server zu managen. Man kann Systemabfragen direkt über etliche
SQL Server laufen lassen. Man muss nicht mehr jeden Einzelnen Server selektieren.

Und noch vieles mehr.

Mir hat das Teil Eindruck gemacht.

es läuft: EMIGRATE – EMIGRATE – EMIGRATE – MY WORLD

C# – Alle SQL Server auflisten die sichtbar sind

 Entwicklung  Kommentare deaktiviert für C# – Alle SQL Server auflisten die sichtbar sind
Okt 152007
 

Das könnte etwas sein, dass man immer mal wieder gebrauchen könnte.
Eine Liste aller SQL Server die im Netz sichtbar sind.

Mit C# ist das recht einfach.

dgv ist ein DataGridView. Auf der Form gibt es also ein Button (cmdSearchSqlServers)
und ein DataGridView (dgv).

   1:  using System;
   2:  using System.Data.Sql;
   3:  using System.Windows.Forms;
   4:   
   5:  namespace SqlServerBrowser
   6:  {
   7:     public partial class Form1 : Form
   8:     {
   9:        public Form1()
  10:        {
  11:           InitializeComponent();
  12:        }
  13:   
  14:        private void cmdSearchSqlServers_Click(object sender, EventArgs e)
  15:        {
  16:           SqlDataSourceEnumerator sqlServers = SqlDataSourceEnumerator.Instance;
  17:           dgv.DataSource = sqlServers.GetDataSources();
  18:        }
  19:     }
  20:  }

Damit bekommt man eine Liste mit allen SQL Server die im Netz sichtbar sind.
Das heisst aber, dass der SQL Server und das Netzwerk auch mitmachen müssen.

Der Port 1433 (Standartport für die SQL Server Kommunikation) darf nicht
gesperrt sein (Firewall und Netzwerk) und der SQL Browser Dienst auf dem
SQL Server muss laufen.

es läuft: Judas Priest – Live In London CD2 – Living After Midnight

Okt 052007
 

Ich versuchte jetzt schon länger die Clienttools des SQL Server 2005 auf meiner
Windows XP Kiste zu installieren. Eigentlich war das noch nie ein Problem.

Auf diesem PC ist aber Office 2007 installiert. Zudem war schon eine Version
der Office 2003 Web Components installiert.

Das SQL Setup scheiterte jetzt immer beim „Produkt“ OWC11. Das sind
die besagten Web Components. Wie so? Wenn das OWC11 nicht installiert
werden konnte wurden auch die Arbeitsstationskomponenten nicht installiert.

Nicht gerade das was ich wollte. Die Lösung war, man deinstalliere die
Microsoft Office 2003 Web Components und führe das SQL Setup nochmals
aus.

Siehe da, nichts mehr rot. 🙂

SQL Server Setup

SQL Server – Transaktionslog verkleinern

 Entwicklung  Kommentare deaktiviert für SQL Server – Transaktionslog verkleinern
Apr 182007
 

Bei den ganzen Experimenten mit den Indexen [1, 2] auf dem SQL Server
hat es mir die Transaktionslogs doch ziemlich aufgeblasen. Das
braucht natürlich ganz viel Platz auf den Festplatten die mir
zur Zeit auch einwenig fehlt.

Ich war gerade dabei mit dem SQL Server Enterprise Manager ein
„Datenbank Verkleinern …“ durch zu führen. Aber das ganze wollte
nicht so recht. Es blieb immer gleich gross.

Aus lauter Resignation fing ich an in den Blogs zu lesen.
Dieser Entscheid war gut. Sehr gut sogar.

Grund? hier -> SQL Server: Logfile effektiv killen

Ein grosses Dankeschön an Thomas. Das war wieder mal
Gold wert.

Apr 102007
 

Nach den ersten Tuningversuchen wurde es schon wesentlich
besser auf dem SQL Server. Ich hatte in den Logs meiner Applikationen
keine Timeout’s mehr. So weit so gut.

Über Ostern lies ich aber den Profiler weiter laufen, um zu schauen,
ob noch mehr Querys kommen die eine lange Laufzeit haben.

Dabei sind mir noch zwei Querys untergekommen.

SELECT COUNT(Hst_ID) FROM CATI_History WHERE (CheckFlagTransform = 0)

Das Feld CheckFlagTransform ist ein bit Feld. Das kennt nur 0 oder 1.
Die Tabelle hat Heute (10.04.2007) um die 8.4 Mio. Record’s drin.
Der Count steht immer so zwischen 200 und 10’000 Row’s.

Ich habe also auch mal auf das Feld CheckFlagTransform ein Index erstellt.

Auch dieses mal war die Überraschung gross. Von Ursprünglich
> 60’000ms blieben noch < 1’000ms übrig. Auch diese Abfrage
wurde mit einem simplen Index um Faktoren schneller.

Es war nur das hier nötig.