Datenbanken und mehr

24. September 2007

Dynamisches T-SQL

Gespeichert unter: T-SQL — Urs Gehrig @ 08:37

Nenn es wie du willst; dynamisches T-SQL, Codegenerierung oder einfach ein cleveres Script. Fact ist, dass du bei der Erstellung deiner T-SQL Scripts nicht immer schon den ganzen Code kennst, den du zur Laufzeit ausführen musst. Mit dem richtigen Gewusst-Wie hast du aber bereits gewonnen. Beispiel gefällig?

Für ein partnerspezifisches Zusatzmodul zu einem Standard ERP System musste ich ein SQL Setup-Script erstellen. Dieses Script hat die Aufgabe langwierige Konfigurationseinstellungen, welche der ERP Administrator in der Regel per Hand via GUI vornimmt, automatisch einzuspielen. Das Script muss für ein und dieselbe DB beliebig oft ausgeführt werden können. Daher hat das Script zu Begin eine Clean-Up Section, wo allenfalls bereits existierende Konfigurationen aus der DB gelöscht werden. Eine Teilaufgabe in dieser Clean-Up Section besteht aus dem Löschen einzelner Felder aus einer Tabelle. Und genau hier benötige ich mein dynamisches T-SQL Script: Die Namen der zu löschenden Felder sind nicht konstant, sondern müssen aus einzelnen Werten in einer weiteren Tabelle hergeleitet werden (Vielleicht etwas ungewöhnlich. Da es sich hier aber um ein Standard ERP System handelt, welches dieses Verhalten vorgibt, habe ich darauf keinen Einfluss und muss wohl oder übel einfach damit leben). Wer mich schon etwas länger kennt, weiss dass ich nichts von Cursor basierenden Lösungen halte; bei mir haben nur Set basierende Scripts eine Chance. So auch hier. Zuerst die Lösung, dann die Kommentierung:

– drop columns form table tdAttributes
DECLARE @stmt nvarchar(1000)

SET @stmt = (SELECT N‘ALTER TABLE dbo.tdAttributeValues DROP COLUMN Attr_’ + AttributeName + N‘; ‘ as [text()]
             FROM dbo.tdAttributes
            
WHERE AttributeGroup = ‘bbvPersECA’
             FOR XML Path());

EXEC sp_executesql @stmt

Die zu löschenden Spalten sind also in der Tabelle dbo.tdAttributeValues und die Namen der Spalten lassen sich aus dbo.tdAttributes.AttributeName herleiten (fixes Präfix Attr_). Die Idee liegt nahe, alle notwendigen ALTER TABLE Befehle zuerst in einem String (@stmt) zusammen zu fassen und anschliessend diesen String mittels sp_executesql auszuführen. Leider kann ich einem String nicht mehrere Ergebniszeilen eines SELECT-Kommandos zuweisen. Ich muss also alle Zeilen (gleichbedeutend mit alle ALTER TABLE Kommandos) in einer einzigen Zeile zusammenfassen. Genau das macht FOR XML. as [text()] und PATH() sorgen lediglich für die korrekte Formatierung. That’s it! Viel Spass beim adaptieren meiner Lösung für deine Problemstellungen.

17. September 2007

Typofehler in text Feldern

Gespeichert unter: T-SQL — Urs Gehrig @ 15:56

Heute wurde ich um einen Tipp gebeten: Wie korrigiere ich einen Tippfehler in meinen Daten?

Eigentlich mit REPLACE() ganz einfach, wenn da nicht noch die Randbedingungen wären J. Einerseits läuft die DB noch immer auf einem SQL Server 2000 (wie so viele andere ja auch) und anderseits sind die Daten in einem Feld vom Typ text abgelegt. Und da haben wir auch schon den Schlamassel; REPLACE() lässt sich nicht auf Felder vom Typ text anwenden L. Glück gehabt: Es gibt eine Einschränkung in den Daten, welche die ganze Sache wieder vereinfacht: Das falsch geschriebene Wort kommt immer in den ersten 8000 Zeichen vor.

Die korrekte Fragestellung lautet also: Wie korrigiere ich einen Tippfehler in den ersten 8000 Zeichen meiner Daten vom Typ text? Und das ist ganz klar ein Fall für UPDATETEXT:

BEGIN TRAN

DECLARE @wrongWord varchar(50)
DECLARE @correctWord varchar(50)
SELECT  @wrongWord = ‘generalinvoicerequest_410.xsd’, @correctWord = ‘generalInvoiceRequest.xsd’ –- use camel-case

DECLARE @ptrval binary(16)
DECLARE @offset int
DECLARE @length int
DECLARE myCursor CURSOR FAST_FORWARD READ_ONLY FOR
    SELECT TEXTPTR(message_data), CHARINDEX(@wrongWord, SUBSTRING(message_data,1,8000)) - 1, LEN(@wrongWord)
   
