Datenbanken und mehr

25. März 2007

Gehören Dokumente in die Datenbank?

Gespeichert unter: DB Design — Urs Gehrig @ 22:49

Über diese Frage kann man wohl fast endlos streiten.

Argumente für ein Ablegen von Dokumenten in der DB finde ich rasch sehr viele:

  • Verfügbarkeit: Die Dokumente stehen immer zur Verfügung. Ein locken der Files durch andere Applikationen kann nicht auftreten. Auch unbedachte Benutzer können uns durch ein Löschen oder Umbenennen von Files auf dem Server nichts anhaben.
  • Berechtigung: Schreiben wir unsere eigene Applikation, welche die Dokumente von der DB holt, können wir jedes beliebige und noch so detailierte Berechtigungssystem realisieren. Ein Berechtigungssystem, das weit über die Möglichkeiten des Dateisystems geht. So können wir z.B. einem Benutzer lediglich die Berechtigung auf Dokumente geben, welche vor dem 1. April 2006 ausschliesslich von Hans Huber angelegt wurden.
  • Synchron mit Metadaten: Da kein Benutzer unsere Dokumente direkt auf dem Filesystem und somit ohne das Wissen der Applikation durchführen kann, sind die ebenfalls in der DB abgelegten Metadaten der Dokumente mit diesen immer synchron. Ein Ändern des Dokuments und ein nicht nachtragen der Metadaten kann nicht vorkommen – Vorausgesetz wir haben beim Schreiben der Applikation nicht geschlammt.
  • Historisierung: Eine weitere Version eines bestehenden Dokuments ist rasch abgelegt; einfach eine neue Zeile in unserer Dokumententabelle einfügen. Ein kompliziertes Namenskonventionsschema für die Files auf dem Server benötigen wir nicht.
  • Distribution: Wird der Server zu klein und müssen wir unsere Applikation auf einer neuen Hardware installieren, genügt ein einfaches Backup & Restore unserer Datenbank; die Dokumente kommen automatisch mit. Ein aufwendiges umbenennen der Dokumentreferenzen in der DB entfällt genauso wie das exakte nachführen der ganzen Verzeichnisstruktur mit all ihren Security Einstellungen.
  • XML: Ist das Dokument gar ein XML File, dann ist der neue XML Datentyp vom SQL Server 2005 ein weiterer Trumpf für das Ablegen in der DB. Mit Hilfe von XQuery lassen sich die Dokumente effizient durchsuchen und gar bearbeiten.

Gegen ein Ablegen von Dokumenten in der Datenbank finde ich jedoch nur wenige Gründe:

  • Performance: Dieses Argument höre ich immer wieder – angetroffen habe ich es aber noch nie!
  • Grösse: Die Grösse der DB kann rasch sehr schnell anwachsen und dessen Handling wird damit schnell einmal mühsam. Diese Situation lässt sich aber entschärfen, wenn wir die Dokumente in einer separaten Tabelle und diese wiederum in einer separaten Filegroup führen. So lassen sich die eigentlichen Daten unabhängig von den Dokumenten backupen und restoren. Wenn wir die Dokumententabelle gar in einer eigenen DB führen, können wir für die Dokumente sogar ein eigenes Recovery-Modell spezifizieren. Einen wichtigen Nebeneffekt hat das Abtrennen der Dokumente in eine eigene Tabelle auch noch. Alle unbedachten Entwickler, welche das Abfragen aller Metadaten der Dokumente mit SELECT * FROM table lösen, machen uns so keine Angst mehr. Was wäre, wenn wir diese Trennung nicht hätten? Genau, tausende von Dokumenten und somit hunderte oder noch mehr von Gigabytes an Daten würden übers Netzwerk vom Server zum Client transferiert, wo diese dann unbenützt gleich wieder fortgeworfen werden. Das nenne ich ein unnötiges Performance Problem.

Damit dürfte meine Antwort auf die einleitende Frage „Gehören Dokumente in die Datenbank“ wohl klar sein – Ja, wann immer möglich!

