Datumswerte und Zeitstempel



Ähnliche Dokumente
Zeichen bei Zahlen entschlüsseln

Lineargleichungssysteme: Additions-/ Subtraktionsverfahren

Stellen Sie bitte den Cursor in die Spalte B2 und rufen die Funktion Sverweis auf. Es öffnet sich folgendes Dialogfenster

Primzahlen und RSA-Verschlüsselung

Datensicherung. Beschreibung der Datensicherung

Professionelle Seminare im Bereich MS-Office

Was meinen die Leute eigentlich mit: Grexit?

Das Leitbild vom Verein WIR

4 Aufzählungen und Listen erstellen

OP-LOG

Professionelle Seminare im Bereich MS-Office

Web-Kürzel. Krishna Tateneni Yves Arrouye Deutsche Übersetzung: Stefan Winter

Suche schlecht beschriftete Bilder mit Eigenen Abfragen

4. BEZIEHUNGEN ZWISCHEN TABELLEN

M. Graefenhan Übungen zu C. Blatt 3. Musterlösung

(für Grund- und Leistungskurse Mathematik) 26W55DLQHU0DUWLQ(KUHQE UJ*\PQDVLXP)RUFKKHLP

Handbuch zur Anlage von Turnieren auf der NÖEV-Homepage

Wir basteln einen Jahreskalender mit MS Excel.

Einführung in die Java- Programmierung

Binäre Bäume. 1. Allgemeines. 2. Funktionsweise. 2.1 Eintragen

Objektorientierte Programmierung für Anfänger am Beispiel PHP

Adobe Photoshop. Lightroom 5 für Einsteiger Bilder verwalten und entwickeln. Sam Jost

Anleitung zur Daten zur Datensicherung und Datenrücksicherung. Datensicherung

Leichte-Sprache-Bilder

Herzlich Willkommen bei der BITel!

1 Mathematische Grundlagen

mysql - Clients MySQL - Abfragen eine serverbasierenden Datenbank

Überprüfung der digital signierten E-Rechnung

Variablen & erweiterte Aktionen nutzen

Gezielt über Folien hinweg springen

Handbuch Fischertechnik-Einzelteiltabelle V3.7.3

Der vorliegende Konverter unterstützt Sie bei der Konvertierung der Datensätze zu IBAN und BIC.

Tutorial: Entlohnungsberechnung erstellen mit LibreOffice Calc 3.5

Kurzanleitung fu r Clubbeauftragte zur Pflege der Mitgliederdaten im Mitgliederbereich

5 DATEN Variablen. Variablen können beliebige Werte zugewiesen und im Gegensatz zu

Inhalt. 1 Einleitung AUTOMATISCHE DATENSICHERUNG AUF EINEN CLOUDSPEICHER

CLIQ Solo. Einfache und flexible Sicherheit - die Sie selbst aktualisieren können

In diesem Tutorial lernen Sie, wie Sie einen Termin erfassen und verschiedene Einstellungen zu einem Termin vornehmen können.

Outlook Web App 2013 designed by HP Engineering - powered by Swisscom

infach Geld FBV Ihr Weg zum finanzellen Erfolg Florian Mock

Wie Sie mit Mastern arbeiten

Das große ElterngeldPlus 1x1. Alles über das ElterngeldPlus. Wer kann ElterngeldPlus beantragen? ElterngeldPlus verstehen ein paar einleitende Fakten

Datenbanken Kapitel 2

Anleitung über den Umgang mit Schildern

Um in das Administrationsmenü zu gelangen ruft Ihr Eure Seite auf mit dem Zusatz?mod=admin :

Elexis-BlueEvidence-Connector

1. Man schreibe die folgenden Aussagen jeweils in einen normalen Satz um. Zum Beispiel kann man die Aussage:

CSS-Grundlagen. Etwas über Browser. Kapitel. Die Vorbereitung

Datenbank-Verschlüsselung mit DbDefence und Webanwendungen.

Datenübernahme von HKO 5.9 zur. Advolux Kanzleisoftware

Leitfaden zur ersten Nutzung der R FOM Portable-Version für Windows (Version 1.0)

Dynamisches SQL. Folien zum Datenbankpraktikum Wintersemester 2009/10 LMU München

40-Tage-Wunder- Kurs. Umarme, was Du nicht ändern kannst.

Berechnungen in Access Teil I

icloud nicht neu, aber doch irgendwie anders

Summenbildung in Bauteiltabellen mit If Then Abfrage

der Eingabe! Haben Sie das Ergebnis? Auf diesen schwarzen Punkt kommen wir noch zu sprechen.

Abamsoft Finos im Zusammenspiel mit shop to date von DATA BECKER

SANDBOXIE konfigurieren

Inhalt. Allgemeine Einführung. Argumentationsvermögen. Räumliches Vorstellungsvermögen. Begabungen und Fähigkeiten messen

Sie werden sehen, dass Sie für uns nur noch den direkten PDF-Export benötigen. Warum?

Alle gehören dazu. Vorwort

TYPO3-Zusatzkurs für

Durchführung der Datenübernahme nach Reisekosten 2011

Binärdarstellung von Fliesskommazahlen

Was man mit dem Computer alles machen kann

Leit-Bild. Elbe-Werkstätten GmbH und. PIER Service & Consulting GmbH. Mit Menschen erfolgreich

Inhaltsverzeichnis. 1. Empfängerübersicht / Empfänger hinzufügen 2. Erstellen eines neuen Newsletters / Mailings 3. Versand eines Newsletters

Datenaufbereitung in SPSS. Daten zusammenfügen

Computeria Rorschach Mit Excel Diagramme erstellen

Kaufkräftige Zielgruppen gewinnen

Dokumentation IBIS Monitor

1 topologisches Sortieren

Excel Auswertungen in XAuftrag / XFibu

Dieser Ablauf soll eine Hilfe für die tägliche Arbeit mit der SMS Bestätigung im Millennium darstellen.

Ihre Interessentendatensätze bei inobroker. 1. Interessentendatensätze

Gimp Kurzanleitung. Offizielle Gimp Seite:

Zahlen auf einen Blick

Outlook und Outlook Express

Erweiterung der Aufgabe. Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen:

Information zum SQL Server: Installieren und deinstallieren. (Stand: September 2012)

Mit der Maus im Menü links auf den Menüpunkt 'Seiten' gehen und auf 'Erstellen klicken.

Vorlesung Dokumentation und Datenbanken Klausur

Druck von bzw. Scan auf USB-Stick

Speicher in der Cloud

Intranet Moodle

Jede Zahl muss dabei einzeln umgerechnet werden. Beginnen wir also ganz am Anfang mit der Zahl,192.

Verarbeitung der Eingangsmeldungen in einem Callcenter

In diesem Thema lernen wir die Grundlagen der Datenbanken kennen und werden diese lernen einzusetzen. Access. Die Grundlagen der Datenbanken.

3. GLIEDERUNG. Aufgabe:

Stammdatenanlage über den Einrichtungsassistenten

Artikel Schnittstelle über CSV

Bedienungsanleitung Einsatzplanung. Bedienungsanleitung Einsatzplanung. Inhalt. Bedienung einer Plan-Tabelle

ARCO Software - Anleitung zur Umstellung der MWSt

Outlook. sysplus.ch outlook - mail-grundlagen Seite 1/8. Mail-Grundlagen. Posteingang

Erstellen einer digitalen Signatur für Adobe-Formulare

Die Post hat eine Umfrage gemacht

Diese Ansicht erhalten Sie nach der erfolgreichen Anmeldung bei Wordpress.

Zimmertypen. Zimmertypen anlegen

Wintersemester Maschinenbau und Kunststofftechnik. Informatik. Tobias Wolf Seite 1 von 18

Transkript:

KAPITEL 10 Datumswerte und Zeitstempel In den meisten unserer Anwendungen müssen auch Datums- und Uhrzeitwerte gespeichert und verarbeitet werden. Datumswerte sind recht kompliziert: Sie sind nicht nur stark formatiert, sondern unterliegen auch einer Unzahl von Regeln zur Festlegung der genauen Werte und der zulässigen Berechnungen (Schaltjahre und -tage, Schulferien und Betriebsferien, Datumsintervalle usw.). Zum Glück bieten uns das Oracle RDBMS und PL/SQL viel Hilfestellung im Umgang mit Datumsinformationen. Erstens stellen sowohl das RDBMS als auch PL/SQL eine Reihe von echten Datums- und Uhrzeittypen zur Verfügung, um die betreffenden Zeitinformationen in einem internen Standardformat zu speichern. Egal wie Sie diese Werte letztlich darstellen, wenn Sie sie ein- oder ausgeben: Innerhalb von PL/SQL und dem RDBMS werden sie konsistent dargestellt. Für jeden Datums- und Uhrzeitwert speichert Oracle ganz oder teilweise folgende Informationen: Jahr Monat Tag Stunde Minute Sekunde Sekundenbruchteil Stundenverschiebung der Zeitzone Minutenverschiebung der Zeitzone Name der Zeitzonenregion Abkürzung der Zeitzone Die Unterstützung echter Datums-/Uhrzeittypen ist jedoch nur die halbe Miete. Sie benötigen auch eine Sprache, in der sie diese Werte auf natürliche und intelligente Weise verarbeiten können als tatsächliche Datums- und Zeitwerte. Oracle stellt eine umfassende Sammlung von Funktionen zur Verarbeitung solcher Werte zur Verfügung. Sie 272 Kapitel 10: Datumswerte und Zeitstempel

