none
Fehler beim SQL Update RRS feed

  • Frage

  • Hallo, guten Tag,

    ich versuche in einer MySQL Table die Spalte "Anzahl" in der Datenbank definiert als Float 12,3 mit einem Dezimalwert zu ändern. Bei ganzen Zahlen funktioniert es.

    Jedoch bei Kommawerten bekomme ich einen Fehler obwohl der Kommawert in der Variable als Decimal-Wert angezeigt wird. Jedoch im SQL-Kommando wird aus dem Wert 2.5 D der Wert Double 2,5 und führt zu einem Fehler wie auf den Bildausschnitten ersichtlich.

    Welche Möglichkeit gibt es um diesen Fehler zu vermeiden?

    Nachfolgend der Bildauszug sowie ein  Auszug aus dem Code:


     
    Public VLeseMenge As Decimal 'Der Wert z.B 2,5 aus einem Textfeld 
    Dim sql as string 'Das SQL Kommando'
    
     Try
                conn = New ADODB.Connection
                conn.ConnectionString = "DRIVER={MySQL ODBC 5.1 Driver};SERVER=XXX.XXX.XXX.XXX;DATABASE=myelog;UID=xxxxx;PWD=xxxxx; OPTION=3"
                conn.Open()
            Catch ex As Exception
                MessageBox.Show(ex.Message, "Fehler")
            End Try
    
    'Codeblock für update
    sql = "update matkartartikel set anzahl = Anzahl + '" & VLesemenge & "' where ArtNr =  '" & VArtNr & "'" 
    conn.Execute(sql)
    
    

     

    Freitag, 17. Oktober 2014 08:56

Antworten

  • Hallo Anthony,

    Du wirst de-DE Regional Settings haben und bei der Umwandlung von Numerisch nach String wird nach den Einstellungen formiert, sofern man nichts anderes angibt. Bei ToString z.B. kann man vorgeben, nach welcher abweichenden Settings formatiert werden soll.

    Imports System.Globalization
    
    Module Module1
    
        Sub Main()
            Dim value = 2.5D
    
            Console.WriteLine(value.ToString())
            Console.WriteLine(value.ToString(CultureInfo.InvariantCulture))
            Console.WriteLine(value.ToString(CultureInfo.CreateSpecificCulture("en-US")))
            Console.ReadKey()
        End Sub
    
    End Module

    Ergebnis: Erste Ausgabe mit Komma, die beiden weiteren mit Punkt

    Wie Visual Studio und die ganzen Tools den Wert anzeigen, ist noch mal eine andere Geschichte.


    Olaf Helper

    [ Blog] [ Xing] [ MVP]



    Freitag, 17. Oktober 2014 10:22

