Discussion:
Datum von VB nach Access
(zu alt für eine Antwort)
Coder2001
2007-04-17 08:22:03 UTC
Permalink
Hallo allerseits,

wenn ich ein vollständiges Datum an eine Access-Parameterabfrage übergebe,
wird der Monat und Tag vertauscht!

Codeausschnitt (Aufruf einer Acessabfrage mit ADO):
dtmDate = now ' Datum ist 06.01.2007 12:01:23
cmd.Execute lngRecordsAffectes, dtmDate, adCmdUnknown Or adExecuteNoRecords


=> in VB:
06.01.2007 12:01:23

=> in Access:
01.06.2007 12:01:23

Das Datum wird korrekt, wenn der Wert für den Tag größer als 12 ist.

Kann jemand dieses Verhalten nachvollziehen?

Softwarekonfiguration:
VB6 SP6 deutsch
XP SP2 englisch mit deutscher Oberfläche

PS
Einen Workaround habe ich zwar gefunden: Format$(Now, "yyyy-mm-dd hh:mm:ss",
aber trotzdem ungutes Gefühl
Peter Fleischer
2007-04-17 08:54:11 UTC
Permalink
Post by Coder2001
wenn ich ein vollständiges Datum an eine Access-Parameterabfrage
übergebe, wird der Monat und Tag vertauscht!
Du übergibst bestimmt nicht als Datum, sondern als Zeichenkette.
Post by Coder2001
dtmDate = now ' Datum ist 06.01.2007 12:01:23
cmd.Execute lngRecordsAffectes, dtmDate, adCmdUnknown Or
adExecuteNoRecords
06.01.2007 12:01:23
deutsch oder englisch?
Post by Coder2001
01.06.2007 12:01:23
logisch, da invariant (=angelsächsisch) übergeben wurde: Monat/Tag/Jahr
Post by Coder2001
Das Datum wird korrekt, wenn der Wert für den Tag größer als 12 ist.
Weil sich dann der String nicht in ein Datum konvertieren lässt und versucht
wird, irgendeine andere Umwandlung zum Erfolg zu führen.
Post by Coder2001
Kann jemand dieses Verhalten nachvollziehen?
Ja, wenn ich falsch programmiere.
Post by Coder2001
VB6 SP6 deutsch
XP SP2 englisch mit deutscher Oberfläche
PS
Einen Workaround habe ich zwar gefunden: Format$(Now, "yyyy-mm-dd
hh:mm:ss", aber trotzdem ungutes Gefühl
Nimm Parameter-Objekte und übergib keine Zeichenketten, sondern weise dem
Parameter-Objekt den Wert der Datumsvariablen zu.

Du erhöhst Deine Chance, dass Deine Frage überhaupt gelesen und qualifiziert
und schnell beantwortet wird, wenn Du Deinen Realnamen im Absender
einstellst (Vor- und Zuname).
--
Viele Grüße

Peter
Coder2001
2007-04-17 09:44:01 UTC
Permalink
Zunächst Entschuldigung, dass ich in der Hektik meinen Namen vergessen habe,

so ganz richtig habe ich Dich nicht verstanden: ich übergebe doch einen
Datumswert (dtmDate ist eine Variable vom Typ "Date"). In "Execute
RecordsAffected, Parameters, Options" übergebe ich als Parameters eben diese
Datumsvariable. Im übrigen hast Du natürlich recht: Parameter-Objekte wären
besser.

Gruß
Ulrich Boehringer
Post by Peter Fleischer
Post by Coder2001
wenn ich ein vollständiges Datum an eine Access-Parameterabfrage
übergebe, wird der Monat und Tag vertauscht!
Du übergibst bestimmt nicht als Datum, sondern als Zeichenkette.
Post by Coder2001
dtmDate = now ' Datum ist 06.01.2007 12:01:23
cmd.Execute lngRecordsAffectes, dtmDate, adCmdUnknown Or
adExecuteNoRecords
06.01.2007 12:01:23
deutsch oder englisch?
Post by Coder2001
01.06.2007 12:01:23
logisch, da invariant (=angelsächsisch) übergeben wurde: Monat/Tag/Jahr
Post by Coder2001
Das Datum wird korrekt, wenn der Wert für den Tag größer als 12 ist.
Weil sich dann der String nicht in ein Datum konvertieren lässt und versucht
wird, irgendeine andere Umwandlung zum Erfolg zu führen.
Post by Coder2001
Kann jemand dieses Verhalten nachvollziehen?
Ja, wenn ich falsch programmiere.
Post by Coder2001
VB6 SP6 deutsch
XP SP2 englisch mit deutscher Oberfläche
PS
Einen Workaround habe ich zwar gefunden: Format$(Now, "yyyy-mm-dd
hh:mm:ss", aber trotzdem ungutes Gefühl
Nimm Parameter-Objekte und übergib keine Zeichenketten, sondern weise dem
Parameter-Objekt den Wert der Datumsvariablen zu.
Du erhöhst Deine Chance, dass Deine Frage überhaupt gelesen und qualifiziert
und schnell beantwortet wird, wenn Du Deinen Realnamen im Absender
einstellst (Vor- und Zuname).
--
Viele Grüße
Peter
Peter Fleischer
2007-04-17 14:26:31 UTC
Permalink
Post by Coder2001
Zunächst Entschuldigung, dass ich in der Hektik meinen Namen
vergessen habe,
ja, und?
Post by Coder2001
so ganz richtig habe ich Dich nicht verstanden: ich übergebe doch
einen Datumswert (dtmDate ist eine Variable vom Typ "Date").
s. Hilfe:

Parameters
An optional Variant array of parameter values passed with an SQL statement.
Post by Coder2001
In
"Execute RecordsAffected, Parameters, Options" übergebe ich als
Parameters eben diese Datumsvariable.
s. Hilfe: als Variant, nicht als Date!
Post by Coder2001
Im übrigen hast Du natürlich
recht: Parameter-Objekte wären besser.
Dann nimm sie doch.
--
Viele Grüße

Peter
Ulrich Boehringer
2007-04-19 09:36:03 UTC
Permalink
Leider ist Deine Antwort nicht sehr hilfreich: wenn ich einem Variant einen
Wert vom Typ 'Date' übergebe, dann enthält der Variant den Datentyp 'Date'.
Ich übergebe das Datum nicht als String, sondern ich weise unmittelbar
miitels 'Now' das aktuelle Systemdatum zu. Wo bitte soll VB an dieser Stelle
eine Umwandlung durchführen?

Ich arbeite in einer Firmenumgebung, und kann meinen Code leider nicht so
auf die Schnelle auf Parameterobjekte umstellen.

Gruß
Ulrich Boehringer
Post by Peter Fleischer
Post by Coder2001
Zunächst Entschuldigung, dass ich in der Hektik meinen Namen vergessen habe,
ja, und?
Post by Coder2001
so ganz richtig habe ich Dich nicht verstanden: ich übergebe doch
einen Datumswert (dtmDate ist eine Variable vom Typ "Date").
Parameters
An optional Variant array of parameter values passed with an SQL statement.
Post by Coder2001
In
"Execute RecordsAffected, Parameters, Options" übergebe ich als
Parameters eben diese Datumsvariable.
s. Hilfe: als Variant, nicht als Date!
Post by Coder2001
Im übrigen hast Du natürlich
recht: Parameter-Objekte wären besser.
Dann nimm sie doch.
--
Viele Grüße
Peter
rainer b. kranok
2007-04-19 16:13:25 UTC
Permalink
Now() liefert eine Variant, und die Umwandlung von Variants in Zielformate
ist insbesondere bei Datumswerten, na sagen wir mal knifflig, weil da z.B.
auch noch die Ländereinstellung mit reinspielt.

Das ist einer der Gründe, warum ich nie Variants sich selbst überlasse,
sondern sie vor Weiterverarbeitung selbst in ein passendes Format umwandle.

Wenn Dir Format$() nicht paßt, dann verwende CDate(Now). Das liefert dem
Compiler definitiv einen Wert vom Typ Date.

Im übrigen ist Format() und Format$() nicht dasselbe, auch wenn dank des
toleranten Compilers meistens dasselbe rauskommt.
Peter Fleischer
2007-04-19 17:04:29 UTC
Permalink
Post by Ulrich Boehringer
Leider ist Deine Antwort nicht sehr hilfreich: wenn ich einem Variant
einen Wert vom Typ 'Date' übergebe, dann enthält der Variant den
Datentyp 'Date'. Ich übergebe das Datum nicht als String, sondern ich
weise unmittelbar miitels 'Now' das aktuelle Systemdatum zu. Wo bitte
soll VB an dieser Stelle eine Umwandlung durchführen?
Hi Ulrich,
beim Serialisieren der Parameter wird dein Variant entsprechend den lokalen
Einstellungen in einen String umgewandelt. Access wandelt den serialisierten
String invariant zu einem Datumswert zurück.
Post by Ulrich Boehringer
Ich arbeite in einer Firmenumgebung, und kann meinen Code leider
nicht so auf die Schnelle auf Parameterobjekte umstellen.
Wenn ein Programm fehlerhaft ist und du es nicht ändern darfst, dann kann
dir bestimmt niemand helfen.

Hier mal eine Demo mit einer vorhandenen Tabelle TempTab, die eine Spalte
"EinDatum" vom Typ Datum hat:

Private Sub Command1_Click()
Dim cn As New ADODB.Connection
cn.ConnectionString = "provider=microsoft.jet.oledb.4.0;" & _
"data source=c:\me\vb6\test2k.mdb"
cn.Open
Dim cmd As New ADODB.Command
Set cmd.ActiveConnection = cn
cmd.CommandType = adCmdText
'
On Error Resume Next
cmd.CommandText = "DROP VIEW test"
cmd.Execute
On Error GoTo 0
cmd.CommandText = "CREATE PROC test AS INSERT INTO TempTab(EinDatum)
VALUES(?)"
cmd.Execute
'
Dim i As Integer
Dim d As Variant
d = CDate("1.2.03")
'
cmd.CommandText = "test"
cmd.CommandType = adCmdStoredProc
cmd.Execute i, d, adCmdUnknown Or adExecuteNoRecords
'
Dim par1 As New ADODB.Parameter
par1.Type = adDate
par1.Value = d
cmd.CommandText = "test"
cmd.Parameters.Append par1
cmd.CommandType = adCmdStoredProc
cmd.Execute i
'
End Sub
Joachim Heisterfeld
2007-04-19 23:34:14 UTC
Permalink
Hallo Peter,

ich hasse Parameterobjekte, weil man eben nicht mehr einfach einen
SQL-String übergeben kann.
Na klar ist das Ding, das Du hier gepostet hast, niedlich, aber was
machst Du, wenn Du in Deinem Programm vielleicht 5000 SQL-Abfragen hast,
die bis auf wenige Ausnahmen ohne Parameter funktionieren. Oder
schreibst Du sogar jedes mal den ganzen Code aus, statt das irgendwie zu
kapseln?

Gruß Jo
Peter Fleischer
2007-04-20 02:41:13 UTC
Permalink
Post by Joachim Heisterfeld
ich hasse Parameterobjekte, weil man eben nicht mehr einfach einen
SQL-String übergeben kann.
Hi Joachim,
wenn du eine SQl-Anweisung mit Parameter hast, dann musst du auch die
Parameter übergeben. Ich verstehe deine Bemerkung nicht.
Post by Joachim Heisterfeld
Na klar ist das Ding, das Du hier gepostet hast, niedlich, aber was
machst Du, wenn Du in Deinem Programm vielleicht 5000 SQL-Abfragen
hast, die bis auf wenige Ausnahmen ohne Parameter funktionieren.
Bei 5000 unterschiedlichen SQL-Anweisungen hast du auch 5000
unterschiedliche Aufrufe. Un bei jedem Aufruf sind ggf. eine
unterschiedliche Anzahl Parameter zu übergeben. Wo siehst du da Probleme?
Post by Joachim Heisterfeld
Oder
schreibst Du sogar jedes mal den ganzen Code aus, statt das irgendwie
zu kapseln?
Irgendwie muss der Code doch geschrieben werden. Wenn er sich
wiederverwenden lässt, dann wird er auch in eine separate Methode gepackt.
Ich sehe da keinen Unterschied, ob ich die Parameter im command.Execute oder
in Parametern übergebe. Mit Parameter-Objekten kann ich typgerecht arbeiten
und ohne Parameter-Objekte muss ich mit der Formatanweisung mit einem
passenden angelsächsischen FormatString konvertieren. Ich sahe da keinen
Unterschied im Aufwand.

Bei entsprechender Programmgestaltung reden wir über einen Zusatzaufwand pro
Parameter von einer Anweisung. Dafür bleiben dann die Probleme wegen
impliziter Typkonvertierung aus:

Private Sub Command1_Click()
Dim cn As New ADODB.Connection
cn.ConnectionString = "provider=microsoft.jet.oledb.4.0;" & _
"data source=c:\me\vb6\test2k.mdb"
cn.Open
Dim cmd As New ADODB.Command
Set cmd.ActiveConnection = cn
cmd.CommandType = adCmdText
'
On Error Resume Next
cmd.CommandText = "DROP VIEW test"
cmd.Execute
On Error GoTo 0
cmd.CommandText = "CREATE PROC test AS INSERT INTO TempTab(EinDatum)
VALUES(?)"
cmd.Execute
'
Dim i As Integer
Dim d As Variant
d = CDate("1.2.03")
Dim par1 As New ADODB.Parameter
par1.Type = adDate
Dim s As String
'
cmd.CommandText = "test"
cmd.CommandType = adCmdStoredProc
s = Format(d, "mm\/dd\/yyyy")
cmd.Execute i, s, adCmdUnknown Or adExecuteNoRecords
'
par1.Value = d
cmd.CommandText = "test"
cmd.CommandType = adCmdStoredProc
cmd.Parameters.Append par1
cmd.Execute i
'
End Sub
--
Viele Grüße

Peter
Ulrich Boehringer
2007-04-20 05:48:00 UTC
Permalink
Hallo,

danke dass Ihr meine Frage noch mal aufgegriffen habt. Ich habe inzwischen
ein kleines Testprogramm geschrieben, das den von 'Now' zurückgegebenen
Datumswert in eine Datumsfeld schreibt. Ich habe diesen Datumswert über
'Cdbl' (VB) bzw. 'ZDouble' (Access) jeweils in eine serielle Zahl umgewandelt
und erhalte 2 verschiedene Werte.

Eine Rückfrage bei anderen Entwicklern ergab, dass in Access statt
Textfelder Datumsfelder eingesetzt werden. Dies ist für mich nicht
aktzeptabel!

Das von Rainer vorgeschlagene CDate(Now) funktioniert bei mir nicht, nur
Format$(Now, "yyyy-mm-dd hh:mm:ss") und dabei belasse ich es auch, zumal
dieses Format der Norm (ISO 8601) entspricht. Ich hoffe nur, dass ich solche
Probleme mit C# und ADO.NET zukünftig nicht mehr habe (wobei ich mit C# nach
10 Jahren VB andere habe).

Gruß
Ulrich Boehringer
Ralf Brostedt
2007-04-20 07:49:40 UTC
Permalink
Post by Ulrich Boehringer
Eine Rückfrage bei anderen Entwicklern ergab, dass in Access statt
Textfelder Datumsfelder eingesetzt werden. Dies ist für mich nicht
aktzeptabel!
Das verstehe ich nicht. In jeder Datenbank, egal ob Access, MSSQL, MySQL
oder Oracle oder oder oder, gibt es einen Datentyp "Datum". Das ist für
deine Zwecke genau DIE Lösung. Es gibt keine andere. Alles andere ist,
um es mal so zu sagen, Gefrickel, und zu welchen Ergebnissen bzw.
Problemen das führt, hast du uns ja in deinem Originalposting schon
beschrieben.

Kann es sein, dass hier mal wieder der klassische Fall von Verwechslung
vorliegt, zwischen dem, wie Daten gespeichert, und dem, wie Daten
dargestellt werden?

Oder um es anders zu sagen: Ein Datum ist kein Text, sondern ein Datum.
Ein Zahlenwert ist kein Text, sondern ein Zahlenwert. Speichert man
sowas in einem Textfeld/String, dann wird aus dem Wert eine reine
Zeichenfolge. Das ist unter bestimmten Bedingungen sinnvoll oder sogar
geboten, spontan fallen mir dazu Postleitzahlen oder Hausnummern ein. In
den meisten anderen Fällen ist das fahrlässig und fehleranfällig.
--
Sender's Mail address is valid but not to be read.
In order to write an email, please replace "compuserve" with
the name given in Organization header.
Joachim Heisterfeld
2007-04-20 09:35:10 UTC
Permalink
Also irgendwie denk ich, dass ich es anders mache als jeder hier, aber
ich verwende Parameter nur 2x gegenüber wie gesagt ca. 5000
SQL-Anweisungen, die ich gekapselt habe. Aber das Datenbankgefutzel
macht ja auch jeder anders, bzw. ich denke, es ist stark vom
Programmierstil abhängig. Ich mach z. B. folgendes:

Public colKunden() as Kunde
Public type Kunde
Vorname as string
Nachname as string
end type

public sub main

dim k&

if not moddb.dbconnect(kunden) then
'fehlermeldung
else
moddb.sqlkunden("SELECT * FROM kunden ORDER BY whatever")
redim colKunden(0)
if not rskunden.eof then
redim colkunden(1 to rskunden.recordcount)
for k = 1 to rskunden.recordcount
colkunden(k).vorname = moddb.nonull(rskunden!vorname)
rskunden.movenext
next k
end if
end if

Also so in diesem Stil. Ich persönlich bin der Meinung, Datenbank ist
einfach so unterschiedlich zu handhaben, dass es da keine Patentlösung
gibt, und man muss einfach "seinen Stil" finden. Vielleicht gebe ich Dir
in ein paar Jahren recht, aber bisher schwör ich noch auf meine eigene
Methode.
Und man muss die Applikation auch mal mit anderen regionalen Settings
ausprobieren!
Peter Fleischer
2007-04-20 12:18:24 UTC
Permalink
Post by Joachim Heisterfeld
Also so in diesem Stil. Ich persönlich bin der Meinung, Datenbank ist
einfach so unterschiedlich zu handhaben, dass es da keine Patentlösung
gibt, und man muss einfach "seinen Stil" finden.
Hi Joachim,
das ist vereinfacht gesagt wenig professionell. Ein Grundprinzip ist die
typgerechte Arbeit. Nimm mal folgendes Beispiel:

Dim a, b, c
a = "1"
b = "2"
c = a + b

Da kommt garantiert kein Wert 3 raus :-)
Post by Joachim Heisterfeld
Vielleicht gebe ich
Dir in ein paar Jahren recht, aber bisher schwör ich noch auf meine
eigene Methode.
Da hast du noch nie richtig stabile Anwendungen geschreiben, die produktiv
mit ggf. unterschiedlichen lokalen Einstellungen sowohl im Client als auch
in der Datenbank abreiten.
Post by Joachim Heisterfeld
Und man muss die Applikation auch mal mit anderen regionalen Settings
ausprobieren!
Ändere einfach mal auf ein anderes Dezimal-Trennzeichen und lass dann Daten
in einem entsprechenden Erfassungsformular eingeben, z.b. mit englischen
Punkt als Trennzeichen.

Ganz schlimm wird es mit Datumswerten.
--
Viele Grüße

Peter
Schmidt
2007-04-20 13:18:52 UTC
Permalink
Post by Peter Fleischer
Da hast du noch nie richtig stabile Anwendungen geschreiben,
die produktiv mit ggf. unterschiedlichen lokalen Einstellungen
sowohl im Client als auch in der Datenbank abreiten.
Naja, jetzt gleich solche Schlüsse zu ziehen, nur weil jemand
auf den Einsatz von Command-Objekten verzichten möchte und
stattdessen mittels geeigneter (ANSI-SQL-)Wandler-Funktionen
seine SQL-Commands direkt zusammenbaut - also ich weiss ja
nicht.

Olaf
Peter Fleischer
2007-04-21 19:10:41 UTC
Permalink
Post by Schmidt
Post by Peter Fleischer
Da hast du noch nie richtig stabile Anwendungen geschreiben,
die produktiv mit ggf. unterschiedlichen lokalen Einstellungen
sowohl im Client als auch in der Datenbank abreiten.
Naja, jetzt gleich solche Schlüsse zu ziehen, nur weil jemand
auf den Einsatz von Command-Objekten verzichten möchte und
stattdessen mittels geeigneter (ANSI-SQL-)Wandler-Funktionen
seine SQL-Commands direkt zusammenbaut - also ich weiss ja
nicht.
Wer nicht typgerecht arbeiten will und die gesamte Typkonvertierung
beherrscht, der kann auch damit glücklich werden. Professionell ist das aber
nach meiner Meinung nicht, vor allem, da es in VB funktionierende Techniken
gibt, die das nicht erforderlich machen. Dazu gehört z.B. die
Variablendeklaration inclusive Typangabe genau so wie der maximale Verzicht
auf Variant. Es gibt bestimmt kaum Situationen, wo eine nicht-typgerechte
Arbeit mit eigenen Konvertierungsfunktionen effektiver ist als eine
typgerechte Arbeit.
--
Viele Grüße

Peter
Schmidt
2007-04-23 01:03:09 UTC
Permalink
Post by Peter Fleischer
Wer nicht typgerecht arbeiten will und die gesamte Typkonvertierung
beherrscht, der kann auch damit glücklich werden.
Professionell ist das aber nach meiner Meinung nicht, vor allem,
da es in VB funktionierende Techniken gibt, die das nicht erforderlich
machen. Dazu gehört z.B. die Variablendeklaration inclusive Typangabe
genau so wie der maximale Verzicht auf Variant.
Es geht hier in dem Thread IMO weniger um das typgerechte Arbeiten
mit VB allgemein, sondern eher um das DB-Typen gerechte Arbeiten.
Das kann man zum einen sicherstellen, indem man auf Command-
Parameter-Objekte der clientseitigen DB-Zugriffssschicht vertraut
(in Falle von VBClassic in aller Regel ADO) - oder indem man
sich halt wie Joachim kleine Funktionen baut, die dabei helfen, die
entsprechenden Command-Strings für die in den unterschiedlichen
DB-Engines meist leicht unterschiedlich verlangten Feld-Typen
(z.B. Date-Felder, Bit-Felder, Blob-Felder) korrekt zusammen-
zubauen.

Olaf
Peter Fleischer
2007-04-23 04:36:20 UTC
Permalink
Post by Schmidt
Es geht hier in dem Thread IMO weniger um das typgerechte Arbeiten
mit VB allgemein, sondern eher um das DB-Typen gerechte Arbeiten.
Und warum soll man auch bei der Arbeit mit Datenbanken nicht typgerecht
arbeiten? Das verstehe ich nicht.
Post by Schmidt
Das kann man zum einen sicherstellen, indem man auf Command-
Parameter-Objekte der clientseitigen DB-Zugriffssschicht vertraut
(in Falle von VBClassic in aller Regel ADO) - oder indem man
sich halt wie Joachim kleine Funktionen baut, die dabei helfen, die
entsprechenden Command-Strings für die in den unterschiedlichen
DB-Engines meist leicht unterschiedlich verlangten Feld-Typen
(z.B. Date-Felder, Bit-Felder, Blob-Felder) korrekt zusammen-
zubauen.
Wenn die Felder typgerecht angesprochen werden, sehe ich überhaupt keine
Notwendigkeit, in Abhängigkeit vom eingesetzten Datenbankserver die Daten
irgendwie aufzubereiten. Zeig mal ein Beispiel. Mit Parameter-Objekten habe
ich es bisher noch nicht erlebt, dass z.B. eine unterschiedliche
Konvertierung von Datum a in Datum b in Abhängigkeit vom angewandten
Datenbankserver notwendig war.

Wie bereits von mir geschrieben, kann jeder auch mit eigener Konvertierung
in Zeichenketten ohne typgerechte Zuweisung arbeiten. Man muss es eben nur
in allen Fällen beherrschen, es birgt zusätzliche Fehlerquellen bei
unzureichender Beherrschung und bewirkt u.U. eine Reduzierung der
Performance. Mit professioneller Arbeitsweise hat das in meinem Augen wenig
zu tun.
--
Viele Grüße

Peter
Joachim Heisterfeld
2007-04-20 09:42:46 UTC
Permalink
Eins stimmt aber ganz sicher:
Datumswerte gehören in Datumsfelder.

Wenn kein Datum gegeben ist, muss man eben 00:00:00 speichern oder einen
Ausweichwert, den man später rausfiltern kann. Schon wegen der
Sortierfunktion. Es ist nicht lustig, Datumswerte, die in Textfeldern
gespeichert sind, zu ordnen.
Ich fahre mit der Funktion SQLDate schon seit Jahren gut, die aus einem
VB-Datum ein SQL-Datum macht. Aber wie gesagt, ich denke, Datenbank ist
ein Gefutzel, das jeder unterschiedlich habenhaben wird.
Peter Fleischer
2007-04-20 12:21:55 UTC
Permalink
Post by Joachim Heisterfeld
Datumswerte gehören in Datumsfelder.
Wenn kein Datum gegeben ist, muss man eben 00:00:00 speichern oder
einen Ausweichwert, den man später rausfiltern kann.
Hi Joachim,
dafür ist Null (keine Eingabe) vorgesehen. "00:00:00" ist schon ein konreter
Wert. Null kann man auch filtern. "keine Eingabe" und Mitternacht ist bei
deinem Szenarion nicht unterscheidbar - also unpassende Lösung.
Post by Joachim Heisterfeld
Schon wegen der
Sortierfunktion.
Null-Werte stören eine Sortierung nicht.
Post by Joachim Heisterfeld
Es ist nicht lustig, Datumswerte, die in Textfeldern
gespeichert sind, zu ordnen.
Wer so etwas schwachsinniges macht, der muss auch mit den Konsequenzen
leben.
Post by Joachim Heisterfeld
Ich fahre mit der Funktion SQLDate schon seit Jahren gut, die aus
einem VB-Datum ein SQL-Datum macht. Aber wie gesagt, ich denke,
Datenbank ist ein Gefutzel, das jeder unterschiedlich habenhaben wird.
Man kann es aber auch richtig machen - "richtig machen" bedeutet für mich
mindestens typgerecht. Und da gibt es die von dir geschilderten Probleme
nicht.
--
Viele Grüße

Peter
Peter Fleischer
2007-04-20 12:11:10 UTC
Permalink
Post by Ulrich Boehringer
danke dass Ihr meine Frage noch mal aufgegriffen habt. Ich habe
inzwischen ein kleines Testprogramm geschrieben, das den von 'Now'
zurückgegebenen Datumswert in eine Datumsfeld schreibt. Ich habe
diesen Datumswert über 'Cdbl' (VB) bzw. 'ZDouble' (Access) jeweils in
eine serielle Zahl umgewandelt und erhalte 2 verschiedene Werte.
Hi Ulrich,
typgerechte Arbeit lohnt sich immer. Wenn mit Datum gearbeitet wird, dann
sollten Variablen vom Type Date und Datenbankfelder vom Tyb DbDate genutzt
werden. Wenn dann noch für Parameterübergabe wirklich Parameter-Objekte
genutzt werden, gibt es keine Probleme.
Post by Ulrich Boehringer
Eine Rückfrage bei anderen Entwicklern ergab, dass in Access statt
Textfelder Datumsfelder eingesetzt werden. Dies ist für mich nicht
aktzeptabel!
Überlege mal diesen Satz. Für mich ist nicht akzeptabel, wenn jemand nicht
typgerecht arbeitet. So etwas ist unprofessionell und dilettantisch.
Post by Ulrich Boehringer
Das von Rainer vorgeschlagene CDate(Now) funktioniert bei mir nicht,
nur Format$(Now, "yyyy-mm-dd hh:mm:ss") und dabei belasse ich es
auch, zumal dieses Format der Norm (ISO 8601) entspricht. Ich hoffe
nur, dass ich solche Probleme mit C# und ADO.NET zukünftig nicht mehr
habe (wobei ich mit C# nach 10 Jahren VB andere habe).
Probleme wirst du auch in C# haben, wenn du nicht typgerecht arbeitest und
z.B. Datumswerte als String verarbeitest.
--
Viele Grüße

Peter
Peter Götz
2007-04-20 17:36:54 UTC
Permalink
Hallo Ulrich,
Ich habe inzwischen ein kleines Testprogramm
geschrieben, das den von 'Now' zurückgegebenen
Datumswert in eine Datumsfeld schreibt.
Now() liefert einen Wert vom Typ Variant, Untertyp Date.
Mit

Dim MeinDatum as Date
MeinDatum = now

hast Du in MeinDatum einen Wert vom Typ Date.
In welches Feld schreibst Du wie diesen Wert?
Ich habe diesen Datumswert über 'Cdbl' (VB)
bzw. 'ZDouble' (Access) jeweils in eine serielle
Zahl umgewandelt
Was meinst Du mit einer "seriellen Zahl"?

Mit

Dim dblValue as Double
dblValue = cDBL(Now)

steht in der Variablen dblValue nun ein Wert
vom Typ Double, bei dem der Wert vor dem
Dezimaltrenner die Anzahl der seit dem 30.12.1899
vergangenen Tage darstellt und der Teil hinter
dem Dezimaltrenner die Uhrzeit als Bruchteil eines
ganzen Tages von 24Std. darstellt. Der Wert 0,5
wäre also der 30. Dezember 1899 12Uhr Mittags.
und erhalte 2 verschiedene Werte.
Wie erhältst Du wo 2 verschiedene Werte?
Eine Rückfrage bei anderen Entwicklern ergab,
dass in Access statt Textfelder Datumsfelder
eingesetzt werden.
Wo werden in Access Datumsfelder statt Textfelder
eingesetzt?
Es ist Deine Entscheidung, ob Du für ein Feld in
einem Datensatz einer Tabelle einer *.mdb ein
Feld als Textfeld oder als Feld vom Typ Datum/Zeit
definierst.
Aber natürlich ist es sinnvoll, für das Speichern von
Datumswerten ein Feld vom Typ Datum/Zeit
(VB-Typ Date) zu verwenden, da Du nur so die bei
der Speicherung von Datumsausdrücken in Textfeldern
unumgänglichen Formatierungsprobleme bei
unterschiedlichen Ländereinstellungen umgehen
kannst.
Dies ist für mich nicht
aktzeptabel!
Was ist nicht akzeptabel?
Warum willst Du einen Wert vom Typ Date in einem
Textfeld in der DB speichern? Damit handelst Du
Dir nur völlig unnötige Probleme im Zusammenhang
mit unterschiedlichen Ländereinstellungen ein.
Das von Rainer vorgeschlagene CDate(Now)
funktioniert bei mir nicht,
Natürlich nicht.
cDate(Now) liefert wieder einen Wert vom Typ Date,
ist also hölzernes Holz.
Und so wie Du es verwendest, zwingst Du VB diesen
Wert in einem String umzuwandeln, was nach den
Formatierungsregeln der jeweiligen Ländereinstellung
geschieht. In Deinem Fall also mit einiger Wahrscheinlichkeit
nach Deutschen Formatierungsregeln. Einen derart
formatierten Datumsausdruck versteht aber die Jet-
Engine nicht, bzw. kann diesen in einer Reihe von
Fällen falsch interpretieren. Die Jet-Engine erwartet
bei Datumsausdrücken in Strings das US-Format
(mm/dd/yyyy) oder das ISO-Format (yyyy/mm/dd).
Das ISO-Format hat den Vorteil, dass es da kein
Vertun zwischen Monat und Tag geben kann, da
die JetEngine bei einem führenden Jahr in jedem
Fall weiss, dass der Rest Monat und dann Tag ist.
nur Format$(Now, "yyyy-mm-dd hh:mm:ss")
Ja, mit diesem Format (ISO) kann die Jet-Engine
einwandfrei arbeiten und es kann damit auch keine
Fehlinterpretationen geben.
und dabei belasse ich es auch, zumal
dieses Format der Norm (ISO 8601) entspricht.
Ja, so isses.

Nur hat das alles nichts damit zu tun, ob man ein
Datum in der DB als Wert vom Typ Date oder als
String speichert. In der DB solltest Du Deine
Datumswerte auf jeden Fall als Werte vom Typ
Date speichern. Ein solcher Wert ist völlig unabhängig
von irgendwelchen länderspezifischen Formatierungen.
Dagegen sind Datumsausdrücke in Strings immer mit
irgendwelchen (länderspezifischen) Formatierungen
behaftet und somit Probleme bei der Interpretation
solcher Ausdrücke schon vorprogrammiert.
Ich hoffe nur, dass ich solche Probleme mit C#
und ADO.NET zukünftig nicht mehr habe
Ich befürchte, dass Du diese Probleme auch damit
haben wirst, da Dir offenbar (noch) nicht klar ist, dass
ein Datum in einem Feld einer DB-Tabelle zwar als
Wert vom Typ Date gespeichert werden kann, ein
solches Datum jedoch in einem SQL-Statement,
welches ja in Form eines Strings erstellt wird, eben
zwangsläufig als String mit einem bestimmten (US-
oder ISO- Format) dargestellt werden muss.

Die konsequente Verwendung von Parameterobjekten
für Deine Commands erspart Dir dieses Umdenken
bzw. richtige Formatieren von Datumsausdrücken für
SQL-Strings, weil Du dem Parameterobjekt den
Datumswert typgerecht als Wert vom Typ Date übergeben
kannst.

Schau Dir zum Thema Datum in SQL-Strings vielleicht
auch mal die beiden Artikel unter

www.gssg.de -> Visual Basic -> VBclassic
-> Datum/Zeit
-> Datum u. Zeit in Visual Basic
-> Datum u. Zeit in SQL-Strings

an. Dort findest Du auch Dein ISO-Format wieder und
auch noch anderes, was die Jet-Engine als Datum
versteht.

Gruß aus St.Georgen
Peter Götz
www.gssg.de (mit VB-Tipps u. Beispielprogrammen)
Wilfried Dietrich
2007-04-23 07:40:16 UTC
Permalink
Hallo Peter,

ich verwende in meinen SQL-Strings bis dto. das US-Format
Format$(Datum,"\#m\/d\/yyyy\#).
Ist es jetzt besser und sicherer das ISO-Format
Format$(Datum,"\#yyyy\/mm\/dd\#") zu benutzen?

MfG.
Wilfried
Peter Götz
2007-04-23 09:52:11 UTC
Permalink
Hallo Wilfried,
Post by Wilfried Dietrich
ich verwende in meinen SQL-Strings bis dto. das
US-Format Format$(Datum,"\#m\/d\/yyyy\#).
Das ist dann schon ok. Die meisten DBS, so auch die
Jet und der SQL-Server, verstehen dieses Format.
Post by Wilfried Dietrich
Ist es jetzt besser und sicherer das ISO-Format
Format$(Datum,"\#yyyy\/mm\/dd\#") zu benutzen?
Nicht besser.
Ich verwende, wenn ich nicht ohnehin mit Parameter-
objekten arbeite, ganz gerne das ISO-Format, weil
es eben schon beim reinen (optischen) Lesen sofort
erkennen lässt, wo Jahr, Monat und Tag stehen.

"2007.12.10" ist unmissverständlich der 10. Dez. 2007

Bei einem String

"12/10/2007" oder "12.10.2007"

könnte man ins Grübeln kommen, ob es um
den 12. Oktober (deutsches Format) oder um
den 10. Dezember (US-Format) geht.

Ob nun ISO oder US-Format, würde ich eher
als Geschmackssache einstufen. Mit
Parameterobjekten erspart man sich eben
diese ganzen Überlegungen, weil man dem
Paramterobjekt den Datumswert typgerecht
als Date übergeben kann.

Die JetEngine versteht neben dem US-Format
und dem ISO-Format auch noch Abbildungen eines
in Double umgewandelten Date-Wertes

dim strDatWert as String
dim Datum as Date
Datum = Now
strDatWert = Trim$(Str$(cDBL(Datum)))

"Select * From Tabelle Where Datum = " &
strDatWert

Wichtig ist die Umwandlung von Double nach String
mit der Funktion Str$(), damit der erzeugte String
den Punkt und nicht das länderspezifische Komma
als Dezimaltrenner erhält.

Gruß aus St.Georgen
Peter Götz
www.gssg.de (mit VB-Tipps u. Beispielprogrammen)
Wilfried Dietrich
2007-04-23 11:21:32 UTC
Permalink
Hallo Peter,

ja OK.

Wenn ich das ISO-Format verwende dann kann ich
wie gehabt die Uhrzeit anhängen z.B.
Format$(Now, "\#yyyy\/mm\/dd hh:mm:ss\#")
oder wenn ich nur bis zur Minute möchte
Format$(Now, "\#yyyy\/mm\/dd hh:mm\#")?
Ist das richtig?

Gruß
Wilfried
Peter Götz
2007-04-23 12:35:42 UTC
Permalink
Hallo Wilfried,
Post by Wilfried Dietrich
Wenn ich das ISO-Format verwende dann kann ich
wie gehabt die Uhrzeit anhängen z.B.
Format$(Now, "\#yyyy\/mm\/dd hh:mm:ss\#")
oder wenn ich nur bis zur Minute möchte
Format$(Now, "\#yyyy\/mm\/dd hh:mm\#")?
Ist das richtig?
Ja, die Jet-Engine versteht auch das.

Gruß aus St.Georgen
Peter Götz
www.gssg.de (mit VB-Tipps u. Beispielprogrammen)

Loading...