wollen einen String in ein Datum konvertieren? Kein Problem. In Oracle gibt es dazu die Funktion TO_DATE, die diverse unterschiedliche Datumsformate interpretieren und prüfen kann. Sie müssen zwischen Zeitzonen konvertieren? Auch dafür hat Oracle etwas zu bieten: die Funktion NEW_TIME. Sie haben nicht nur eine Menge von Built-in-Funktionen für Datum und Uhrzeit zur Verfügung, sondern können auch bestimmte Arten von arithmetischen Operationen direkt auf einem beliebigen Datums- oder Uhrzeitwert ausführen. Die Anzahl Tage zwischen zwei Daten berechnen Sie z.b. einfach, indem Sie das eine von dem anderen subtrahieren. Mit einem so mächtigen Arsenal für die Datums- und Uhrzeitverarbeitung ist es wichtig zu wissen, woraus man wählen kann. Zu diesem Zweck werden die verschiedenen Datentypen von PL/SQL für die Datums- und Uhrzeitdarstellung im nächsten Abschnitt vorgestellt. Danach werden Konvertierungen behandelt, und es wird erklärt, wie Sie Werte in Ihre Datums- und Uhrzeit-Variablen hinein- und wieder herausbekommen. In den restlichen Abschnitten dieses Kapitels werden die verfügbaren Datums- und Uhrzeitfunktionen beschrieben: Sie erfahren, wie Sie mit diesen Funktionen umgehen und die verschiedenen Datentypen verarbeiten, die Oracle für Datum und Uhrzeit unterstützt. Datentypen für Datum und Uhrzeit Früher hatten Sie keine Wahl. Das Leben war noch einfach. Wenn Sie in den Zeiten von Oracle8i, Oracle8 und den Vorläuferversionen mit Datums- und Uhrzeitwerten arbeiten wollten, benutzten Sie den Datentyp DATE, und das war s. Doch mit Oracle9i führte Oracle eine Menge neuer Datentypen und Funktionen für Datums- und Uhrzeitwerte ein. Ein Großteil dieser neuen Funktionalität von Oracle9i dreht sich um die Datentyp-Familien TIMESTAMP und INTERVAL. Mit diesen Datentypen verwandt sind die neuen Zeitstempel- und Intervall-Ausdrücke. Diese neue Funktionalität ist nicht nur nützlich, sondern bringt Oracle auch den SQL-Standards von ANSI/ISO einen Schritt näher. Der Datentyp DATE DATE ist der ursprüngliche Datentyp, den Oracle für Datum und Uhrzeit bereithielt, und es ist bis Oracle8i auch der einzige. Ein DATE von Oracle speichert folgende Informationen in einem sieben Bytes großen Wert fester Länge: Jahr Monat Tag Stunde Minute Sekunde Datentypen für Datum und Uhrzeit 273

Diese internen Werte können Sie allerdings nicht in einer Zuweisungsanweisung angeben. Statt dessen müssen Sie sich darauf verlassen, daß die Zeichen und numerischen Angaben implizit oder mit Hilfe der Funktion TO_DATE auch explizit in das tatsächliche Datum konvertiert werden. Mehr Informatinen dazu gibt s im Abschnitt»Datumsund Zeitstempel-Konvertierungen«weiter unten in diesem Kapitel. DATE-Variablen deklarieren DATE-Variablen deklarieren Sie mit folgender Syntax: var_name [CONSTANT] DATE [:= DEFAULT anfangs_wert] Hierbei ist var_name der Name der Variablen, die Sie deklarieren. Haben Sie eine DATE- Variable deklariert, können Sie darin entweder einfache Datumswerte oder eine Kombination aus Datums- und Uhrzeitwert speichern. Datums- und Uhrzeitwerte haben immer einen Uhrzeitbestandteil. Die Frage ist nur, ob Sie diesen nutzen oder nicht. Im Folgenden sehen Sie einige Beispiele für DATE-Deklarationen: DECLARE todays_date CONSTANT DATE := SYSDATE; hire_date DATE DEFAULT SYSDATE; end_of_year DATE := TO_DATE('12/31/2002', 'MM/DD/YYYY'); Wann Sie DATE benutzen Sie verwenden DATE, wenn Sie Programme für vorhandene Systeme entwickeln, die in der Datenbank Spalten vom Typ DATE haben, oder wenn Sie eine Anwendung für eine Datenbank schreiben, die noch nicht mit Oracle9i entwickelt wurde. Und natürlich müssen Sie sich mit DATE zufriedengeben, wenn Sie selbst noch mit Oracle8i, Oracle8 oder einer Vorläuferversion arbeiten. Doch für neue Programme, die mit Oracle9i oder höher laufen, sollten Sie einen der neuen TIMESTAMP-Datentypen in Erwägung ziehen. Grenzen von DATE DATE hat zwei Beschränkungen, von denen Sie wissen müssen: Der Datentyp DATE löst Uhrzeitwerte lediglich zu Vielfachen einer Sekunde auf und zu keinen kleineren Einheiten. Daher eignet er sich nicht zur Verfolgung von Echtzeit-Events, die in Abständen von weniger als einer Sekunde auftreten. DATE-Werte enthalten keine Zeitzoneninformationen. Das kann ein Problem sein, wenn Ihr System von Leuten in mehreren unterschiedlichen Zeitzonen benutzt wird. Wenn Sie dann einen DATE-Wert aus der Datenbank abrufen, müssen Sie halt»einfach wissen«, welche Zeitzone ihm zugrunde liegt. 274 Kapitel 10: Datumswerte und Zeitstempel

Die neuen TIMESTAMP-Datentypen haben diese Beschränkung überwunden, so daß Sie nun mit Zeitangaben bis hinab zu einer Milliardstelsekunde umgehen und in den Datums- und Uhrzeitwerten auch Zeitzoneninformationen speichern können. Wenn Sie eine ältere Version als Oracle9i nutzen und Zeiträume von weniger als einer Sekunde verfolgen müssen, können Sie diese Informationen auch als Zahl speichern. Mit der Funktion GET_TIME aus dem Package DBMS_UTILITY können Sie Sekundenbruchteile darstellen. Die TIMESTAMP-Datentypen Oracle9i hat drei TIMESTAMP-Datentypen eingeführt, die alle eine Zeitauflösung bis hinunter zu einer Milliardstelsekunde leisten. Zwei dieser Typen speichern auch Zeitzonen, allerdings in unterschiedlicher Weise. Die drei Typen sind: TIMESTAMP Speichert Datums- und Uhrzeitwerte ohne Zeitzone. Kann die Zeit bis auf eine Milliardstelsekunde genau darstellen, ist aber ansonsten äquivalent zu DATE. TIMESTAMP WITH TIME ZONE Speichert zu jedem Datums- und Uhrzeitwert auch eine Zeitzone. TIMESTAMP WITH LOCAL TIME ZONE Speichert einen Datums- und Uhrzeitwert unter der Annahme, daß für ihn die lokale Zeitzone gilt. Bei Datenbankspalten dieses Typs ist die»lokale«zeitzone die Zeitzone der Datenbank. Für PL/SQL-Variablen dieses Typs ist die»lokale«zeitzone die Zeitzone der Sitzung. Werte, die zwischen Datenbankspalten und PL/SQL- Variablen hin- und hergespeichert werden, werden von einer Zeitzone in die andere konvertiert. Die Varianten dieser drei Typen können zunächst etwas schwer verständlich sein, vor allem der Typ TIMESTAMP WITH LOCAL TIME ZONE. Abbildung 10-1 zeigt, wie sich die verschiedenen Datums- und Uhrzeittypen auf einen Wert auswirken, wenn dieser von einem Benutzer in einer Zeitzone durch die Datenbank an einen Benutzer in einer anderen Zeitzone übergeben wird. Die Abbildung zeigt den Benutzer Jonathan in der Eastern Time Zone, die fünf Stunden hinter der Coordinated Universal Time (UTC) zurück ist. (Die UTC wird weiter unten in einem Kasten beschrieben.) Jonathan speichert denselben Datums- und Uhrzeitwert in vier Datenbankfeldern. Der Wert (im Bild) wird mit der Standard-Notation von ANSI/ISO geschrieben und stellt in diesem Fall drei Uhr nachmittags (15:00:00.00) Eastern Standard Time ( 5:00) am 6. Februar 2002 (2002-02-06) dar. Die Datenbank in der Abbildung kennt die Mountain Standard Time Zone. Beachten Sie, wie sich die Zeitdarstellung in der Datenbank mit den verschiedenen Datums- und Uhrzeittypen ändert. DATE und TIMESTAMP nehmen den Zeitzonenunterschied zwischen Datentypen für Datum und Uhrzeit 275

