SQL Server: datetime und datetime2 in Access

Wir verknüpfen eine Tabelle des SQL Servers mit Access, öffnen den Direktbereich und lesen mit DLookup ein Datum aus der ersten Zeile. Bei einem Feld liefert der Aufruf den Wert, bei einem anderen scheitert derselbe Aufruf mit der Meldung Typen unverträglich. Beide Felder enthalten ein Datum mit Uhrzeit. Der Unterschied liegt im Datentyp: Der SQL Server kennt mehrere Datentypen für Datum und Uhrzeit, und Access bindet sie je nach Einstellung unterschiedlich ein. Welche Konstellationen ohne Probleme laufen, welche Fehler auftreten und wie wir die Anbindung einrichten, zeigt dieser Beitrag.

Beispieldatenbank

Die Beispiele dieses Beitrags laufen gegen die SQL Server-Datenbank DateTimeTest. Das Skript DateTimeTest.sql legt sie auf einer lokalen Instanz an, in unserem Fall .SQLEXPRESS.

Es löscht eine vorhandene Datenbank gleichen Namens und erzeugt sie neu.

Die Datenbank enthält zwei Tabellen und eine Sicht. Die Tabelle tblZeitstempel hat neben ZeitstempelID und Bezeichnung je eine Spalte für jeden Datentyp, den wir untersuchen wollen:

  • ZDate: Datentyp date
  • ZSmallDateTime: Datentyp smalldatetime
  • ZDateTime: Datentyp datetime
  • ZDateTime2_0: Datentyp datetime2(0)
  • ZDateTime2_3: Datentyp datetime2(3)
  • ZDateTime2_7: Datentyp datetime2(7)

Sie enthält drei Zeilen. Die erste enthält den 2. Oktober 2026 um 8:30:15 Uhr. Bei ZDate fehlt die Uhrzeit, ZSmallDateTime steht auf 8:30:00, weil der Typ nur Minuten speichert. ZDateTime und ZDateTime2_3 tragen die Sekundenbruchteile .123, ZDateTime2_7 die Sekundenbruchteile .1234567.

Die zweite Zeile hat den 15. September 2026 um 11:30:05 Uhr, die dritte den 1. Januar 2026 ohne Uhrzeit. Das Ergebnis in SQL Server Management Studio steht im Ergebnisraster (siehe Bild 1).

Die Tabelle tblZeitstempel im Ergebnisraster von SSMS

Bild 1: Die Tabelle tblZeitstempel im Ergebnisraster von SSMS

Die Tabelle tblSchreibtest hat die vier Spalten ZDateTime, ZDateTime2_0, ZDateTime2_3 und ZDateTime2_7. Wir verwenden sie für die Schreibversuche. Die Sicht vwZeitstempel liefert dieselben Daten wie tblZeitstempel, wandelt aber die drei datetime2-Spalten mit CAST in datetime um.

Das Frontend SQLServer_DateTimeUndDateTime2InAccess.accdb enthält die Tabellen als Verknüpfungen.

Die Verknüpfungen mit dem Zusatz Normal im Namen verwenden die Einstellung, die wir weiter unten als Konstellation 3 beschreiben, die übrigen die Standardeinstellung. Die VBA-Prozeduren stehen im Modul mdlDateTimeBeispiele, ein Testmodul prüft die Aussagen dieses Beitrags.

Datums- und Zeittypen im SQL Server

Für Datum und Uhrzeit bietet der SQL Server vier Datentypen an, die wir hier betrachten:

  • date: nur das Datum, vom 1. Januar 0001 bis zum 31. Dezember 9999
  • smalldatetime: Datum und Uhrzeit auf die Minute genau, vom 1. Januar 1900 bis zum 6. Juni 2079
  • datetime: Datum und Uhrzeit, vom 1. Januar 1753 bis zum 31. Dezember 9999, in Schritten von etwa 3 Millisekunden
  • datetime2(n): Datum und Uhrzeit, vom 1. Januar 0001 bis zum 31. Dezember 9999, mit n Nachkommastellen für die Sekunden, wobei n zwischen 0 und 7 liegt

Den Typ datetime gibt es seit den frühen Versionen des SQL Servers, datetime2 ist neuer. Er hat einen größeren Bereich, eine höhere Genauigkeit und entspricht dem SQL-Standard. Die Dokumentation von Microsoft zu datetime empfiehlt für neue Arbeiten die Typen date, time, datetime2 und datetimeoffset.

Für Access sieht das anders aus. Hier kommt es darauf an, wie Access die Typen einbindet, wenn wir eine Tabelle verknüpfen.

Wie Access die Typen einbindet