15. März 2007

Wie speichere ich ein Datum in der DB?

Gespeichert unter: SQL Server — Urs Gehrig @ 23:54

Diese Frage wird mir immer wieder gestellt und meine Antwort darauf ist immer dieselbe: Natürlich in einem datetime Feld, ausser… Naja, eine Antwort wie man sie von einem Berater halt erwartet; einfach nie festlegen. Lass mich kurz das ausser erklären. Zuerst aber ein paar Worte zu Natürlich in einem datetime Feld.

Der SQL Server kennt zwei Datentypen für das Speichern von Datum und Uhrzeit:

Datentyp Wertebereich Genauigkeit
smalldatetime 1. Januar 1900 bis 6. Juni 2079 1 Minute
datetime 1. Januar 1753 bis 31. Dezember 9999 3.33 Millisekunden

Immer wieder werde ich gefragt „und was ist mit timestamp?“. Leider ist die Bezeichnung etwas irrtümlich ausgefallen; mit einer Zeitangabe hat timestamp absolut nichts zu tun. timestamp ist viel mehr eine Identity. Ein Identity Feld ist eindeutig innerhalb einer Tabelle und timestamp ist eindeutig innerhalb der ganzen Datenbank. Also nichts mit Zeit!

Leider existiert kein Datentyp für das separate Abspeichern eines Datums ohne Uhrzeit. Wenn dich aber trotzdem nur der Tag und nicht die Uhrzeit interessiert (z.B. für eine GROUP BY innerhalb eines Tages) so kannst du dies trotzdem einfach erreichen

GROUP BY DATEADD(day, DATEDIFF(day, ‘19000101′, meinDatetimeFeld), ‘19000101′)

Die Verwendung von datetime hat gegnüber varchar oder numeric eine Menge von Vorteilen. Bei allem was du in datetime speicherst bist du sicher, das dies auch Sinn macht; das Datum wird validiert. So kannst du z.B. nie den 29. Februar 2007 dort abspeichern, da 2007 kein Schaltjahr ist. Mit datetime kannst du auch rechnen. Mit Hilfe des Ausdruckes DATEADD(day, 14, GETDATE()) bekommst du z.B. das Datum in 14 Tagen oder mit DATEDIFF(week, deinGeburtstag, GETDATE()) erfährst du, wie viele Wochen alt du bist. Ist doch ganz einfach, oder?

Nun zum ausser…Falls du ein Geschichtsstudent bist und ein Verzeichnis aller Schlachten unserer Vorfahren im SQL Server ablegen willst, dann ist datetime ganz und gar nicht geeignet. Spätestens wenn du die Schlacht bei Morgarten erfassen willst, wirst du dein blaues Wunder erleben – der 15. November 1315 liegt weit ausserhalb des Gültigkeitsbereichs von datetime. Dass die Zeitrechnung im SQL Server erst im Jahre 1753 beginnt, hat mit der Umstellung vom julianischen zum gregorianischen Kalender zu tun. In England (und auch in den späteren USA) wurde der gregorianische Kalender in der Nacht vom 2. September auf den 14. September 1752 eingeführt. Upps, das muss ja eine tolle, lange Nacht gewesen sein! Leider nein, man hat lediglich 10 Tage übersprungen, um die Frühlings-Tagundnachtgleiche wieder mit dem 21. März in Übereinstimmung zu bringen. Falls du wirklich vor das Jahr 1753 gehen musst, bleibt dir leider nichts anderes übrig, als dein Datum als String oder Zahl in der DB abzulegen. Die Validierung und Rechenfunktionen musst du in diesem Falle aber selber implementieren. Kannst du aber mit dem Wertebereich und der gegebenen Genauigkeit leben, dann gibt es keinen Grund auf datetime respektive smalldatetime zu verzichten.