dem Benutzer und der Datenbank gar nicht zur Kenntnis und bewahren auch nicht die ursprüngliche Zeitzone. So geht diese Information verloren, und mit ihr jegliches Wissen darüber, welchen Zeitpuntk der Benutzer denn eigentlich gemeint hat. Abbildung 10-1: Auswirkungen verschiedener Datums- und Uhrzeittypen Die Spalte des Typs TIMESTAMP WITH TIME ZONE bewahrt die Zeitzoneninformation und stellt aus ihrer Sicht den genauen Zeitpunkt dar, zu dem Jonathan die Werte eingab. Vergleichen Sie nun dieses Verhalten mit dem der TIMESTAMP WITH LOCAL TIME ZONE-Spalte. Hier können Sie sehen, daß die Zeit von Eastern Time in Mountain Time, die lokale Zeitzone der Datenbank, konvertiert wurde. So wurde zwar der richtige Zeitpunkt bewahrt, aber die Perspektive ging verloren: Wir wissen jetzt nicht mehr, in welcher Zeitzone der Zeitwert eingegeben wurde. Abbildung 10-1 stellt nur das Konzept von TIMESTAMP WITH TIME ZONE dar. Intern speichert Oracle alle TIMESTAMP WITH TIME ZONE-Werte als UTC-Zeit. Das geschieht sicherlich, um Datumsvergleiche und Arithmetik effizienter zu machen. Die interne Darstellung des abgebildeten Werts wäre: 2002-02-06 20:00:00:00.00-5:00 Die Zeitzoneninformation wird beibehalten, damit der Datums- und Uhrzeitwert richtig in seine ursprüngliche Zeitzone zurückkonvertiert werden kann. So merken Sie gar nicht, daß intern UTC verwendet wird. Betrachten Sie zum Schluß die Benutzerin Donna in Abbildung 10-1. Donna befindet sich wie auch die Datenbank in der Mountain Standard Time Zone. Schauen Sie, welche Werte ihr zurückgeliefert werden, wenn sie die Datenbank nach den vier von Jonathan 276 Kapitel 10: Datumswerte und Zeitstempel

eingegebenen Werten abfragt. Die Werte vom Typ DATE oder TIMESTAMP sind völlig irreführend. Jonathan hatte um drei Uhr nachmittags Eastern Time etwas eingegeben, und Donna denkt, es sei um drei Uhr nachmittags Mountain Time gewesen. Mit den anderen Datentypen ist es besser: Den TIMESTAMP WITH TIME ZONE-Wert sieht Donna genau so, wie er eingegeben wurde. So erkennt sie, daß Jonathan einen Wert zur Eastern Standard Time eingegeben hatte. Donna sieht auch am Wert des Typs TIMESTAMP WITH LOCAL TIME ZONE den korrekten Zeitpunkt (1:00 PM Mountain Time ist äquivalent zu 3:00 PM Eastern Time), hat aber keine Ahnung, in welcher Zeitzone der Wert ursprünglich eingegeben wurde. Coordinated Universal Time Die Coordinated Universal Time, kurz UTC, wird mit hochpräzisen Atomuhren gemessen und bildet die Grundlage unseres weltweiten Systems der zivilen Zeitmessung. So sind die Zeitzonen alle im Hinblick darauf definiert, wie weit sie in Stunden und Minuten von der UTC entfernt sind. Die UTC wird in regelmäßigen Abständen über Schaltsekunden mit der durch die Erdrotation vorgegebenen Zeit synchronisiert. Vielleicht kennen Sie die Greenwich Mean Time (GMT) bereits. GMT ist in der Wissenschaft inzwischen bedeutungslos. In der Praxis ist GMT häufig äquivalent zu UTC, aber in Wirklichkeit sind diese beiden Zeitangaben nicht dasselbe. Warum heißt nun das Akronym UTC und nicht CUT? Die Normierungsbehörde konnte sich nicht zwischen dem englischen Akronym CUT und dem französischen TUC entscheiden und wählte daher als Kompromiß die Abkürzung UTC, die keiner der beiden Sprachen entspricht. Siehe auch http://www.boulder.nist.gov/timefreq/general/misc.htm#anchor- 14550. Genauere Informationen über UTC finden Sie im Dokument»What is Universal Time?«des U.S. Naval Observatory unter http://aa.usno.navy.mil/faq/docs/ut.html. Siehe auch das Dokument des National Institute of Standards and Technology über UTC unter http://physics.nist.gov/genint/time/world.html. TIMESTAMP-Variablen deklarieren Die Syntax zur Deklaration von TIMESTAMP-Variablen ist ein wenig komplexer als die zur Deklaration von DATE-Variablen. Die meisten TIMESTAMP-Typen sind aus mehreren Wörtern zusammengesetzt, und daran muß man sich erst einmal gewöhnen. Mit TIMESTAMP-Typen können Sie auch festlegen, bis auf wie viele Dezimalstellen genau Sekundenbruchteile angegeben werden. Die Syntax ist: TIMESTAMP [(genauigkeit)] TIMESTAMP [(genauigkeit)] WITH TIME ZONE TIMESTAMP [(genauigkeit)] WITH LOCAL TIME ZONE Datentypen für Datum und Uhrzeit 277

Mit genauigkeit ist in diesen Deklarationen gemeint, auf wie viele Dezimalstellen genau Sekundenbruchteile dargestellt werden. Die Standard-genauigkeit ist 6, so daß Sie eine Uhrzeit bis auf 0,000001 Sekunden genau angeben können. Zulässige Werte für genauigkeit sind 0 bis 9. Eine TIMESTAMP(0)-Variable verhält sich genau wie eine DATE-Variable. Wann Sie TIMESTAMPs benutzen Es gibt zwei Hauptgründe für die Verwendung von TIMESTAMP-Variablen: Sie müssen die Zeit bis auf einen Sekundenbruchteil genau bestimmen. Sie müssen Uhrzeitwerte aus verschiedenen Zeitzonen verarbeiten. Da alle TIMESTAMP-Typen Sekundenbruchteile darstellen können, benutzen Sie TIMESTAMP, wenn das alles ist, was Sie interessiert. Sind jedoch für Sie auch Zeitzonen wichtig, sollten Sie mit TIMESTAMP WITH TIME ZONE oder TIMESTAMP WITH LOCAL TIME ZONE arbeiten. Der Datentyp TIMESTAMP WITH TIME ZONE stellt zusammen mit dem Datums- und Uhrzeitwert auch die Zeitzone dar. Es gibt also keinerlei Zweifel darüber, welchen Zeitpunkt ein solcher Wert tatsächlich meint, da die Zeitzone Teil des Werts ist. Verwenden Sie TIMESTAMP WITH TIME ZONE, wenn Sie es mit Daten aus unterschiedlichen Zeitzonen zu tun haben, vor allem, wenn das Wissen über die Ursprungszeitzone nicht verlorengehen darf. In ganz besonderen Fällen kann die Sommerzeit dazu führen, daß sogar TIMESTAMP WITH TIME ZONE-Werte nicht mehr eindeutig sind. Doch dies können Sie steuern. Einzelheiten finden Sie weiter unten unter»datums- und Zeitstempel-Konvertierungen«. Wenn die genaue Zeit für Sie wichtig ist, aber die ursprüngliche Zeitzone nicht, können Sie TIMESTAMP WITH LOCAL TIME ZONE verwenden. Mit diesem Datentyp werden Datums- und Uhrzeitwerte automatisch in Ihre lokale Zeitzone konvertiert. Seien Sie jedoch mit diesem Typ vorsichtig, denn in dreischichtigen Systemen kann es leicht passieren, daß die»lokale«zeitzone die des Webanwendungs-Servers und nicht die des Benutzers ist, der die Daten in seinem Webbrowser sieht. Der Datentyp TIMESTAMP WITH LOCAL TIME ZONE ist auch nützlich, wenn Sie vorhandene DATE-Spalten einer Datenbank auf TIMESTAMP-Spalten umstellen möchten. Sie können eine DATE-Spalte nicht direkt auf TIMESTAMP WITH TIME ZONE umstellen, da DATEs keine Zeitzoneninformation enthalten. Wenn Sie jedoch alle DATE-Werte 278 Kapitel 10: Datumswerte und Zeitstempel