Access kennt für Datum und Uhrzeit zwei Felddatentypen. Datum/Uhrzeit speichert den Wert intern als Zahl vom Typ Double.

Der Teil vor dem Komma ist die Zahl der Tage seit dem 30. Dezember 1899, der Teil hinter dem Komma der Anteil des Tages. Daneben gibt es seit Access 2021 und Access in Microsoft 365 den Typ Datum/Uhrzeit, erweitert, der Sekundenbruchteile mit bis zu sieben Stellen speichert. Er ist nicht mit älteren Access-Versionen kompatibel.

Der erweiterte Typ wurde vor allem für die Anbindung des SQL Servers eingeführt. Er bildet den Typ datetime2 nach. Ob Access ihn beim Verknüpfen verwendet, steuert eine Option der aktuellen Datenbank. Wir finden sie in den Access-Optionen unter Aktuelle Datenbank im Bereich Datentypunterstützungs-Optionen, sie heißt Unterstützung des erweiterten Datentyps “Date Time Extended” (DateTime2) für mit ODBC verknüpfte/importierte Tabellen (siehe Bild 2).

Die Option für datetime2 in den Access-Optionen

Bild 2: Die Option für datetime2 in den Access-Optionen

Die Option wirkt beim Verknüpfen oder Importieren. Eine bestehende Verknüpfung ändert sich nicht, wenn wir die Option später umschalten, bis wir sie neu verknüpfen. In unseren Tests verhielt sich eine neue Datenbank, in der wir die Option nie geändert hatten, wie bei eingeschalteter Option.

Was daraus folgt, sehen wir an den Verknüpfungen mit DAO. Die Funktion FeldTypen liefert zu jedem Feld einer Tabelle den DAO-Datentyp (siehe Listing 1). Der Wert 8 steht für Datum/Uhrzeit, der Wert 26 für Datum/Uhrzeit, erweitert.

Public Function FeldTypen(strTabelle As String) As String
    Dim db As DAO.Database
    Dim fld As DAO.Field
    Set db = CurrentDb
    For Each fld In db.TableDefs(strTabelle).Fields
        FeldTypen = FeldTypen & fld.Name & "=" & fld.Type & " "
    Next fld
    FeldTypen = Trim(FeldTypen)
End Function

Listing 1: FeldTypen liefert die Felder einer Tabelle mit dem DAO-Datentyp

Für die Standardverknüpfung dbo_tblZeitstempel erhalten wir im Direktbereich diese Zeile, hier zur besseren Lesbarkeit umgebrochen:

FeldTypen("dbo_tblZeitstempel")
ZeitstempelID=4 Bezeichnung=10 ZDate=8
ZSmallDateTime=8 ZDateTime=8
ZDateTime2_0=26 ZDateTime2_3=26
ZDateTime2_7=26

Die Typen date, smalldatetime und datetime kommen als Datum/Uhrzeit an, alle drei datetime2-Felder als Datum/Uhrzeit, erweitert.

Die Tabelle im Entwurf zeigt denselben Unterschied (siehe Bild 3).

Die Felder der verknüpften Tabelle im Entwurf mit den Datentypen

Bild 3: Die Felder der verknüpften Tabelle im Entwurf mit den Datentypen

Damit ergeben sich drei Konstellationen, die wir nacheinander durchgehen: datetime, smalldatetime und date in Access, datetime2 bei eingeschalteter Option und datetime2 bei ausgeschalteter Option.

Konstellation 1: datetime, smalldatetime und date

Die Typen date, smalldatetime und datetime verhalten sich in Access wie ein normales Datum/Uhrzeit-Feld. Das gilt in unseren Tests unabhängig von der Option. Ein Aufruf von DLookup auf das Feld ZDateTime liefert den Wert wie bei einer Access-Tabelle:

DLookup("ZDateTime","dbo_tblZeitstempel")
02.10.2026 08:30:15

Der Wert in der Tabelle lautet 8:30:15.123 Uhr. Access zeigt die Sekundenbruchteile nicht an. Format, CDate, Nz und DateAdd arbeiten mit dem Feld wie bei einer Access-Tabelle.

Bei ZDate und ZSmallDateTime gelten in unseren Tests dieselben Ergebnisse. Der Aufruf ohne Kriterium liest den ersten Datensatz in der Reihenfolge der Tabelle.

Wer in einer Datenbank, auf die vor allem Access zugreift, keine Sekundenbruchteile braucht, kommt mit diesen Typen ohne Einstellungen aus.

Die Einschränkungen des Typs datetime sind die Schritte von etwa 3 Millisekunden und der Bereich ab dem Jahr 1753.

Konstellation 2: datetime2 bei eingeschalteter Option

