Zeitspanne vergleichen und entsprechende Datensätze nicht zeigen Access und VB.Net

werner_sg

Erfahrenes Mitglied
Hallo ich hole mir mit folgendem Code alle daten einer Spalte in eine Checkbox, was so fehlerfrei funktioniert.

Code:
        conn.Open()

        Try
            dbcmd = New OleDbCommand("SELECT * FROM tblfahrzeuge", conn)
            Dim DbReader As OleDbDataReader

            DbReader = dbcmd.ExecuteReader
            While DbReader.Read
                CboxFahrzeug.Items.Add(DbReader("KFZ_NAME").ToString)
            End While
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try

        Try
            dbcmd = New OleDbCommand("SELECT * FROM tblmieter", conn)
            Dim DbReader As OleDbDataReader

            DbReader = dbcmd.ExecuteReader
            While DbReader.Read
                CboxMieter.Items.Add(DbReader("MIETER_NAME").ToString)
            End While
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try

        conn.Close()

ich möchte aber das alle Fahrzeuge zwischen zwei Datumsfeldern nicht mitgeladen werden

Die Felder im Program sind DataTimePicker1 und DataTimePicker3 und die Spalten in der Tabelle tblreservierung sind ABHOLUNG_DATUM und ABGABE_DATUM

hierzu habe ich es dann mit folgendem String versucht

(SELECT * FROM tblfahrzeuge, tblreservierung WHERE KFZ_NAME = KFZ_NAME WHERE '" & DateTimePicker1.Value & "' AND '" & DateTimePicker3.Value & "' NOT BETWEEN ABHOLUNG_DATUM AND ABGABE_DATUM , conn)

Dabei erhalte ich die Fehlermeldung : Syntayfehler (fehlender Operator) in Abfrageausdruck WHERE KFZ_NAME = KFZ_NAME WHERE 22.06.2021 17:05:33 AND 26.06.2021 18:06:12' NOT BETWEEN ABHOLUNG_DATUM AND ABGABE_DATUM

welcher Operator fehlt? Die beiden Zeiten aus den Pickern werden ja richtig übergeben
 
Lösung
1624480918307.png
Doch wieder als String?
Was machen die = im Between?
Was soll das Format DD-MM-YYYY in den Fixen Datumswerten? Entweder MM/DD/YYYY oder YYYY-MM-DD.

Visual Basic:
'Wert aus DateTimePicker1 als SQL-String
sqlStrDt1 = "#" & DateTimePicker1.Value.ToString("yyyy-MM-dd H:mm:ss") & "#"
sqlStrDt2 = "#" & DateTimePicker2.Value.ToString("yyyy-MM-dd H:mm:ss") & "#"
'Hier kannst du sqlDt1 debuggen. Schauen mal wie die aussehen

'Das SQL zusammenstellen
sql = "SELECT *  " &
    "FROM tblfahrzeuge  " &
    "WHERE  " &
    "    KFZ_NAME NOT IN ( " &
    "        SELECT KFZ_NAME " &
    "        FROM tblreservierung " &
    "          WHERE " &
    "             ( " & sqlStrDt1 & " BETWEEN abholung_datum AND abgabe_datum) " &
    "            OR ( "...
Habs jetzt auch mal so versucht
SQL:
            Sql = "SELECT * FROM tblfahrzeuge LEFT JOIN tblreservierung ON tblfahrzeuge.KFZ_NAME = tblreservierung.KFZ_NAME AND NOT @KFZ_ABHOLUNG OR @KFZ_ABGABE BETWEEN KFZ_ABHOLUNG AND KFZ_ABGABE"

            dbcmd.Connection = conn
            dbcmd.CommandText = Sql
            dbcmd.Parameters.AddWithValue("@KFZ_NAME", CboxFahrzeug.Text)
            dbcmd.Parameters.AddWithValue("@KFZ_ABHOLUNG", DateTimePicker1.Value.ToString)
            dbcmd.Parameters.AddWithValue("@KFZ_ABGABE", DateTimePicker3.Value.ToString)

da erzählt er mir dass das AND in der Between Anweisung fehlt
 
Das SQL Formatieren, damit man es lesen kann. Dann erkennt man auch, dass du da ein grosses Chaos drin hast.

Dein SQL
SQL:
SELECT * 
FROM 
    tblfahrzeuge 
    LEFT JOIN tblreservierung 
        ON tblfahrzeuge.KFZ_NAME = tblreservierung.KFZ_NAME 
        AND NOT @KFZ_ABHOLUNG 
        OR @KFZ_ABGABE BETWEEN KFZ_ABHOLUNG AND KFZ_ABGABE

  1. Du mischst da JOIN mit WHERE. Ab dem AND hat es ja nix mehr mit dem JOIN zu tun. Das gehört ins WHERE
  2. Klammern helfen. Grad wenn man mt AND und OR arbeitet, machen erst Klammern klar, was zum OR gehört. Auch das NOT über mehrere Bedinungen sollte Klammern haben
  3. Die kannst nicht (A or B) between .. schreiben.