der Datenbank als zur lokalen Zeitzone gehörig behandeln möchten, können Sie eine DATE-Spalte in eine Spalte des Typs TIMESTAMP WITH LOCAL TIME ZONE konvertieren. Dann werden die Datums- und Uhrzeitwerte der resultierenden Spalte automatisch zwischen der Zeitzone der Datenbank und der Zeitzone der Benutzersitzung konvertiert. Solche Konvertierungen sind vielleicht mehr Sache der Datenbankadministration als der Programmierung, aber darüber Bescheid wissen sollte man allemal. Die INTERVAL-Datentypen INTERVAL-Datentypen sind neu in Oracle9i. Um besser zu verstehen, was diese repräsentieren, sollten Sie zunächst ein wenig überlegen, mit welchen verschiedenen Arten von Datums- und Uhrzeitdaten wir es täglich zu tun haben: Zeitpunkte Ein Zeitpunkt (Instant) ist ein mit einer bestimmten Genauigkeit angegebener Punkt in der Zeit. Wenn wir zu einer bestimmten Stunde geweckt werden möchten, stellt diese Stunde einen Zeitpunkt dar. Die Genauigkeit wäre in diesem Fall eine Stunde oder vielleicht auch eine Minute. DATE und alle TIMESTAMP-Datentypen ermöglichen die Darstellung von Zeitpunkten. Zeiträume Ein Zeitraum (Interval) ist kein bestimmter Zeitpunkt, sondern eine bestimmte Zeitmenge. Mit Zeiträumen gehen wir tagtäglich um. Wir arbeiten acht Stunden (oder hoffen es zumindest), wir nehmen uns eine Stunde Zeit zum Essen (davon träumen wir!) und so weiter. Die neuen INTERVAL-Typen von Oracle9i ermöglichen die Angabe solcher Zeiträume. Zeitdauer Mit Zeitdauer (Period) ist ein Zeitraum gemeint, der zu einem bestimmten Zeitpunkt anfängt und endet. Zum Beispiel:»Ich bin um acht Uhr aufgewacht und habe acht Stunden gearbeitet.«hier würde der Zeitraum, der um 8 Uhr morgens beginnt, als Zeitdauer betrachtet. Einen Datentyp für die Zeitdauer kennen weder Oracle noch ANSI/ISO. Die beiden mit Oracle9i eingeführten INTERVAL-Datentypen entsprechen dem ANSI/ISO-Standard: INTERVAL YEAR TO MONTH Ermöglicht die Definition eines Zeitraums in Jahren und Monaten. INTERVAL DAY TO SECOND Ermöglicht die Definition eines Zeitraums in Tagen, Minuten, Sekunden und Sekundenbruchteilen. Datentypen für Datum und Uhrzeit 279

INTERVAL-Variablen deklarieren Verglichen mit anderen Variablen in PL/SQL ist die Syntax zur Deklaration von INTER- VAL-Variablen ein wenig ungewöhnlich. Sie haben nicht nur Typnamen, die aus mehreren Wörtern bestehen, sondern können in einem Fall sogar zwei Genauigkeiten statt einer angeben: oder: var_name INTERVAL YEAR [(jahr_genauigkeit)] TO MONTH var_name INTERVAL DAY [(tag_genauigkeit)] TO SECOND [(sek bruchteil_genau)] Hierbei ist: var_name der Name der zu deklarierenden INTERVAL-Variablen, jahr_genauigkeit die Anzahl Ziffern (von 0 bis 4), die Sie für einen Jahreswert gestatten möchten, Standard ist 2, tag_genauigkeit die Anzahl Ziffern (von 0 bis 9), die Sie für einen Tageswert gestatten möchten, Standard ist 2, sek_bruchteil_genau die Anzahl Ziffern (von 0 bis 9), die Sie für einen Sekundenbruchteil gestatten möchten (also die Genauigkeit der Sekundenbruchteilangabe). Der Standard ist 6. Es liegt in der Natur der Zeiträume, daß Sie sich nur in Sonderfällen um ihre Genauigkeit zu kümmern brauchen. INTERVAL YEAR TO MONTH-Werte sind immer so normalisiert, daß die Anzahl der Monate zwischen 0 und 11 liegt. In Oracle können Sie keinen Monat größer als 11 angeben: Einen Zeitraum, der sich über ein Jahr und 13 Monate erstreckt, müssen Sie als 2 Jahre und 1 Monat ausdrücken. Die jahr_genauigkeit legt fest, wie groß der Zeitraum höchstens sein darf. Ebenso legt tag_genauigkeit in INTERVAL DAY TO SECOND die Maximalgröße dieses Zeitraums fest. Für eine Variable des Typs INTERVAL DAY TO SECOND brauchen Sie aus denselben Gründen keine Genauigkeit für Stunde, Minute und Sekunde anzugeben, aus denen Sie auch für INTERVAL YEAR TO MONTH keine Genauigkeit für den Monat angeben. Die Zeiträume sind immer so normalisiert, daß die Werte für Stunde, Minute und Sekunde im normalen Wertebereich liegen: 0 bis 23 für Stunden, 0 bis 59 für Minuten und 0 bis 59 für Sekunden, ausgenommen Sekundenbruchteile. Die Genauigkeit für Sekundenbruchteile (sek_bruchteil_genau) ist notwendig, weil INTERVAL DAY TO SECOND-Werte Zeiträume bis auf den Sekundenbruchteil genau auflösen können. Da andererseits INTERVAL YEAR TO MONTH-Werte keine Monatsbruchteile aufnehmen, ist für den Monat keine Angabe der Genauigkeit erforderlich. 280 Kapitel 10: Datumswerte und Zeitstempel

Wann Sie INTERVAL benutzen Da INTERVAL-Typen in Oracle neu sind, wollen wir ein paar Beispiele für ihre Verwendung anschauen. Wir hoffen damit Ihre Kreativität zu wecken, so daß Sie sich auch selbst Gedanken darüber machen, wie Sie in Ihren Systemen die INTERVAL-Typen am besten einsetzen. Stellen Sie sich vor, Sie arbeiten in einer Fabrik für Lebensmittelkonserven. Die Konserven müssen ein Verfallsdatum erhalten, und Ihre Aufgabe ist es, das Programm zu schreiben, das dieses Verfallsdatum für jedes Produkt errechnet, das gerade konserviert wird. Diese Aufgabe schreit geradezu nach dem Einsatz von Zeiträumen. Die Lebensmittel halten sich eine gewisse Zeit in der Konserve frisch, und das Verfallsdatum markiert den Zeitpunkt, an dem diese Zeit zu Ende geht. Da sich die Waren in Konservendosen sehr lange halten, reden wir hier in Zeiträumen von Jahren und Monaten. Um die Dinge noch komplizierter zu machen: Jedes konservierte Lebensmittel hat ein anderes Verfallsdatum. Gemüse in Dosen hält sich länger als Fleisch in Dosen, und die Verfallsdaten von Tierfutter lassen sich weiter hinausschieben als die von menschlicher Nahrung. Sie beschließen also, eine Tabelle zu erstellen, die für jedes Produkt Ihrer Firma einen Haltbarkeitszeitraum»good_for«speichert. Eine Möglichkeit für diese Tabelle wäre: CREATE TABLE shelf_life ( product_id NUMBER, good_for_period INTERVAL YEAR(2) TO MONTH NOT NULL ); Dann stellen Sie etwas fest (wenn Sie bereits lange genug programmieren, spricht die Erfahrung manchmal auf wundersame Weise zu Ihnen): Sie benötigen eine PL/SQL- Funktion, die Ihnen das Haltbarkeitsdatum für ein Produkt anhand seines»good_for«- Zeitraums liefert. Diese Funktion kann man kurz und gut ausdrücken als: CREATE OR REPLACE FUNCTION expiration_date ( good_for_period_in IN shelf_life.good_for_period%type ) RETURN DATE IS -- Kuerze das aktuelle Datum so, dass wir nicht die Uhrzeit, -- sondern nur das Datum selbst uebrig behalten. RETURN TRUNC (SYSDATE) + good_for_period_in; Hätten wir die erste Lösung eingesetzt (zwei Zahlenspalten für Jahre und Monate anstatt einer einzigen INTERVAL-Spalte), wäre die Berechnung komplizierter: expiration_date := ADD_MONTHS(TRUNC(SYSDATE), (good_for_years_in * 12) + good_for_months_in ); Datentypen für Datum und Uhrzeit 281