Beim Arbeiten mit datetime solltest du aber unbedingt auf ein paar Dinge achten. Notationen für Daten variieren von Land zu Land. Ob der SQL Server ein Datum z.B. als 15. März 2007 oder March 15. 2007 darstellt hängt in erster Linie von den Regions- und Sprachoptionen des Client ab, kann aber auch durch einen SET DATEFORMAT oder SET LANGUAGE Befehl übersteuert werden. Willst du das Datum unabhängig von irgendwelchen Einstellungen in einem fix definierten Format anzeigen, kannst du dieses vorgängig in einen String umwandeln

CONVERT(varchar, GETDATE(), 6) z.B. als: 15 Mar 07

Welche Formate unterstützt werden findest du im BOL unter CAST and CONVERT (Transact-SQL) .

Kritisch wird es bei einer T-SQL Abfrage der Art

SELECT * FROM Order WHERE OrderDate = ‘2007/11/03′

Ist hier der 11. März oder der 3. November gemeint? In Abhängigkeit der diversen Einstellungen kann dies auf dem Entwicklungsserver der 11. März sein, während dem auf dem Produktivsystem das Datum als 3. November interpretiert wird. Um diesem Problem aus dem Weg zu gehen, unterstütz der SQL Server das Datumsformat nach ISO 8601, welches ein Datum mit Uhrzeit wie folgt codiert:

yyyy-mm-ddThh:mm:ss[.mmm] z.B. als: ‘2007-03-15T23:14:25.100′

Unabhängig von irgendwelchen Einstellungen und wenn und aber. Dies sollte also dein bevorzugtes Format für die Angabe eines Datums sein. Für nur einen Teil des vollständigen Datums gibt es alternativ auch noch

yyyymmdd z.B. als: ‘ 20070315′
{ts ‘yyyy-mm-dd hh:mm:ss[.fff]‘}
z.B. als: {ts ‘2007-03-15 23:14:25′}
{d ‘yyyy-mm-dd’}
z.B. als: {d ‘2007-03-15′}
{t ‘hh:mm:ss’}
z.B. als: {t ‘23:14:25′}

Kurz zusammengefasst: Benutze wann immer möglich datetime für das Ablegen eines Datums und verwende für die Notation von Konstanten die ISO 8601 Notation.

10. März 2007

Wie greife ich aus dem SQL Server heraus auf Oracle zu?

Gespeichert unter: SQL Server — Urs Gehrig @ 23:11

Tja, SQL Server ist zwar ganz bestimmt eine tolle Datenbank – nur ist dies noch lange nicht die ganze Welt. So kommt es immer wieder mal vor, dass du zusätzlich auch noch auf andere Datenbanken zugreifen musst, z.B. Oracle. Innerhalb SQL Server greifst du am einfachsten mit einem Linked Server darauf zu. Und so gehst du für die Definition dieses Linked Servers vor:

  1. Zuerst musst du die Oracle Client Software installieren, und zwar auf demselben Rechner wo auch dein SQL Server läuft. Die Oracle Client Software kannst du bei Oracle gratis runter laden, z.B. unter
    www.oracle.com/technology/software/products/database/oracle10g/htdocs/10201winsoft.html. Anschliessend kannst du den Client mit dem mitgelieferten Oracle Net Configuration Assistant konfigurieren.
  2. Definiere den Linked Server wir folgt:
    EXEC sp_addlinkedserver
        ’OracleLinkedServer’, ‘Oracle’,
        ’MSDAORA’, ‘OracleServer’
  3. Füge Logins für den Linked Server hinzu:EXEC sp_addlinkedsrvlogin ‘
        OracleLinkedServer ‘, false,
        ’<SQLuser>’, ‘<OracleUser>’, ‘<OraclePwd>’
  4. Jetzt kannst du Oracle bereits abfragen:
    SELECT * FROM
        OracleLinkedServer..SCOTT.EMP

Und wenn’s dann immer noch nicht klappt, hilft dir vielleicht der folgende Blog weiter: mobeen.spaces.live.com/blog/cns!C7EE59ADAEED6598!153.entry

Bloggen Sie auf WordPress.com.