Alle Antworten

  • Jedoch im SQL-Kommando wird aus dem Wert 2.5 D der Wert Double 2,5 und führt zu einem Fehler

    Hallo Anthony,
    SQL erwartet als Dezimaltrennzeichen immer den Punkt, kein Komma. Man sollte auch nie SQL Abfrage dynamisch zusammen bauen, so wie Du es machst, das führt immer zu Fehler, z.B. auch bei Datumswerten. Verwende besser parametrisierte Abfragen; siehe Commands and Parameters

    Olaf Helper

    [ Blog] [ Xing] [ MVP]


    • Bearbeitet Olaf HelperMVP Freitag, 17. Oktober 2014 09:02
    • Als Antwort vorgeschlagen Jens Gerber Freitag, 17. Oktober 2014 10:47
    Freitag, 17. Oktober 2014 09:02
  • Hallo Olaf,

    vielen Dank für die schnelle Antwort.

    Richtig ist SQL erwartet einen Punkt als Trennzeichen

    Was mich verwundert ist, in der Variable ist der Wert 2.5 mit Punkt und wird, wie auch immer, im SQL-Kommando zu 2,5 mit Komma (s.  o. Bild)

    Anthony

    Freitag, 17. Oktober 2014 09:24
  • Hallo Anthony,

    Du wirst de-DE Regional Settings haben und bei der Umwandlung von Numerisch nach String wird nach den Einstellungen formiert, sofern man nichts anderes angibt. Bei ToString z.B. kann man vorgeben, nach welcher abweichenden Settings formatiert werden soll.

    Imports System.Globalization
    
    Module Module1
    
        Sub Main()
            Dim value = 2.5D
    
            Console.WriteLine(value.ToString())
            Console.WriteLine(value.ToString(CultureInfo.InvariantCulture))
            Console.WriteLine(value.ToString(CultureInfo.CreateSpecificCulture("en-US")))
            Console.ReadKey()
        End Sub
    
    End Module

    Ergebnis: Erste Ausgabe mit Komma, die beiden weiteren mit Punkt

    Wie Visual Studio und die ganzen Tools den Wert anzeigen, ist noch mal eine andere Geschichte.


    Olaf Helper

    [ Blog] [ Xing] [ MVP]



    Freitag, 17. Oktober 2014 10:22
  • Hallo Anthony,

    nur ergänzend zu der Erklärung von Olaf. Du fährst wirklich besser wenn mit Parametern arbeitest. Das nimmt dir viel Arbeit ab. Z.B bei Strings das doppeln der Hochkommas, Culture abhängige Datumsformatierung etc. , um all das musst du dich bei der Verwendung von Parametern nicht kümmern. Aber um das zu nutzen empfehle ich dir nicht mit ADODB und ODBC zu arbeiten, sondern mit dem offiziellen MySQL Net Connector, der sehr komfortabel ist.

    MySQL Connector

    Ich habe hier eine Reihe an Funktionen und Klassen die Insert's und Update's mit Parametern sehr leicht mit wenig Code zur Verfügung stellen. Bei Bedarf einfach fragen.

    PS.

    um diesen zu nutzen musst du in deinem Projekt die MySQL.Data.Dll einbinden und kannst dann die Namespaces MySQL.Data.MySqlClient importieren. Der MySQL Connector hält sich äquivalent an die Namenskonventionen vom MS SQL Connector in Visual Studio. 

    Gruß



    Jens Gerber


    • Bearbeitet Jens Gerber Freitag, 17. Oktober 2014 10:59
    Freitag, 17. Oktober 2014 10:47
  • Hallo Olaf,

    hallo Jens,

    Vielen Dank für die Information mit der Culture. Dies scheint die  tatsächliche Ursache zu sein.

    Mittlerweilen habe ich den Code auf eine parametrisierte Abfrage umgestellt.

    Nachfolgend ein paar Zeilen als Beispielcode:

    Vielen Dank an beide

    Anthony


    Imports MySql.Data.MySqlClient
    

    'Definition Dim myconn As New MySqlConnection Dim mysqlcomm As New MySqlCommand 'Verbindung öffnen Try myconn = New MySqlConnection myconn.ConnectionString = "SERVER=xxx.xxx.xxx.xxx; UID=xxxxx; PWD=xxxxx;DATABASE=xxxx;" myconn.Open() Catch ex As Exception MessageBox.Show(ex.Message, "Fehler") End Try 'Die Verbindung dem SQL-Befehl bereitsstellen mysqlcomm.Connection = myconn 'Die Parameter hinzufügen mysqlcomm.Parameters.Add("@VMenge",MySqlDbType.Decimal).Value = VMenge mysqlcomm.Parameters.Add("@VArtNR",MySqlDbType.String).Value = VArtNr 'Die Abfrage ausführen mysqlcomm.CommandText = "update artikel set anzahl = '@VMenge' where ArtNr = '@VArtNr'" mysqlcomm.ExecuteNonQuery() 'Verbindung schliessen myconn.close()




    Freitag, 17. Oktober 2014 11:29
  • Noch ein kleiner Hinweis: MySqlConnection & Command implementieren IDisposable, also nach Ende der Verwendung der Objekte das .Dispose() aufrufen, um die Objekte sauber zu schließen, oder einfach ein Using verwenden:

    'Definition
    Using myconn As New MySqlConnection("SERVER=xxx.xxx.xxx.xxx; UID=xxxxx; PWD=xxxxx;DATABASE=xxxx;")
        'Verbindung öffnen
        Try
            myconn.Open()
        Catch ex As Exception
            'MessageBox.Show(ex.Message, "Fehler")
        End Try
    
        'Die Verbindung dem SQL-Befehl bereitsstellen
        Using mysqlcomm As New MySqlCommand()
            mysqlcomm.Connection = myconn
    
            'Die Parameter hinzufügen
            mysqlcomm.Parameters.Add("@VMenge", MySqlDbType.Decimal).Value = VMenge
            mysqlcomm.Parameters.Add("@VArtNR", MySqlDbType.String).Value = VArtNr
    
            'Die Abfrage ausführen
            mysqlcomm.CommandText = "update artikel set anzahl =  '@VMenge' where ArtNr = '@VArtNr'"
            mysqlcomm.ExecuteNonQuery()
        End Using
    
        'Verbindung schliessen
        myconn.Close()
    End Using


    Olaf Helper

    [ Blog] [ Xing] [ MVP]

    Freitag, 17. Oktober 2014 11:51
  • Das

      'Verbindung schliessen
        myconn.Close()

    Kann man meines Erachtens sogar bei der Nutzung von Using weglassen. Bei Using wird die Verbindung automatisch geschlossen außer man nutzt Pooling.


    Jens Gerber

    Freitag, 17. Oktober 2014 12:05