Die Lösung mit dem INTERVAL bietet mehrere Vorteile gegenüber der anderen: Sie ist einfacher, was Ihnen Programmierfehler und Debugging erspart. Sie ist leichter zu lesen und zu verstehen. Der Typ INTERVAL YEAR TO MONTH in der Tabelle good_for gewährleistet, daß nur gültige Jahres-/Monatszeiträume gespeichert werden. Sie brauchen sich nie Sorgen über die Interpretation eines Werts wie 1 Jahr und 24 Monate zu machen. Eine weitere Anwendung für INTERVAL-Typen haben Sie, wenn Sie sich die Differenz zwischen den beiden Daten anschauen. Betrachten Sie folgendes Beispiel, das die Beschäftigungsdauer eines Angestellten berechnet: DECLARE start_date DATE; end_date DATE; service_interval INTERVAL YEAR TO MONTH; years_of_service NUMBER; months_of_service NUMBER; --Normalerweise wuerden wir Start- und Enddaten aus einer Datenbank holen. start_date := TO_DATE('29-DEC-1988','dd-mon-yyyy'); end_date := TO_DATE ('26-DEC-1995','dd-mon-yyyy'); --Stelle Dienstjahre und -monate fest und zeige sie an: service_interval := (end_date - start_date) YEAR TO MONTH; DBMS_OUTPUT.PUT_LINE(service_interval); --Hole mit der neuen EXTRACT-Funktion den --Jahres- und den Monatsteil heraus. years_of_service := EXTRACT(YEAR FROM service_interval); months_of_service := EXTRACT(MONTH FROM service_interval); DBMS_OUTPUT.PUT_LINE(years_of_service ' Jahre und ' months_of_service ' Monate'); Die Zeile, in der die Dienstjahre und -monate berechnet werden, ist: service_interval := (end_date - start_date) YEAR TO MONTH; YEAR TO MONTH ist Teil einer Syntax zur Darstellung von Zeiträumen, über die Sie weiter unten im Abschnitt»Datums-/Uhrzeit-Arithmetik«noch Genaueres nachlesen werden. Sie sehen jedoch bereits hier, daß sich ein Zeitraum ganz einfach durch Subtraktion eines Datums von einem anderen berechnen läßt. Hätten wir keinen INTERVAL- Typ verwendet, hätten wir so etwas wie dieses schreiben müssen: months_of_service := ROUND(months_between(end_date, start_date)); years_of_service := TRUNC(months_of_service/12); months_of_service := MOD(months_of_service,12); Wieder ist die Lösung ohne INTERVAL viel schwieriger zu programmieren und zu verstehen. 282 Kapitel 10: Datumswerte und Zeitstempel

Der Typ INTERVAL YEAR TO MONTH hat ein Rundungsverhalten, dessen verschiedene Auswirkungen Sie unbedingt verstehen sollten. Bitte lesen Sie hierzu den Abschnitt»Datums-/Uhrzeit-Arithmetik«. Wozu zwei INTERVAL-Datentypen? Anfangs haben wir uns über die beiden INTERVAL-Typen gewundert. Wir sahen zwar, daß beide Typen zusammengenommen alle Teile eines TIMESTAMP-Werts berücksichtigten, aber es schien uns doch reichlich überflüssig, das Jahr und den Monat getrennt von Tagen, Stunden, Minuten und Sekunden zu behandeln. Warum keinen einfachen INTER- VAL-Typ definieren, der alles abdeckt? Doch es stellt sich heraus, daß an alledem der gute alte Julius Caesar schuld ist, zu dessen Zeit unser Kalender entwickelt und die Länge der meisten Monate festgelegt wurde. Die beiden INTERVAL-Typen mit ihrer Trennlinie zwischen Monaten und Tagen gibt es, weil Monate den einzigen Bestandteil von Datums- und Uhrzeitwerten darstellen, der verschiedene Längen haben kann. Denken Sie an einen Zeitraum von einem Monat und 30 Tagen. Wie lang soll denn das sein? Kürzer als zwei Monate? Dasselbe wie zwei Monate? Mehr als zwei Monate? Wenn der eine Monat der Januar ist, dann reichen die 30 Tage über den Februar hinaus in den März hinein, und der Zeitraum von 61 Tagen ist etwas mehr als»zwei Monate«lang. Ist der eine Monat der Februar, beträgt der Zeitraum genau zwei Monate (aber nur 59 oder 60 Tage). Ist der eine Monat der April, dann ist der Zeitraum etwas weniger als zwei Monate lang und beträgt insgesamt 60 Tage. Anstatt all die Komplikationen zu sortieren und gesondert zu behandeln, die aufgrund unterschiedlich langer Monate für Zeitraumvergleiche, Datums-Arithmetik und Normalisierung von Datumswerten entstehen,»zerlegt«der ANSI-Standard das Datums- und Uhrzeitmodell in zwei Teile, nämlich Jahr und Monat auf der einen und den ganzen Rest auf der anderen Seite. (Mehr dazu erfahren Sie in A Guide to the SQL Standard, 3rd Edition, von C. J. Date, Addison-Wesley, 1993.) Datums- und Zeitstempel-Konvertierungen Nun, da Sie die Oracle-Datentypen für Datum und Uhrzeit kennengelernt haben, ist es an der Zeit zu betrachten, wie Sie Datumswerte in Datums- und Uhrzeit-Variablen hinein und wieder aus ihnen herausbekommen. Für Menschen lesbare Datums- und Uhrzeitwerte sind Strings wie»5. März 2002«oder»10:30 Uhr«. Daher konzentrieren wir uns hier darauf, Datums- und Uhrzeitwerte aus Strings in die interne Darstellung von Oracle und umgekehrt zu konvertieren. PL/SQL prüft und speichert Daten vom 1. Januar 4712 v.chr. bis 31. Dezember 9999 n.chr. (Die Oracle-Dokumentation spricht von dem 31. Dezember 4712 als spätestem Datum.) Was für Ihre Version gilt, können Sie mit dem Skript showdate.sql feststellen, Datums- und Zeitstempel-Konvertierungen 283