FROM IO_XMLOutput
    WHERE Identifier IN (SELECT f.hnnummer
                         FROM fall f

                              JOIN auftrag a ON a.id = f.auftrag_id AND a.nr IN (‘2007.00001′, ‘2007.00004′, ‘2007.00006′)
                              
JOIN leistungserbringer le ON le.id = f.leistungserbringer_id AND le.nr = 999007
                              JOIN kostentraeger_patient kp ON kp.id = f.Kostentraeger_Patient_Id
                             
JOIN kostentraeger kt ON kt.id = kp.Kostentraeger_Id
                        
WHERE f.patienttiers = 2
                             
AND kt.kassencode IN (11110, 11103))
OPEN myCURSOR
FETCH NEXT FROM myCursor INTO @ptrval, @offset, @length
WHILE @@FETCH_STATUS = 0
BEGIN
   
UPDATETEXT IO_XMLOutput.message_data
              
@ptrval – textpointer
              
@offset – insert offset
              
@length – delete length
              
@correctWord – new value
    FETCH NEXT FROM myCursor INTO @ptrval, @offset, @length
END
CLOSE myCursor
DEALLOCATE myCursor

COMMIT

Ganz schön kompliziert, oder? Sicher ein Grund mehr auf SQL Server 2005 zu migrieren. Denn neu gibt es ja den Datentyp varchar(max); und da funktioniert auch REPLACE() wieder. Mehr darüber findest du in meinem Blogbeitrag Wie lade ich Dokumente in die DB?

11. September 2007

Wie finde ich heraus, welche SQL Server Version installiert ist?

Gespeichert unter: SQL Server — Urs Gehrig @ 09:04

Zu wissen, mit welcher Version des SQL Servers du es zu tun hast, ist immer gut. Wenn du interaktiv mit dem SSMS arbeitest, findest du die Version in der Statuszeile des Abfragefensters. Innerhalb deiner eigenen Applikation kannst du die Version mit einem SELECT-Statement abfragen:

SELECT @@Version

Microsoft SQL Server 2000 – 8.00.2039 (Intel X86)
     May 3 2005 23:18:38
     Copyright (c) 1988-2003 Microsoft Corporation
     Developer Edition on Windows NT 5.0 (Build 2195: Service Pack 4)

oder für SQL Server 2000 und 2005:

SELECT SERVERPROPERTY(‘productversion’), SERVERPROPERTY (‘productlevel’), SERVERPROPERTY (‘edition’)
8.00.2039 SP4 Developer Edition

Die einzelnen Productversion habe ich in der folgenden Tabelle zusammengefasst:

SQL Server 2008

 

Katmay November CTP (CTP 5) (November 18, 2007)

10.00.1075.23

Katmay July CTP ( CTP 4) (July 31, 2007)

10.00.1049.14

June 2007 CTP Release (Katmai)

10.00.1019

SQL Server 2005

 

Cumulative Update Package 3 for SP2 (August 23, 2007)

9.00.3186

Cumulative Update Package 2 for SP2 (June 22, 2007)

9.00.3175

Critical Update SP2 (March 6, 2007)

9.00.3050

SP2 (February 16, 2007)

9.00.3042

SP2 CTP (November 6, 2006)

9.00.3027

Cumulative hotfix package (July 13, 2006)

9.00.2153

SP1 (April 19, 2006)

9.00.2047

RTM (November 7, 2005)

9.00.1399.06

September 2005 CTP Release

9.00.1314

June 2005 CTP Release

9.00.1187

April 2005 CTP Release

9.00.1116

December 2004 CTP Release

9.00.981

Beta 2

9.00.852

Beta 1

9.00.608

SQL Server 2000

 

SP4

8.00.2039

SP3a

8.00.760

SP3

8.00.760

SP2

8.00.534

SP1

8.00.384

RTM

8.00.194

SQL Server 7.0

 

SP4

7.00.1063

SP3

7.00.961

SP2

7.00.842

SP1

7.00.699

RTM

7.00.623

SQL Server 6.5

 

SP5a Update

6.50.479

SP5a

6.50.416

SP5

6.50.415

SP4

6.50.281

SP3

6.50.258

SP2

6.50.240

SP1

6.50.213

RTM

6.50.201

10. September 2007

Katmai zum Vierten

Gespeichert unter: Katmai — Urs Gehrig @ 10:20

Seit dem 31. July ist der CTP 4 (oder auch CTP July genannt) von Katmai allgemein verfügbar. Du bekommst ihn unter http://connect.microsoft.com/sqlserver/, benötigst hierfür aber eine Windows Live ID. Sowohl Beispielcodes als auch die Beispiel-DB AdventureWorks ist nicht Bestandteil des Downloads; du kriegst dies aber ebenfalls online unter http://codeplex.com/SqlServerSamples.

