Announcement

Collapse
No announcement yet.

DATE_SUB; Formatierungsfehler?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • DATE_SUB; Formatierungsfehler?

    Hi,
    trotz zahlreicher Quellen, vom Referenzhandbuch angefangen, bis zum Stöbern div. Foren und einigem Zeitaufwand den Fehler über Try and Error zu ermitteln, gelang es mir nicht, den Fehler zu ermitteln.
    Code:
    Dim nDatum As Date
    	nDatum = CDate(txtDate.Text)
    	Try
    	  myconn.Open()
    	  Dim com As New MySqlCommand("SELECT * FROM treffer ORDER BY datum ASC", myconn)
    	  Dim da As New MySqlDataAdapter(com)
    	  Dim ds As New DataSet()
    	  da.Fill(ds, "treffer")
    	  Dim dt As DataTable = ds.Tables("treffer")
    	  Dim cb As New MySqlCommandBuilder(da)
    	  Dim row As DataRow
    	  For Each row In dt.Rows
    		Dim command As New MySqlCommand("DELETE FROM treffer WHERE DATE_SUB(nDatum, INTERVAL 1 MONTH)< Datum", myconn)
    	  Next
    	  da.Update(ds, "treffer")
    	Catch ex As Exception
    	  MessageBox.Show(ex.Message, "Fehler! Datenbereinigung 'treffer' ist fehlgeschlagen!")
    	Finally
    	  myconn.Close()
    	End Try
    Es gibt mir keinen Fehler aus und bereinigte mir auch jene Datensätze nicht, die vor dem Referenzdatum nDatum liegen.
    Es ist eine von Access imigrierte Tabelle(MyISAM) mit dem Datentyp DATE.
    Was habe ich hier falsch gemacht? Ich habe nicht nur den Operator < umgedreht (hätte ja sein können, dass ich falsch liege) und ich habe auch nDatum in '" & nDatum & "' eingeschlossen. Alles ohne Ergebnis.
    Meine zweite Frage wäre, ob der SqlCommand in eine Schleife gelegt werden muss?
    Ich bin wirklich am Verzweifeln.
    Grüße

  • #2
    Hallo Albert,

    ob der DATE_SUB-Befehl richtig verwendet wird, habe ich nicht geprüft. Das steht in der MySql-Dokumentation.

    Dein Fehler ist das grundlegend falsche Vorgehen mit DbDataAdapter.Update sowie einzelnen Befehlen für jede Zeile.

    Mir wird immer schlecht, wenn ich so etwas lese:
    Code:
    For Each row In dt.Rows
    	Dim command As New MySqlCommand("DELETE FROM treffer 
    	WHERE DATE_SUB(nDatum, INTERVAL 1 MONTH)< Datum", myconn)
    Next
    Für jede Zeile deklarierst Du die Variable command, erzeugst mit new eine neue Instanz - und beim Next ist diese Instanz wieder vergessen.

    Nirgends gibt es eine Anweisung, dass dieser command benutzt werden soll - erst recht nicht in Verbindung mit der Datenbank.

    Nirgends gibt es eine Anweisung, die etwas mit dem CommandBuilder macht.

    DbDataAdapter.Update benötigt einen eigenen DeleteCommand, der sich auf die DataTable bezieht und DataRow.State benutzt. Wenn der SelectCommand passt (insbesondere darf er sich nur auf eine Tabelle beziehen und muss einen PrimaryKey enthalten; beides scheint zu stimmen), erzeugt der DbDataAdapter selbst einen DeleteCommand und kann alle Zeilen, die mit DataRowState.Deleted markiert sind, automatisch löschen. Aber Du hast keine einzige DataRow zum Löschen vorgesehen. (Jedenfalls sehe ich im Code nichts davon.)

    Du hast mindestens drei Möglichkeiten:

    Entweder Du bearbeitest in einer Schleife jede DataRow und prüfst per Code, ob row.Delete() auszuführen ist oder nicht; dann kann anschließend DbDataAdapter.Update verwendet werden.

    Oder Du benutzt einen DELETE-Befehl bezogen auf den PK (PrimaryKey), dazu eine Schleife für jede DataRow und prüfst per Code, ob sie zu löschen ist; wenn ja, dann übergibst Du den PK an den DELETE-Befehl und führst ihn per ExecuteNonQuery aus (ohne DbDataAdapter). Benutze dafür unbedingt Parameters und keine String-Verknüpfung mit PK.ToString().

    Oder Du erzeugst einen DELETE-Befehl wie den von Dir vorgesehenen. Dieser wird einmalig per command.ExecuteNonQuery() ausgeführt - fertig. Dieses Vorgehen ist am besten, weil etwas, was nur in der DB erledigt werden soll, auch dort ausgeführt werden soll. Es handelt sich um einen Sql-Befehl und nicht um einen je Zeile.

    Übrigens gehören DB-Fragen besser ins Unterforum ADO.NET. Zur Einführung schlage ich die VB-OpenBooks vor. (Ich hätte noch mehrere grundsätzliche Kritikpunkte, aber die spare ich mir jetzt.)

    Jürgen

    Comment


    • #3
      Äh, ich bin ja jetzt nicht der Oberfachmann, aber Du hast das Command angelegt, aber rufen musst Du es schon noch, oder?

      [EDIT:]Ok, man sollte vor dem Antworten mal einen Reload machen [/EDIT]
      Gruß Womble

      Comment


      • #4
        Originally posted by Jürgen Thomas View Post
        Mir wird immer schlecht, wenn ich so etwas lese:
        Hi Jürgen,
        ich habe mich - ich weiß nicht mehr wieso -, in dieser an sich recht einfachen Sache verrannt und hatte noch immer die folgende Routine im "Kopf"
        Code:
        	  Dim com1 As New MySqlCommand("SELECT * FROM xyz ORDER BY ID ASC", myconn)
        	  Dim da As New MySqlDataAdapter(com1)
        	  Dim ds As New DataSet()
        	  da.Fill(ds, "xyz")
        	  Dim dt As DataTable = ds.Tables("xyz")
        	  Dim cb As New MySqlCommandBuilder(da)
        	  Dim row As DataRow
        	  i = 1
        	  For Each row In dt.Rows
        
        		Dim com2 As New MySqlCommand("SELECT COUNT(Z1) FROM zyx " + _
        		"WHERE A1='" & i & "' OR B2='" & i & "' OR C3='" & i & "' " + _
        		"OR D4='" & i & "' OR E5='" & i & "' OR F6='" & i & "'", myconn)
        		tot = CInt(Format(CType(com2.ExecuteScalar, Integer), "##0"))
        		row!nList = tot
        		i += 1
        
        	  Next
        	  da.Update(ds, "xyz")
        	Catch ex As Exception
        	  MessageBox.Show(ex.Message, "Fehler! Datenspeicherung 'xyz' ist fehlgeschlagen!")
        	Finally
        	  myconn.Close()
        	End Try
        . Es ist mir leider passiert, Du hast inhaltlich vollkommen recht, Deine Fachkompetenz wird von mir nicht in Zweifel gezogen!
        Was mich an Deiner Antwort aber schon stört, ist Dein persönlicher Untergriff.
        Ich kann verstehen, dass man bei zahlreichen Anfragen - die für Dich glasklare Dinge sind - entnervt antwortet. Deshalb schlage ich vor, wir beginnen von Neuem und Du zeigts mir (ich bin 61, nach wie vor lernbegierung und habe in den frühen 80iger Jahren einen der ersten IBM-Computer besessen) wie's richtig geht.
        Einverstanden?
        PS.:
        Wenn ich den Operator < umdrehe, dann werden alle Daten gelöscht. Im vorliegendem Fall allerdings kein Datensatz.
        nDatum as Date(=txtDate.text = Referenzdatum)
        Datum = TabFeld
        Ein Fehler in der Variablen-Übergabe?
        Code:
        	Dim nDatum As Date
        	nDatum = CDate(txtDate.Text)
        	  Dim com As New MySqlCommand("DELETE FROM treffer WHERE DATE_SUB('" & nDatum & "', INTERVAL 1 MONTH)<Datum", myconn)
        	  com.ExecuteNonQuery()

        Comment


        • #5
          Hallo Alfred,

          die DATE_SUB-Konstruktion sieht theoretisch sauber aus; ich habe es in der MySql-Doku nachgelesen. Mein Verdacht liegt deshalb darin, dass der Sql-String in der Tat falsch aufgebaut wird; deshalb hatte ich auf Parameters hingewiesen. DATE_SUB kann man außerdem noch umgehen, indem diese Funktion ins Programm verlagert wird.

          Bist Du sicher, dass richtig verglichen werden soll? Pseudo-Code:
          Code:
          Lösche alle Einträge, bei denen im Feld "Datum" etwas steht, 
          was später liegt als das Vergleichsdatum (korrigiert um einen Monat zurück).
          Wenn ja, dann kann das etwa so aussehen:
          Code:
          Dim compareDate As Date
          compareDate = CDate(txtDate.Text)
          //  jetzt Datum verändern
          compareDate = compareDate.AddMonths(-1)
          
          //  Befehl erzeugen und Parameter vorbereiten
          Dim com As New MySqlCommand("DELETE FROM treffer WHERE ?nDatum < Datum", myconn)
          com.Parameters.AddWithValue("?nDatum", compareDate)
          com.ExecuteNonQuery()
          Details musst Du ggf. in der Doku nachlesen.

          Gruß Jürgen

          PS 1. Mein Tonfall bezieht sich primär auf das falsch verwendete new und die nicht verwendeten Objekte. Das ist so elementar und widerspricht jedem Zugriffsrecht, dass ich verzweifle.

          PS 2. Gibt es doch tatsächlich Programmierer, die älter sind als ich (und ich gehöre auch zur Generation 60+). Bei "sauberen" Zitaten antworte ich nur sachbezogen.

          Comment


          • #6
            Hallo Jürgen (Thomas ist vermutlich Dein Familienname),
            ich bin froh eine Ebene gefunden zu haben, bei der wir uns nicht an die "Gurgel" springen. Ich kann Dich verstehen, aber lassen wir das...
            Auf Deine Lösung wäre ich nie im Leben gekommen. Wie auch, denn ich bin "nur ein interessierter Laie". Meine Brötchen verdiente ich als Abteilungsleiter einer universitären Einrichtung mit dem Schwerpunkt "Systemanalyse im Buchhaltungsbereich". Dazu war es notwendig die Grundkenntnisse des Programmierens zu kennen um zu einem Konsenz zwischen Forderung und Möglichkeit zu kommen. Meine erste Sprache war Clipper5 von Borland, also vor langer Zeit. Das VB.Net-Zeitalter begann nach meiner aktiven Zeit, weshalb ich mehr oder weniger mit Try/Error arbeite. Es ist auch nur eine VB6-Applikation die ich zu konvertieren versuche. Emotional habe ich mich sehr lange dagegen gesträubt, aber die Zwischenergebnisse überzeugten mich(Performanceschub um das 4-fache).
            Doch zurück zur Sache.
            Bei meinem Query habe nDatum mit CURDATE() ausgetauscht und es funktionierte. Logische Folgerung, es muss der Hund bei "nDatum" begraben sein.Allerdings musste ich den Opterator auf > stellen. Bei Deiner Lösung habe ich mir erlaubt die Zwischenräume bei der Bedingung zu entfernen.
            Code:
            WHERE ?nDatum>Datum
            MySql mag das nicht.
            Nochmals recht herzlichen Dank für Deine Mühe.
            Alfred
            PS.: es wird noch einige Zeit dauern, bis ich wieder Hilfe benötige (Datensatzzeigermanipulationen etc. was jetzt über Bindingsource gelöst wird. Vorher muss ich mir noch die Grundlagen ansehen.

            Comment


            • #7
              Originally posted by Alfred_ View Post
              Hallo Jürgen (Thomas ist vermutlich Dein Familienname),
              Richtig.

              Allerdings musste ich den Opterator auf > stellen.
              Dafür hatte ich den Pseudo-Code geschrieben; der macht oft klarer, was man eigentlich vergleichen will.

              Bei Deiner Lösung habe ich mir erlaubt die Zwischenräume bei der Bedingung zu entfernen.
              Code:
              WHERE ?nDatum>Datum
              MySql mag das nicht.
              Na sowas, damit habe ich überhaupt nicht gerechnet. (Aber ich kenne selbst nur Firebird und allgemeine SQL-Regeln.)

              (Datensatzzeigermanipulationen etc. was jetzt über Bindingsource gelöst wird.
              BindingSource ist schon richtig. DataTables u.a. sind nur ungeordnete Datenmengen.

              Schöne Grüße und schonmal frohe Weihnachten!
              Jürgen

              Comment


              • #8
                Hallo Jürgen,
                ich darf Deine Grüße erwidern und wünsche auch Dir ein gesegnetes Weihnachtsfest und ein erfolgreiches Neues Jahr!
                Grüße Alfred

                Comment

                Working...
                X