das auf der Website von O Reilly zur Verfügung steht. Wenn Sie ein Datum ohne Uhrzeit eingeben (da für viele Anwendungen die Uhrzeit keine Rolle spielt, können Sie diese bei PL/SQL auch weglassen), ist der Uhrzeitwert standardmäßig Mitternacht (12:00:00 AM). Oracle kann beinahe jedes Datums- und Uhrzeitformat interpretieren, das Sie ihm vorwerfen. Der Schlüssel für diese Flexibilität ist das Datumsformatmodell: ein String von Sonderzeichen, die das Format eines Datums für Oracle definieren. Da diese Zeichen die Grundlage für die Datumskonvertierung bilden, reden wir als erstes über die Formatmodelle und zeigen danach, wie Sie diese einsetzen, um Daten in Datums- und Uhrzeit- Variablen von PL/SQL hinein- und wieder herauszubekommen. Datumsformatmodelle Bis zur Version 6 des Oracle RDBMS hatte ein Datum als Zeichenwert das Standardformat TT-MON-JJ, was viele Entwickler und Benutzer mit Bestürzung erfüllte. Dieses Format ist zwar in vielen Teilen der Welt üblich, aber nicht in den USA. Seit Oracle7 können Datenbankadministratoren ein eigenes Standarddatumsformat angeben (das bei der Initialisierung oder beim Hochfahren der RDBMS-Instanz in Kraft tritt). Dazu wird der Parameter NLS_DATE_FORMAT wie folgt eingestellt: NLS_DATE_FORMAT = 'MM/DD/YYYY' Das Standardformat wird also implizit mit einem anderen Initialisierungsparameter, nämlich NLS_TERRITORY, gesetzt. Wenn Sie einen Wert für NLS_TERRITORY angeben, geben Sie damit Konventionen für das Format und die Sprache des Datums, die Zahlenformate, die Währungssymbole und den Tag des Wochenbeginns vor. Sie können auch auf der Sitzungsebene ein Datumsformat angeben. Das ist praktisch, wenn Ihre speziellen Bedürfnisse sich von denen der meisten Datenbanknutzer unterscheiden. Mit dem Befehl ALTER SESSION richten Sie ein Standarddatumsformat auf der Ebene der Sitzung ein. Das folgende Beispiel funktioniert ab Oracle8i und gibt MM/DD/YYYY als Standarddatumsformat vor: EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_DATE_FORMAT=''MM/DD/YYYY'''; Um zu schauen, welches Standarddatumsformat für Ihre Sitzung zu einem gegebenen Zeitpunkt gilt, können Sie die Data Dictionary-View NLS_SESSION_PARAMETERS wie folgt abfragen: SELECT value FROM nls_session_parameters WHERE parameter='nls_date_format'; Sowohl die Entwickler als auch die Benutzer müssen das Standarddatumsformat kennen, wenn sie mit Datumswerten arbeiten. In den nachfolgenden Abschnitten»Strings in Datumswerte konvertieren«und»konvertierung von Daten in Strings«werden Sie erfah- 284 Kapitel 10: Datumswerte und Zeitstempel

ren, wie Sie Datumsformatmodelle für einzelne Konvertierungen angeben können, anstatt das Standardmodell der Sitzung oder der Datenbank zu verwenden. Wie Sie sehen, spielen Formatmodelle (wie MMDDYY und Month DD, YYYY) eine wichtige Rolle für die Konvertierung von Datums- und Zeichendaten. Datumsformatmodelle bestehen aus einzelnen Elementen. So sind die Bestandteile des Modells MM/DD/YYYY: MM DD YYYY die beiden vorwärtsgerichteten Schrägstriche (/) Tabelle 10-1 zeigt alle Datumsformat-Elemente und erklärt, wie Sie diese in allen Variationen einsetzen können. In der Tabelle finden Sie Beispiele für einige dieser Variationen. Sie können die Formatelemente nach Belieben und in jeder Reihenfolge kombinieren. Allerdings können Sie mit NLS_DATE_FORMAT nicht zweimal dasselbe Datumselement angeben, sondern nur entweder MONTH oder MON oder MM, da mit allen dreien der Monat gemeint ist. In älteren Oracle-Versionen war es zulässig, dasselbe Datumselement zweimal anzugeben. So kommt z.b. in»mon (MM) DD, YYYY«der Monat zweimal vor. Seit Oracle9i können Sie ein Element in einem Formatmodell nur noch einmal angeben. Einige Elemente in Tabelle 10-1 werden nur für die Übersetzung von Datums- und Uhrzeitwerten aus dem internen Format von Oracle in Strings eingesetzt, aber nicht umgekehrt. Solche Elemente können Sie in einem Standarddatumsmodell (z.b. mit NLS_DATE_FORMAT) nicht benutzen, da ein Standarddatumsmodell für Konvertierungen in beide Richtungen einsetzbar sein muß. Die betreffenden Elemente sind in der Tabelle mit»nur Ausgabe«markiert. Tabelle 10-1: Elemente von Datumsformatmodellen Element 6&& RGHU && 6<<<< RGHU <<<< Beschreibung 'DV -DKUKXQGHUW,P 6&&)RUPDW VWHKW YRU MHGHP 'DWXP YRU &KULVWL *HEXUW HLQ 0LQXV]HLFKHQ ± 1XU $XVJDEH 'DV -DKU PLW YLHU =LIIHUQ,P 6<<<<)RUPDW VWHKW YRU MHGHP 'DWXP YRU &KULVWL *HEXUW HLQ 0LQXV]HLFKHQ ±,<<< 'DV -DKU PLW YLHU =LIIHUQ ODXW,626WDQGDUG \HDU 1XU $XVJDEH <<< RGHU << RGHU <,<< RGHU,< RGHU, <<<< 'LH OHW]WHQ GUHL ]ZHL RGHU HLQH =LIIHUQ GHV -DKUHV :HQQ 6LH GLHVH (OHPHQWH ]XU.RQYHUWLHUXQJ HLQHV 6WULQJV LQ HLQ 'DWXP YHUZHQGHQ LVW GDV DNWXHOOH -DKU KXQGHUW GHU 6WDQGDUG I U GLH -DKUKXQGHUWDQJDEH 'LH OHW]WHQ GUHL ]ZHL RGHU HLQH =LIIHUQ GHV -DKUHV QDFK,626WDQGDUG 1XU $XV JDEH 'DV -DKU LQ YLHU =LIIHUQ PLW.RPPD DOV 7DXVHQGHUWUHQQ]HLFKHQ XQ EOLFK Datums- und Zeitstempel-Konvertierungen 285

Tabelle 10-1: Elemente von Datumsformatmodellen (Fortsetzung) Element 6<($5 <($5 6<HDU <HDU V\HDU RGHU \HDU 'DV -DKU LQ :RUWHQ ]% ªWZR WKRXVDQG WZR 'DV 3UlIL[ 6 YHUVLHKW HLQ 'DWXP YRU &KULVWL *HEXUW PLW HLQHP 0LQXV]HLFKHQ 'DV )RUPDW NDQQ *UR RGHU.OHLQ EXFKVWDEHQ RGHU HLQH 0LVFKXQJ HQWKDOWHQ 1XU $XVJDEH 55 'LH OHW]WHQ ]ZHL =LIIHUQ GHV -DKUHV (V GLHQW GD]X -DKUH LQ DQGHUHQ -DKUKXQGHU WHQ DOV XQVHUHP GDU]XVWHOOHQ 6LHKH DXFK ª'DV (OHPHQW 55 5555 'DVVHOEH ZLH 55 DXI GLH $XVJDEH DQJHZHQGHW $N]HSWLHUW -DKUH PLW YLHU =LIIHUQ ZHQQ HV I U GLH (LQJDEH DQJHZHQGHW ZLUG %& RGHU $' %& EHGHXWHW YRU XQG $' QDFK &KULVWL *HEXUW.HLQH 3XQNWH %& RGHU $' %& EHGHXWHW YRU XQG $' QDFK &KULVWL *HEXUW 0LW 3XQNWHQ ( $EN U]XQJ GHU bud *LOW QXU I U IROJHQGH.DOHQGHU -DSDQLVFK &KLQHVLVFK XQG 7KDL%XGGKLVWLVFK 1XU (LQJDEH (( 'HU YROOH 1DPH GHU bud 4 'DV 4XDUWDO YRQ ELV -DQXDU ELV 0lU] VLQG GDV HUVWH 4XDUWDO $SULO ELV -XQL GDV ]ZHLWH XVZ 1XU $XVJDEH 00 'LH 0RQDWV]DKO YRQ ELV -DQXDU LVW GHU 0RQDW 1XPPHU 6HSWHPEHU GHU 0RQDW 1XPPHU XVZ 50 'LH 0RQDWV]DKO LQ U PLVFKHQ =LIIHUQ YRQ, ELV ;,, -DQXDU LVW, 6HSWHPEHU LVW,; XVZ 0217+ 0RQWK RGHU PRQWK 021 0RQ RGHU PRQ Beschreibung 'HU 0RQDWVQDPH LQ *UR RGHU.OHLQEXFKVWDEHQ RGHU HLQHU 0LVFKXQJ YRQ EHL GHP 'LH $EN U]XQJ GHV 0RQDWVQDPHQV ]% -$1 I U -DQXDU.DQQ HEHQIDOOV LQ *UR RGHU.OHLQEXFKVWDEHQ RGHU HLQHU 0LVFKXQJ YRQ EHLGHP VWHKHQ :: 'LH.DOHQGHUZRFKH YRQ ELV 1XU $XVJDEH,: 'LH.DOHQGHUZRFKH YRQ ELV RGHU QDFK,626WDQGDUG 1XU $XVJDEH : 'LH :RFKH GHV 0RQDWV YRQ ELV :RFKH EHJLQQW DP HUVWHQ XQG HQGHW DP VLHEWHQ 7DJ GHV 0RQDWV 1XU $XVJDEH ''' 'HU 7DJ GHV -DKUHV YRQ ELV '' 'HU 7DJ GHV 0RQDWV YRQ ELV ' 'HU :RFKHQWDJ YRQ ELV :HOFKHU :RFKHQWDJ GHU HUVWH 7DJ GHU :RFKH LVW LVW LP,QLWLDOLVLHUXQJVSDUDPHWHU 1/6B7(55,725< GHU 'DWHQEDQNLQVWDQ] DXV GU FNOLFK DQJHJHEHQ '$< 'D\ RGHU 'HU 7DJ LQ *UR RGHU.OHLQEXFKVWDEHQ RGHU HLQHU 0LVFKXQJ YRQ EHLGHP GD\ '< '\ RGHU G\ 'LH $EN U]XQJ GHV 7DJHV ]% 78( I U 7XHVGD\'LHQVWDJ - 'DV 'DWXP LP -XOLDQLVFKHQ 7DJHVIRUPDW JHUHFKQHW DOV $Q]DKO GHU 7DJH VHLW GHP -DQXDU Y&KU GHP lowhvwhq 'DWXP LP 2UDFOH5'%06 $0 RGHU 30 'HU 9RU1DFKPLWWDJVLQGLNDWRU RKQH 3XQNWH $0 RGHU 30 'HU 9RU1DFKPLWWDJVLQGLNDWRU PLW 3XQNWHQ 286 Kapitel 10: Datumswerte und Zeitstempel

Tabelle 10-1: Elemente von Datumsformatmodellen (Fortsetzung) Element Beschreibung 7=' 'LH $EN U]XQJ GHU =HLW]RQH ]% (67 367 XVZ 'LHQW QXU GHU (LQJDEH XQG VLHKW ]XQlFKVW NRPLVFK DXV 7=+ 'LH =HLW]RQHQYHUVFKLHEXQJ LQ 6WXQGHQ ± ]% PHLQW HLQH =HLW]RQH GLH I QI 6WXQGHQ YRU 87& OLHJW 7=0 'LH =HLW]RQHQYHUVFKLHEXQJ LQ 0LQXWHQ ± ]% PHLQW HLQH =HLW]RQH GLH I QI 6WXQGHQ XQG 0LQXWHQ YRU 87& OLHJW (V JLEW HLQLJH ZHQLJH VROFKHU =RQHQ 7=5 'LH =HLW]RQHQUHJLRQ ª86(DVWHUQ LVW ]% GLH 5HJLRQ LQ GHU (67 (DVWHUQ 6WDQGDUG 7LPH XQG ('7 (DVWHUQ 'D\OLJKW 7LPH JHOWHQ ++ RGHU ++ 'LH 6WXQGH GHV 7DJHV YRQ ELV ++ GLHQW QXU GHU $XVJDEH ++ 'LH 6WXQGH GHV 7DJHV YRQ ELV 0, 'HU 0LQXWHQWHLO GHV 'DWXPV8KU]HLWZHUWV YRQ ELV 66 'HU 6HNXQGHQWHLO GHV 'DWXPV8KU]HLWZHUWV YRQ ELV 66666 'LH =DKO GHU 6HNXQGHQ GLH VHLW 0LWWHUQDFKW GHU =HLWNRPSRQHQWH YHUJDQJHQ VLQG =XOlVVLJH :HUWH VLQG ELV ZREHL MHGH 6WXQGH 6HNXQGHQ KDW )) 'LH 6HNXQGHQEUXFKWHLOH *LOW QXU LQ 9HUELQGXQJ PLW 7,0(67$03:HUWHQ 9HU ZHQGHQ 6LH LPPHU )) ]ZHL )V HJDO ZLH YLHOH 'H]LPDOVWHOOHQ 6LH P FKWHQ -HGH DQGHUH $Q]DKO YRQ )V LVW XQJ OWLJ ; 'DV ORNDOH =HLFKHQ I U 5DGL[,P DPHULNDQLVFKHQ (QJOLVFK LVW HV HLQ 3XQNW 'LHVHV (OHPHQW N QQHQ 6LH YRU )) VHW]HQ GDPLW 6HNXQGHQEUXFKWHLOH ULFKWLJ LQWHUSUHWLHUW XQG GDUJHVWHOOW ZHUGHQ 7+ 6XIIL[ GDV HLQH =DKO LQ HLQH 2UGLQDO]DKO NRQYHUWLHUW ZLUG ]% ]X WK XQG ]X VW 'LHVHV (OHPHQW NDQQ DP (QGH MHGHV (OHPHQWV HUVFKHLQHQ GDV HLQH =DKO ]XP (UJHEQLV KDW %HLVSLHOVZHLVH KDW ª''WK0RQ<<<< DOV $XVJDEH ªWK1RY 'HU 5 FNJDEHZHUW LVW LPPHU LQ HQJOLVFK HJDO LQ ZHOFKHU 6SUDFKH GLH 'DWXPVDQJDEH YRUOLHJW 63 6XIIL[ GDV HLQH =DKO LQ LKU DXVJHVFKULHEHQHV )RUPDW NRQYHUWLHUW 'LHVHV (OHPHQW NDQQ DP (QGH MHGHV (OHPHQWV HUVFKHLQHQ GDV HLQH =DKO ]XP (UJHEQLV KDW %HL VSLHOVZHLVH I KUW HLQH 0DVNH ZLH ª''WK0RQ<\\\VS ]X HLQHU $XVJDEH ZLH ªWK1RY2QH 7KRXVDQG 1LQH +XQGUHG 6L[W\2QH 'HU 5 FNJDEHZHUW LVW LPPHU LQ HQJOLVFK HJDO LQ ZHOFKHU 6SUDFKH GLH 'DWXPVDQJDEH YRUOLHJW %HDFK WHQ 6LH GD <\\\ JHPLVFKWH *UR XQG.OHLQVFKUHLEXQJ HUJLEW 637+ 6XIIL[ GDV HLQH =DKO LQ LKU DXVJHVFKULHEHQHV XQG LKU 2UGLQDOIRUPDW NRQYHUWLHUW ZLUG ]% ]X )257+ XQG ]X ),567 'LHVHV (OHPHQW NDQQ DP (QGH MHGHV (OH PHQWV HUVFKHLQHQ GDV HLQH =DKO ]XP (UJHEQLV KDW %HLVSLHOVZHLVH I KUW HLQH 0DVNH ZLH ª'GVSWK 0RQ <\\\VS ]X HLQHU $XVJDEH ZLH ª)LIWHHQWK 1RY 2QH 7KRXVDQG 1LQH +XQGUHG 6L[W\2QH 'HU 5 FNJDEHZHUW LVW LPPHU LQ HQJOLVFK HJDO LQ ZHOFKHU 6SUDFKH GLH 'DWXPVDQJDEH YRUOLHJW ); (OHPHQW GDV HLQHQ H[DNWHQ 0XVWHUYHUJOHLFK ]ZLVFKHQ 'DWXP XQG )RUPDWPRGHOO HUIRUGHUW ); VWHKW I U )RUPDW H;DFW 6LHKH ª'DV (OHPHQW ); ZHLWHU XQWHQ LQ GLHVHP.DSLWHO )0 (OHPHQW GDV GLH 8QWHUGU FNXQJ YRQ /HHU]HLFKHQ LQ GHU $XVJDEH GHU.RQYHUWLH UXQJ HLQ RGHU DXVVFKDOWHW )0 VWHKW I U )LOO 0RGH 6LHKH ª'DV (OHPHQW )0 ZHLWHU XQWHQ LQ GLHVHP.DSLWHO Datums- und Zeitstempel-Konvertierungen 287

Tabelle 10-1: Elemente von Datumsformatmodellen (Fortsetzung) Element 2WKHU WH[W Beschreibung $QGHUH,QWHUSXQNWLRQV]HLFKHQ ZLH.RPPD RGHU 6FKUlJVWULFK RGHU %LQGH VWULFK ZHUGHQ LQ GLH IRUPDWLHUWH $XVJDEH GHU.RQYHUWLHUXQJ EHUQRPPHQ 6LH N QQHQ DXFK 7H[W LQ GRSSHOWHQ $QI KUXQJV]HLFKHQ ª HLQJHEHQ 'LHVHU ZLUG GDQQ LP NRQYHUWLHUWHQ :HUW VR ZLHGHUJHJHEHQ ZLH HU ZDU 6LHKH %HLVSLHOH XQWHU ª72B&+$5 Immer wenn ein Datumsformat einen ausgeschriebenen Wert liefert (also Worte statt Zahlen, wie in MONTH, MON, DAY, DY, AM und PM), entscheiden entweder die NLS-Parameter NLS_DATE_LANGUAGE und NLS_LANGUAGE oder der optionale Sprachparameter, den Sie sowohl an TO_ CHAR als auch an TO_DATE übergeben können, in welcher Sprache diese Worte ausgeschrieben werden. Hier sehen Sie einige Beispiele für Datumsformatmasken, die sich aus den oben angegebenen Formatelementen zusammensetzen: 'Month DD, YYYY' 'MM/DD/YY Day A.M.' 'Year Month Day HH24:MI:SS' 'J' 'SSSSS-YYYY-MM-DD' '"Ein schoener Sommermorgen am" DDth" Tag des "Month' Weitere Beispiele für die Verwendung und Ausgabewerte dieser Masken finden Sie unter den Funktionen TO_CHAR und TO_DATE. ISO-Daten Die Elemente IYY und IW stellen das Jahr und die Woche laut ISO (International Standards Organization) dar. Der ISO-Kalender ist ein gutes Beispiel für das, was geschieht, wenn Sie ein Komitee auf einen Entwurf loslassen. Der erste Tag des ISO-Jahres ist immer ein Montag und wird nach folgenden Regeln festgelegt: Fällt der 1. Januar auf einen Montag, beginnt dann das ISO-Jahr. Fällt der 1. Januar auf einen Dienstag bis Donnerstag, beginnt das ISO-Jahr am Montag davor. Fällt der 1. Januar auf einen Freitag bis Sonntag, beginnt das ISO-Jahr am Montag danach. Diese Regeln haben einige Absonderlichkeiten zur Folge. So gilt z.b. der 31.12.2001 als erster Tag des ISO-Jahres 2002, und wenn Sie dieses Datum im Format IYYY darstellen, erhalten Sie exakt den 31.12.2002. ISO-Wochen beginnen immer montags und werden vom ersten Montag des ISO-Jahres an numeriert. 288 Kapitel 10: Datumswerte und Zeitstempel

Strings in Datumswerte konvertieren Wenn Sie mit Datumswerten arbeiten, müssen Sie zuerst das Datum (und die Uhrzeit) in die Datums- und Uhrzeit-Variablen von PL/SQL bekommen. Dazu konvertieren Sie die Werte aus dem String-Format in das interne Format von Oracle. Solche Konvertierungen können Sie implizit vornehmen, indem Sie einen String einer Datums-/Uhrzeit-Variablen zuweisen, oder explizit, indem Sie eine Built-in-Konvertierungsfunktion von Oracle benutzen. Die implizite Konvertierung ist riskant, und wir raten davon ab. Im Folgenden sehen Sie ein Beispiel für eine implizite Konvertierung eines Strings in eine DATE-Variable: DECLARE birthdate DATE; birthdate := '15-Nov-1961'; Eine solche Konvertierung stützt sich auf den Wert von NLS_DATE_FORMAT und funktioniert so lange, bis Ihr DBA beschließt, diese Einstellung zu ändern. In demselben Moment geht all Ihr datumsbezogener Code den Bach herunter. Das kann auch geschehen, wenn Sie NLS_DATE_FORMAT auf der Sitzungsebene ändern. Anstatt sich auf implizite Konvertierungen und NLS_DATE_FORMAT zu verlassen, ist es viel sicherer, Datumswerte explizit mit einer der Built-in-Funktionen zu konvertieren. Diese Funktionen machen nicht nur im Code deutlich, daß hier eine Typkonvertierung vorliegt, sondern ermöglichen Ihnen auch die Angabe des genauen Datums- und Uhrzeitformats. In den nächsten Abschnitten werden Konvertierungen mit Built-in-Funktionen genauer beschrieben. Sie finden darin auch einen Abschnitt über ein neues Feature von Oracle9i, nämlich das Zeitstempel-Literal. Ein Zeitstempel-Literal ist ein ANSI/ISO-Standardtextformat, das für Datums- und Uhrzeitwerte eingesetzt wird. Es bietet Ihnen noch eine Möglichkeit mehr zur Konvertierung von Text in Datums- und Uhrzeitwerte. TO_DATE Die Funktion TO_DATE konvertiert einen String in einen echten DATE-Datentyp. Ihre Spezifikation ist überladen, um sowohl mit String- als auch mit Zahleneingabe arbeiten zu können: FUNCTION TO_DATE (string_in IN VARCHAR2 [, format_maske IN VARCHAR2 [, nls_sprache IN VARCHAR2 ]] ) RETURN DATE; FUNCTION TO_DATE (number_in IN NUMBER Datums- und Zeitstempel-Konvertierungen 289

[, format_maske IN VARCHAR2 [, nls_sprache IN VARCHAR2 ]]) RETURN DATE; Die zweite Version von TO_DATE kann mit der Formatmaske J für Julianisches Datum benutzt werden. Das Julianische Datum bezeichnet die Anzahl der Tage, die seit dem 1.Januar 4712 v.chr. vergangen sind. Nur in dieser Anwendung kann TO_DATE als erster Parameter eine Zahl übergeben werden. Für alle anderen Fälle gelten folgende Parameter: string_in Zu konvertierende String-Variable, Literal, benannte Konstante oder Ausdruck, je nachdem, was konvertiert werden soll. format_maske Die Formatmaske, anhand deren TO_DATE den String konvertieren wird. Entspricht per Voreinstellung dem Wert von NLS_DATE_FORMAT. nls_sprache Gibt optional an, in welcher Sprache die Namen und Abkürzungen von Monaten und Tagen im String interpretiert werden sollen. Hat folgendes Format: 'NLS_DATE_LANGUAGE=sprache' Hierbei ist sprache eine Sprache, die Ihrer Datenbankinstanz bekannt ist. Normalerweise können Sie aus Ihrer Installationsanleitung ersehen, welche Sprachen akzeptiert werden. Das folgende Beispiel konvertiert den String»123188«in ein Datum: TO_DATE ('123188', 'MMDDYY') Im nächsten Beispiel wird mit dem Parameter nls_sprache angegeben, daß der Monatsname in spanisch angegeben werden soll: TO_DATE ('Abril 12 1991', 'Month DD YYYY', 'NLS_DATE_LANGUAGE=Spanish') Irgendwelche Oracle-Fehler zwischen ORA-01800 und ORA-01899 stehen immer mit der internen Datumsfunktion von Oracle in Zusammenhang und können aufgrund von Fehlern in der Datumskonvertierung ausgelöst werden. Sie können noch mehr Nuancen der Datenkonvertierungsregeln finden, wenn Sie die verschiedenen Fehlermeldungen durchgehen und in den zugehörigen Dokumentationen die Fehlerursachen nachschlagen. Einige dieser Regeln sind: Ein Datums-Literal, das an TO_CHAR zur Konvertierung in ein Datum übergeben wurde, darf nicht länger als 220 Zeichen sein. Sie dürfen in ein und derselben Formatmaske nicht zugleich ein Julianisches Datumselement (J) und ein Jahrestagselement (DDD) haben. Sie dürfen für ein- und denselben Datums-/Uhrzeitbestandteil nicht mehrere Elemente in der Maske angeben. So ist z.b. die Maske YYYY-YYY-DD-MM unzulässig, da sie zwei Jahreselemente enthält: YYYY und YYY. 290 Kapitel 10: Datumswerte und Zeitstempel

Sie dürfen in ein und derselben Formatmaske nicht zugleich das 24-Stunden-Format (HH24) und ein Vor-/Nachmittagselement (z.b. AM) haben. Die Familie der TO_TIMESTAMP-Funktionen Es gibt drei TIMESTAMP-Datentypen, und zu jedem gehört eine Konvertierungsfunktion. Wenn Sie einen String in einen TIMESTAMP-Wert konvertieren, verwenden Sie dazu die Funktion, die zu Ihrem Zieldatentyp paßt: TO_TIMESTAMP Konvertiert einen String in einen Wert vom Typ TIMESTAMP. TO_TIMESTAMP_TZ Konvertiert einen String in einen Wert vom Typ TO_TIMESTAMP_TZ. TO_TIMESTAMP_LTZ Konvertiert einen String in einen Wert vom Typ TO_TIMESTAMP_LTZ. Die Spezifikationen für diese drei Funktionen folgen alle demselben Muster: Im Gegensatz zu TO_DATE ist keine der TO_TIMESTAMP-Funktionen überladen, um auch eine NUMBER als Datums-/Uhrzeitwert zu akzeptieren. Wir wollen uns nun die Spezifikation von TO_TIMESTAMP als repräsentatives Beispiel anschauen: FUNCTION TO_TIMESTAMP ( string_in IN VARCHAR2 [, format_maske IN VARCHAR2 [, nls_sprache IN VARCHAR2 ]] ) RETURN DATE; Die Parameter sind denen von TO_DATE ganz ähnlich: string_in Ist ein String, der einen Datums-/Uhrzeitwert darstellt. format_mask Ist ein String von Elementen aus Tabelle 10-1, der das Format des Eingabe-Strings beschreibt. Die Formatmaske entspricht per Voreinstellung einem der folgenden NLS-Parameter: NLS_TIMESTAMP_FORMAT Für TO_TIMESTAMP und TO_TIMESTAMP_LTZ. NLS_TIMESTAMP_TZ_FORMAT Für TO_TIMESTAMP_TZ. nls_sprache Optionale Angabe der Sprache, in der die Namen und Abkürzungen von Monaten und Tagen in dem String interpretiert werden sollen. Datums- und Zeitstempel-Konvertierungen 291