Bereits in einem meiner früheren Blogs habe ich dir empfohlen, Katmai in einer Virtual PC/Server Umgebung zu installieren. Irgendwie scheint Microsoft meinen Beitrag gelesen zu haben ;-) . Seit Ende August kannst du bei Microsoft ein solches Image runterladen (http://www.microsoft.com/downloads/details.aspx?FamilyID=6a39affa-db6e-48a9-82e4-4efd6705f4a6&DisplayLang=en). Der Download ist in vier Dateien von Total ca. 2.3 GB aufgeteilt. Entgegen den von Microsoft beschriebenen Requirements benötigst du nicht zwingend einen Virtual Server 2005 R2; bei mir läuft das ganze auch auf einem Virtual PC 2007 (DELL Laptop mit Vista).

Ach ja: Suchst du das Passwort für den Windows Server 2003? Das ist im Readme der Evaluation Edition versteckt: Evaluation1.

Viel Spass beim entdecken der neuen Features! Viellichts kommst du wieder mal hierhin zurück und postest deine Erfahrungen als Kommentar zu diesem Beitrag?

3. September 2007

Gregorianischer Kalender zum zweiten

Gespeichert unter: Katmai, T-SQL — Urs Gehrig @ 21:56

Bereits in einem früheren Blog habe ich über das Speichern eines Datums in der DB gesprochen. Mit dem Erscheinen der nächsten SQL Server Version (Codename Katmai) möchte ich dieses Thema nochmals aufnehmen, hat sich diesbezüglich doch einiges getan. Konkret, der SQL Server kennt neue Datentypen rund um Datum und Uhrzeit:

Data type

Format

Range

Accuracy

Storage size

(bytes)

User-defined fractional second precision

Time zone offset

time

hh:mm:ss[.nnnnnnn]

00:00:00.0000000 through 23:59:59.9999999

100 nanoseconds

3 to 5

yes

no

date

YYYY-MM-DD

00001-01-01 through 9999-12-31

1 day

3

no

no

smalldatetime

YYYY-MM-DD hh:mm:ss

1900-01-01 through 2079-06-06

1 minute

4

no

no

datetime

YYYY-MM-DD hh:mm:ss[.nnn]

1753-01-01 through 9999-12-31

0.333 second

8

no

no

datetime2

YYYY-MM-DD hh:mm:ss[.nnnnnnn]

0001-01-01 00:00:00.0000000 through 9999-12-31 23:59:59.9999999

100 nanoseconds

6 to 8

yes

no

datetimeoffset

YYYY-MM-DD hh:mm:ss[.nnnnnnn] [+|-]hh:mm

00001-01-01 00:00:00.0000000 through 9999-12-31 23:59:59.9999999 (in UTC)

100 nanoseconds

8 to 10

yes

yes

Die Datentypen datetime und smalldatetime kennen wir bereits vom SQL Server 2005 her; hier hat sich nichts geändert. Diese Datentypen sind 100%-ig Kompatibel zur Implementation im SQL Server 2005. Die vier weiteren Datentypen time, date, datetime2 und datetimeoffset sind neu hinzugekommen. User-defined fractional second precision gibt an, ob du die Anzahl Nachkommastellen der Sekunde selber definieren kannst (im Bereich von 0 – 7). Time zone offset gibt an, ob in diesem Datentyp Information zur Zeitzone (inklusive Sommerzeit) abgelegt werden kann.

Wie bis anhin so folgen auch weiterhin alle Datumsangaben dem Gregorianischen Kalender. Eins irritiert mich aber schon: Der Gregorianische Kalender wurde erst im 16. Jahrhundert von Papst Gregor XIII eingeführt. Was passiert also mit den Daten vor dieser Zeit? Immerhin gehen die neuen Datentypen bis zum Jahr 1 zurück. Naja, sobald ich dahinter gekommen bin wie das funktioniert, schreibe ich einen kleinen Update zu diesem Blog J. Vielleicht hast du mir ein eine Erklärung oder auch nur einen kleinen Tipp? Merci!

Mein neuer Favorit ist ganz klar datetimeoffset. Damit kann ich praktisch alles machen: Zeitstempel für Logeinträge einer global verteilten Applikation verwalten (hierfür benötige ich die Zeitzonen), ein Geschichtsbuch ab Jesu Geburt schreiben (hierfür benötige ich Jahrzahlen ab 1) oder auch (vielleicht) die nächste Rangliste für den 100m Sprint an der Weltklasse Zürich (bis die auch die Tausendstelsekunde auswerten geht es bestimmt nicht mehr lange J und dann brauche ich die höhere Genauigkeit bei der Zeit). Soviel fürs erste. Viel Spass beim weiter entdecken der neuen Features von Katmai.

ACHTUNG: Alle hier gemachten Angaben basieren auf SQL Server 2008 CTP July und können bis zum Erscheinen der endgültigen Version noch ändern.

Bloggen Sie auf WordPress.com.