Bei eingeschalteter Option, in unseren Tests die Standardeinstellung, kommt datetime2 als Datum/Uhrzeit, erweitert an. Hier treten die Fehler auf. Wir gehen sie der Reihe nach durch, beginnend mit der Funktion aus der Einleitung.

Der Aufruf von DLookup auf ein datetime2-Feld liefert einen Fehler:

DLookup("ZDateTime2_3","dbo_tblZeitstempel")

Es erscheint die Meldung Laufzeitfehler 13: Typen unverträglich (siehe Bild 4). Der Aufruf liefert einen Wert, den Access nicht ausgeben kann. Auch die Zuweisung an eine Date-Variable oder an eine String-Variable scheitert mit dem Fehler 13. Dasselbe gilt in unseren Tests für DMax, DMin und DFirst.

Der Aufruf von DLookup auf ein datetime2-Feld meldet Typen unverträglich

Bild 4: Der Aufruf von DLookup auf ein datetime2-Feld meldet Typen unverträglich

Eine Verwendung der Domänenfunktionen ist trotzdem möglich. Die Funktion DCount zählt Datensätze auch dann, wenn das Kriterium ein datetime2-Feld enthält. Der folgende Aufruf zählt die Zeilen vom 2. Oktober 2026 und liefert 1:

DCount("*","dbo_tblZeitstempel", _
  "ZDateTime2_3>=#10/2/2026# AND " & _
  "ZDateTime2_3<#10/3/2026#")

Eine Datumsbedingung auf einem datetime2-Feld funktioniert also, nur der Wert des Feldes lässt sich nicht lesen.

Recordset und CDate bei datetime2

Mit einem Recordset lässt sich der Feldwert lesen. Er kommt allerdings als Text an. Die folgende Abfrage liest das Feld ZDateTime2_7 der ersten Zeile:

Set rst = CurrentDb.OpenRecordset( _
  "SELECT ZDateTime2_7 " & _
  "FROM dbo_tblZeitstempel " & _
  "WHERE ZeitstempelID=1", _
  dbOpenSnapshot, dbSeeChanges)
TypeName(rst.Fields(0).Value)
String
rst.Fields(0).Value
10/02/2026 08:30:15.1234567

Der Text hat in unseren Tests mit deutschen Regionaleinstellungen das amerikanische Format Monat, Tag, Jahr, dazu sieben Nachkommastellen für die Sekunden.

Gemeint ist hier der 2. Oktober 2026. Die Funktion CDate kann diesen Text mit den Nachkommastellen nicht in ein Datum umwandeln und löst den Fehler 13 aus.

Wer die Nachkommastellen mit Left abschneidet, bekommt einen Wert, aber einen falschen. CDate(Left(Text, 19)) liest bei deutschen Regionaleinstellungen den Text 10/02/2026 08:30:15 als 10. Februar 2026 statt als 2. Oktober 2026 (siehe Bild 5). Access gibt dazu keine Meldung aus.

CDate liest den Text des Feldes mit vertauschtem Tag und Monat

Bild 5: CDate liest den Text des Feldes mit vertauschtem Tag und Monat

Beim zweiten Datum der Tabelle, dem 15. September, liefert derselbe Aufruf das richtige Datum, weil es keinen 15. Monat gibt und CDate den Text dann als Monat und Tag liest.

Die Vertauschung tritt deshalb bei Tagen bis zum zwölften eines Monats auf, außer wenn Tag und Monat übereinstimmen. Access meldet dazu nichts.

Abfragen auf datetime2-Felder

Access, SQL und Cloud Automation

Unser exklusives Angebot für Dich!

VB-Entwickler
12,50 € im Monat*

(Gilt für den Abschluss eines Jahres-Abonnements.)

Hier geht’s weiter →

Die ersten 4 Wochen kostenlos testen – voller Zugriff auf alle Artikel, vollständigen Code und Beispieldatenbanken. Kein Risiko: Wenn es nicht passt, kündigst Du einfach innerhalb der ersten vier Wochen.

PayPal VISA Mastercard SEPA
Kostenlos & unverbindlich

Oder hast Du eine konkrete Frage zu Deiner eigenen Access-Anwendung?

Vielleicht stellt Deine Anwendung Dich vor eine Herausforderung, zu der Du bisher keine Lösung findest. Schlechte Performance, kein ausreichender Zugriffsschutz, Du bist unsicher über Dein Datenmodell oder Dein Code liefert unerklärliche Fehler?

In unserem kostenlosen Access-Audit schaut sich André Minhorst persönlich gemeinsam mit Dir Deine Lösung per Zoom an – und zeigt Dir, wo Datenmodell, VBA-Code, Ergonomie und Sicherheit Optimierungspotenzial bieten.

Jetzt kostenloses Access-Audit anfordern →