Ich rate mal, dass so sein sollte. Ist aber ein reine Schätzung, da dein Chaos zu gross ist.
SQL:
SELECT * 
FROM 
    tblfahrzeuge 
    LEFT JOIN tblreservierung 
        ON tblfahrzeuge.KFZ_NAME = tblreservierung.KFZ_NAME 
WHERE
    NOT (
        (@KFZ_ABHOLUNG  BETWEEN KFZ_ABHOLUNG AND KFZ_ABGABE)
        OR (@KFZ_ABGABE BETWEEN KFZ_ABHOLUNG AND KFZ_ABGABE)
    )
 
Unabhängig von Yaslaws Antwort: Du hast zweimal ein WHERE in deinem SQL
Und korrekt wie Yaslaw es geschrieben hat: BETWEEN nimmt nur einen Wert.
Hast du mehrere Kriterien für ein BETWEEN musst du jedes einzeln vergleichen.

Wobei ich mir jetzt gerade nicht sicher bin, ob OR der richtige Operator ist bzw. ob Yaslaws Ansatz korrekt ist (NOT auf das Gesamtergebnis der BETWEEN's).
Kannst du mal ein
"Das ist Input von den DatePickern"
"Das sind Werte der zwei Datums-Felder von Beispielsätzen"
"Das soll gezeigt werden"
hier rein stellen?
Bei sowas würde ich eh erst mit nur einem DatePicker anfangen, und mich dann vorwärts hangeln

EDIT: Seh ich gerade: Welchen DatenTyp haben die zwei Datums-Felder in der Datenbank?
Du übergibst die Parameter als String
 
Zuletzt bearbeitet:
Das SQL Formatieren, damit man es lesen kann. Dann erkennt man auch, dass du da ein grosses Chaos drin hast.

Dein SQL
SQL:
SELECT *
FROM
    tblfahrzeuge
    LEFT JOIN tblreservierung
        ON tblfahrzeuge.KFZ_NAME = tblreservierung.KFZ_NAME
        AND NOT @KFZ_ABHOLUNG
        OR @KFZ_ABGABE BETWEEN KFZ_ABHOLUNG AND KFZ_ABGABE

  1. Du mischst da JOIN mit WHERE. Ab dem AND hat es ja nix mehr mit dem JOIN zu tun. Das gehört ins WHERE
  2. Klammern helfen. Grad wenn man mt AND und OR arbeitet, machen erst Klammern klar, was zum OR gehört. Auch das NOT über mehrere Bedinungen sollte Klammern haben
  3. Die kannst nicht (A or B) between .. schreiben.
Ich rate mal, dass so sein sollte. Ist aber ein reine Schätzung, da dein Chaos zu gross ist.
SQL:
SELECT *
FROM
    tblfahrzeuge
    LEFT JOIN tblreservierung
        ON tblfahrzeuge.KFZ_NAME = tblreservierung.KFZ_NAME
WHERE
    NOT (
        (@KFZ_ABHOLUNG  BETWEEN KFZ_ABHOLUNG AND KFZ_ABGABE)
        OR (@KFZ_ABGABE BETWEEN KFZ_ABHOLUNG AND KFZ_ABGABE)
    )
Guten Morgen Yaslaw
soweit hattest Du das richtig geschätzt
Den String hatte ich mir aus zwei verschiedenen Video Tutorials zusammen gestellt, geordnet sieht es selbstverständlich besser aus

Hatte aber versehentlich zwei falsche Spalten genommen, aber vor dem testen noch korrigiert.
Der Fehler ist auf jeden Fall weg, leider ist abschließend kein Fahrzeug mehr zum auswählen vorhanden

hier mal alle zugehörigen Codesnipsel

aus der booking.vb

Code:
    Private Sub Booking_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Call Btnload_Click(sender, e)
        TxtSachbearbeiter.Text = Mainform.Label3.Text
        conn.Open()

        Try
            'dbcmd = New OleDbCommand("SELECT * FROM tblfahrzeuge", conn)

            dbcmd = New OleDbCommand(" SELECT * " &
                                     " FROM " &
                                     "tblfahrzeuge Left Join tblreservierung  " &
                                     " On tblfahrzeuge.KFZ_NAME = tblreservierung.KFZ_NAME " &
                                     " WHERE " &
                                     " Not ( " &
                                     " ('" & DateTimePicker1.Value & "' BETWEEN ABGABE_DATUM AND ABHOLUNG_DATUM) " &
                                     " Or ('" & DateTimePicker3.Value & "' BETWEEN ABGABE_DATUM AND ABHOLUNG_DATUM))", conn)




            Dim DbReader As OleDbDataReader

            DbReader = dbcmd.ExecuteReader
            While DbReader.Read
                CboxFahrzeug.Items.Add(DbReader("KFZ_NAME").ToString)
            End While
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try

        Try
            dbcmd = New OleDbCommand("SELECT * FROM tblmieter", conn)
            Dim DbReader As OleDbDataReader

            DbReader = dbcmd.ExecuteReader
            While DbReader.Read
                CboxMieter.Items.Add(DbReader("MIETER_NAME").ToString)
            End While
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try

        conn.Close()

    End Sub

aus der Booking.Designer.vb

Code:
        '
        'DateTimePicker1
        '
        Me.DateTimePicker1.Location = New System.Drawing.Point(62, 50)
        Me.DateTimePicker1.Name = "DateTimePicker1"
        Me.DateTimePicker1.Format = DateTimePickerFormat.Short
        Me.DateTimePicker1.Size = New System.Drawing.Size(180, 20)
        Me.DateTimePicker1.TabIndex = 12


        '
        'DateTimePicker3
        '
        Me.DateTimePicker3.Enabled = True
        Me.DateTimePicker3.Location = New System.Drawing.Point(462, 50)
        Me.DateTimePicker3.Format = DateTimePickerFormat.Short
        Me.DateTimePicker3.Name = "DateTimePicker3"
        Me.DateTimePicker3.Size = New System.Drawing.Size(180, 20)
        Me.DateTimePicker3.TabIndex = 12


        '
        'CboxFahrzeug
        '
        Me.CboxFahrzeug.FormattingEnabled = True
        Me.CboxFahrzeug.Location = New System.Drawing.Point(262, 100)
        Me.CboxFahrzeug.Name = "CboxFahrzeug"
        Me.CboxFahrzeug.Size = New System.Drawing.Size(180, 20)
        Me.CboxFahrzeug.TabIndex = 13

in der CheckBox sollen die Fahrzeuge aufgeliste werden

mit dem String: dbcmd = New OleDbCommand("SELECT * FROM tblfahrzeuge", conn)
geht das sehr gut aber halt nur alle Fahrzeuge

in der Access sind die Spalten ABHOLUNG_DATUM und ABGABE_DATUM als DATUM/ZEIT gesetzt mit Format Datum,kurz und Eingabe Format 99.99.0000;0;_

Danke für deine Hilfe
 
Unabhängig von Yaslaws Antwort: Du hast zweimal ein WHERE in deinem SQL
Und korrekt wie Yaslaw es geschrieben hat: BETWEEN nimmt nur einen Wert.
Hast du mehrere Kriterien für ein BETWEEN musst du jedes einzeln vergleichen.

Wobei ich mir jetzt gerade nicht sicher bin, ob OR der richtige Operator ist bzw. ob Yaslaws Ansatz korrekt ist (NOT auf das Gesamtergebnis der BETWEEN's).
Kannst du mal ein
"Das ist Input von den DatePickern"
"Das sind Werte der zwei Datums-Felder von Beispielsätzen"
"Das soll gezeigt werden"
hier rein stellen?
Bei sowas würde ich eh erst mit nur einem DatePicker anfangen, und mich dann vorwärts hangeln

EDIT: Seh ich gerade: Welchen DatenTyp haben die zwei Datums-Felder in der Datenbank?
Du übergibst die Parameter als String
Danke für den Hinweis, werde es mir merken

habe gerade mal alles was zusammengehört gepostet
 
in der Access sind die Spalten ABHOLUNG_DATUM und ABGABE_DATUM als DATUM/ZEIT gesetzt mit Format Datum,kurz und Eingabe Format 99.99.0000;0;_
Das Format ist egal, das ist nur Anzeige. Du hast Date/Time und übergibst String.

Mit dem Rest kann ich nicht helfen, weil
a) Ich nicht weiss was für eine DB dahinter steckt
b) Ich deine Daten nicht kenne und es schwer zu sagen ist, warum da nix gefunden wird
c) Ich VB.NET nicht kann

Der Ansatz mit dem Prepared Statement ist auf alle Fälle dem zusammengesetzten SQL-String vorzuziehen. Das gilt für alle Sprachen.
 
a) Ich nicht weiss was für eine DB dahinter steckt
Steht doch in der Überschrift des Threads: Access

Zum Thema: Das Problem ist nicht der VB.NET-Code (mit Ausnahme String vs. DateTime) sondern die SQL-Abfrage
Wie ich geschrieben habe: Bitte Beispiel-Daten posten
Das habe ich, das wähle ich im DatePicker aus, das soll rauskommen
 
Steht doch in der Überschrift des Threads: Access
Ups.

Datum als SQL-String müsste dann im US- oder ISO-Format vorliegen, begrenz mit # anstelle von '
SQL:
-- ISO YYYY-MM-DD HH:NN:SS
MY_DATE_FIELD = #2021-06-23 10:54:15#

-- US MM/DD/YYYY HH:NN:SS
MY_DATE_FIELD = #06/23/2021 10:54:15#

Oder eben, zu bevorzugen: Prepared Statement und Datum als Datum übergeben, nicht als String.
date time conversion problem when inserting data into sql database
 
Sehe übrigens nochwas in seinem SQL (Post #5):
Er hat Abgabe_datum links im Between
Ich glaube mich daran zu erinnern, dass im BETWEEN links der kleiner Wert zu stehen hat und rechts der grössere.
Mag mich aber auch irren
 
Zurück