No me funciona la instrucción INSERT INTO

Colapsar
X
  • Filtrar
  • Tiempo
  • Mostrar
Limpiar todos
nuevos mensajes

  • No me funciona la instrucción INSERT INTO

    Hola a todos.
    Ya hace unos cuantos día me estoy "pegando" con el código que a continuación os muestro, que no funciona y no entiendo porqué.
    Me explico:

    Tengo un DataGridView al que llamo dtgCoge y que contiene cuatro columnas: idProveedor, Empresa, Mes, Importe.

    Trato de insertar los valores de idProveedor e Importe en una tabla llamada Meses, que contiene los siguientes campos:
    idProv, ene, feb, mar, abr, may, jun, jul, ago, sep, oct, nov, dic. idProv es un campo numérico (entero largo) y el resto de los campos son también numéricos y en este caso del tipo doble y con 2 decimales.

    Y este es el código:
    Al ejecutarle no me da ningún error, pero no inserta los valores.

    Si ñkguien tiene paciencia y ve en dónde puede estar el error, ñe agradecería que me lo indicase pues, como ya os he comentado, hace ya muchos días que lo estoy intentando y sigo igual.

    Como curiosidad, os diré que en VB6 la cosa funciona sin problemas,

    Código:
     
     For i = 0 To dtgCoge.Rows.Count - 1
                dtgCoge.Rows(i).Cells(2).Selected = True
                nmes = Val(dtgCoge.Rows(i).Cells(2).Value)
    
                Select Case nmes
    
                    Case 1
                        csql = "INSERT INTO Meses(idProv,ene) VALUES ("
                        csql += Val(dtgCoge.Rows(i).Cells(0).Value) & ", "
                        csql += Convert.ToDecimal(dtgCoge.Rows(i).Cells(3).Value) & ")"
                    Case 2
                        csql = "INSERT INTO Meses(idProv,feb) VALUES ("
                        csql += Val(dtgCoge.Rows(i).Cells(0).Value) & ", "
                        csql += Convert.ToDecimal(dtgCoge.Rows(i).Cells(3).Value) & ")"
                    Case 3
                        csql = "INSERT INTO Meses(idProv,mar) VALUES ("
                        csql += Val(dtgCoge.Rows(i).Cells(0).Value) & ", "
                        csql += Convert.ToDecimal(dtgCoge.Rows(i).Cells(3).Value) & ")"
                    Case 4
                        csql = "INSERT INTO Meses(idProv,abr) VALUES ("
                        csql += Val(dtgCoge.Rows(i).Cells(0).Value) & ", "
                        csql += Convert.ToDecimal(dtgCoge.Rows(i).Cells(3).Value) & ")"
                    Case 5
                        csql = "INSERT INTO Meses(idProv,may) VALUES ("
                        csql += Val(dtgCoge.Rows(i).Cells(0).Value) & ", "
                        csql += Convert.ToDecimal(dtgCoge.Rows(i).Cells(3).Value) & ")"
                    Case 6
                        csql = "INSERT INTO Meses(idProv,jun) VALUES ("
                        csql += Val(dtgCoge.Rows(i).Cells(0).Value) & ", "
                        csql += Convert.ToDecimal(dtgCoge.Rows(i).Cells(3).Value) & ")"
                    Case 7
                        csql = "INSERT INTO Meses(idProv,jul) VALUES ("
                        csql += Val(dtgCoge.Rows(i).Cells(0).Value) & ", "
                        csql += Convert.ToDecimal(dtgCoge.Rows(i).Cells(3).Value) & ")"
                    Case 8
                        csql = "INSERT INTO Meses(idProv,ago) VALUES ("
                        csql += Val(dtgCoge.Rows(i).Cells(0).Value) & ", "
                        csql += Convert.ToDecimal(dtgCoge.Rows(i).Cells(3).Value) & ")"
                    Case 9
                        csql = "INSERT INTO Meses(idProv,sep) VALUES ("
                        csql += Val(dtgCoge.Rows(i).Cells(0).Value) & ", "
                        csql += Convert.ToDecimal(dtgCoge.Rows(i).Cells(3).Value) & ")"
                    Case 10
                        csql = "INSERT INTO Meses(idProv,oct) VALUES ("
                        csql += Val(dtgCoge.Rows(i).Cells(0).Value) & ", "
                        csql += Convert.ToDecimal(dtgCoge.Rows(i).Cells(3).Value) & ")"
                    Case 11
                        csql = "INSERT INTO Meses(idProv,nov) VALUES ("
                        csql += Val(dtgCoge.Rows(i).Cells(0).Value) & ", "
                        csql += Convert.ToDecimal(dtgCoge.Rows(i).Cells(3).Value) & ")"
                    Case 12
                        csql = "INSERT INTO Meses(idProv,dic) VALUES ("
                        csql += Val(dtgCoge.Rows(i).Cells(0).Value) & ", "
                        csql += Convert.ToDecimal(dtgCoge.Rows(i).Cells(3).Value) & ")"
                End Select
                Try
                    cmd.ExecuteNonQuery()
                Catch ex As Exception
                    MsgBox(ex.ToString)
                End Try
            Next
    Muchas gracias a todos por vuestra ayuda.
    Saludos, Miguel Peña.

  • #2
    Creo que he descubierto a qué puede ser debido el error. Me explico:
    En la instrucción Convert.ToDecimal(dtgCoge.Rows(i).Cells(3).Value) la separación de decimales la hace con el signo coma (,) en lugar del punto decimal, con lo que el procedimiento interpreta que hay un valor más para insertar no coincidiendo el número de valores de consulta y el número de campos de destino.
    He tratado de solucionarlo formateando el valor del importe de la siguiente forma:
    format(dtgCoge.Rows(i).Cells(3).Value),"###,###.00 ")

    pero me da el error indicado,
    Podeis ver en dónde me estoy equivocando?

    Comentario


    • #3
      SOLUCIONADO.
      He incluido Imports System.Globalization al comienzo del formulario y en su evento load he añadido las siguientes líneas:
      System.Threading.Thread.CurrentThread.CurrentCultu re = New System.Globalization.CultureInfo("es-CO")
      System.Threading.Thread.CurrentThread.CurrentCultu re.NumberFormat.NumberDecimalSeparator = "."
      System.Threading.Thread.CurrentThread.CurrentCultu re.NumberFormat.NumberGroupSeparator = ","

      con lo cual conseguimos que el formato (en este caso numérico) de nuestro sistema tenga el punto(.) como separador decimal y la coma(,) como separador de miles.
      Espero que os sirva.
      Saludos.

      Comentario


      • #4
        Por lo que veo lo que haces es cambiar la configuración regional del PC que se usa en el programa, aunque soluciona el problema, no es la solución más correcta, el programa debería ajustarse a la configuración regional y no al reves.
        La solución mejor pasaría por usar parametros en el comando, en vez de construir la SQL como tú haces, eso solucionaría todos los problemas derivados de la configuración regional (fechas, si el proveedor admite parametros de ese tipo) y, además, la posible existencia de apostrofos en cadenas.

        Una visita a las Normas del foro nunca viene mal

        Comentario


        • #5
          Hola Gilman.
          Encantado de volver a encontrarte en este medio.
          Ya se que lo ideal sería hacer lo que tú me indicas, pero lo he tratado formateando, por ejemplo, los números con format(numero,"###,###.00") y tampoco me funcionaba, así que decidí hacer eso.
          No me importaría en absoluto que dieras alguna pista para hacerlo como propones, pues estoy seguro de que será mejor solución.
          Saludos y gracias por tu ayuda.
          Miguel Peña

          Comentario


          • #6
            Perdona por la tardanza en contestar, pero entre que no envía mensajes de contestación a los hilos y que he andado un poco liado no he podido responder.
            La función Format usa la configuración regional, y por lo tanto, si tienes como separador decimal la coma, lo usará, la única diferencia con la conversión por defecto es que te permite especificar el número de decimales a utilizar, una alternativa es usar la función Str, que ignora la configuración regional y por lo tanto usará el punto como separador decimal, pero eso no resuelve el problema de otro tipos de datos como las fechas, o la presencia de apóstrofos en las cadenas de texto.
            Usando parámetros, además de solucionar el problema de la configuración regional, se puede usar el mismo comando para varias operaciones con diferentes valores de los parámetros, con lo que se ahorraría memoria en el cliente y, como el comando se compilaría en el servidor la primera vez que se ejecute se mejorará el rendimiento del comando.

            Yo he usado el proveedor de acceso a base de datos SQLClient si tú usas otros habría alguna que otra diferencia, en cuanto al nombre de los parámetros.

            Código:
                    For i = 0 To dtgCoge.Rows.Count - 1
                        dtgCoge.Rows(i).Cells(2).Selected = True
                        nmes = Val(dtgCoge.Rows(i).Cells(2).Value)
            
                        Select Case nmes
            
                            Case 1
                                csql = "INSERT INTO Meses(idProv,ene) VALUES (@idProv, @Cantidad) "
                            Case 2
                                csql = "INSERT INTO Meses(idProv,feb) VALUES (@idProv, @Cantidad)"
                            Case 3
                                csql = "INSERT INTO Meses(idProv,mar) VALUES (@idProv, @Cantidad)"
                            Case 4
                                csql = "INSERT INTO Meses(idProv,abr) VALUES (@idProv, @Cantidad)"
                            Case 5
                                csql = "INSERT INTO Meses(idProv,may) VALUES (@idProv, @Cantidad)"
                            Case 6
                                csql = "INSERT INTO Meses(idProv,jun) VALUES (@idProv, @Cantidad)"
                            Case 7
                                csql = "INSERT INTO Meses(idProv,jul) VALUES (@idProv, @Cantidad)"
                            Case 8
                                csql = "INSERT INTO Meses(idProv,ago) VALUES (@idProv, @Cantidad)"
                            Case 9
                                csql = "INSERT INTO Meses(idProv,sep) VALUES (@idProv, @Cantidad)"
                            Case 10
                                csql = "INSERT INTO Meses(idProv,oct) VALUES (@idProv, @Cantidad)"
                            Case 11
                                csql = "INSERT INTO Meses(idProv,nov) VALUES (@idProv, @Cantidad)"
                            Case 12
                                csql = "INSERT INTO Meses(idProv,dic) VALUES (@idProv, @Cantidad)"
                        End Select
                        cmd = New System.Data.SqlClient.SqlCommand(csql, conn)
                        Dim p As System.Data.SqlClient.SqlParameter
                        p = New SqlClient.SqlParameter("@idProv", SqlDbType.Int)
                        p.Value = dtgCoge.Rows(i).Cells(0).Value
                        cmd.Parameters.Add(p)
                        p = New SqlClient.SqlParameter("@Cantidad", SqlDbType.Float)
                        p.Value = dtgCoge.Rows(i).Cells(3).Value
                        cmd.Parameters.Add(p)
            
                        Try
                            cmd.ExecuteNonQuery()
                        Catch ex As Exception
                            MsgBox(ex.ToString)
                        End Try
                    Next
            Una visita a las Normas del foro nunca viene mal

            Comentario


            • #7
              Yo cambiaría toda esa lista de Select Case nmes, por esto:

              Código:
              cMeses = "enefebmarabrmayjunjulagosepoctnovdic"
              csql = "INSERT INTO meses(IdPro, Mid(cMeses, 1 + (nmes - 1) * 3, 3) VALUES (@IdProv, @Cantidad)"
              José María Movilla Cuadrado
              ______________________
              Normas del foro
              www.foro.vb-mundo.com
              www.vb-mundo.com

              Comentario


              • #8
                Muchísimas gracias a los dos por vuestra ayuda.
                Como ya sabéis, estoy dando mis primeros pasos en .NET y mis conocimientos son más que escasos.
                He intentado aplicar el código remitido por Gilman, pero no me funciona debido al proveedor de acceso a datos (sqlClient) que desconozco como funciona.
                ¿Sería muy complicado para acceder a una BD de Acces, que es lo que utilizo?
                En cuanto al código que aporta José María, tengo que revisarle porque algo debe de estar haciendo mal y me da errores.
                De nuevo gracias a los dos por vuestra ayuda y paciencia.
                Saludos

                Comentario


                • #9
                  Revisa, por favor, el código de csql = ... Porque no es el que escribí de primera intención, sino que lo he modificado más tarde. No sea que por ello no te funcione.
                  José María Movilla Cuadrado
                  ______________________
                  Normas del foro
                  www.foro.vb-mundo.com
                  www.vb-mundo.com

                  Comentario


                  • #10
                    Hola José María.
                    Si no lo he entendido mal, el nuevo código siguiendo tus orientaciones quedaría así:
                    Código:
                            Private Sub CogePendiente()
                            Dim ds As New DataSet
                            Dim dt As New DataTable
                    
                            If conn.State = ConnectionState.Closed Then
                                conn.Open()
                            End If
                    
                            csql = "SELECT CabecerasCompras.idProveedor, Proveedores.Empresa, Month(cabecerascompras.fecha) AS mes, Sum(CabecerasCompras.Importe) AS Importe "
                            csql += "FROM CabecerasCompras INNER JOIN Proveedores ON CabecerasCompras.idProveedor = Proveedores.idProveedor "
                            csql += " Where CabecerasCompras.Pagado = 0 "
                            csql += "GROUP BY CabecerasCompras.idProveedor, Proveedores.Empresa, Month(cabecerascompras.fecha) "
                            csql += " ORDER BY Proveedores.Empresa, Month(cabecerascompras.fecha)"
                    
                            Dim adp As New OleDb.OleDbDataAdapter(csql, conn)
                    
                            Try
                                ds.Tables.Add("tabla")
                                adp.Fill(ds.Tables("tabla"))
                                dtgCoge.DataSource = ds.Tables("tabla")
                                dtgCoge.DefaultCellStyle.Font = New Font("Verdana", 10)
                    
                                If dtgCoge.RowCount - 1 = 0 Then
                                    MsgBox("No se encontraron facturas" & vbCrLf & "de esta fecha")
                                End If
                            Catch ex As Exception
                                MsgBox(ex.ToString)
                            End Try
                            dtgPendiente.Columns.Clear()
                    
                            Dim cMeses As String
                            Dim nmes As Integer
                            Dim cantidad As Double = 0
                    
                            For i = 0 To dtgCoge.Rows.Count - 1
                                nmes = Val(dtgCoge.Rows(i).Cells(2).Value)
                                cantidad += dtgCoge.Rows(i).Cells(3).Value
                                cMeses = "enefebmarabrmayjunjulagosepoctnovdic"
                                csql = "INSERT INTO meses(IdPro, Mid(cMeses, 1 + (nmes - 1) * 3, 3) VALUES (@IdProv, @Cantidad)"
                                cmd.CommandText = csql
                                Try
                                    cmd.ExecuteNonQuery()
                                Catch ex As Exception
                                    MsgBox(ex.ToString)
                                End Try
                            Next
                        End Sub
                    me da

                    error de sintaxis en la instrucción INSERT INTO

                    en la línea

                    cmd.ExecuteNonQuery()


                    Sigo dándole vueltas al tema a ver si consigo algo.
                    Saludos de nuevo.


                    Comentario


                    • #11
                      Pon un STOP en la línea csql = "INSERT INTO... y comprueba cómo el segundo parámetro de meses va tomando las tres letras iniciales del mes correspondiente (ene, feb...)
                      Si no fuera así, revisa el por qué del error; pero si ese parámetro lo toma adecuadamente, el error te lo daría también con el bucle SELECT CASE.
                      José María Movilla Cuadrado
                      ______________________
                      Normas del foro
                      www.foro.vb-mundo.com
                      www.vb-mundo.com

                      Comentario


                      • #12
                        El problema está en que el proveedor OleDb no admite parámetros con nombre, deberás sustituir @IdProv y @Cantidad por ?, y luego asignarles el valor
                        Código:
                                Dim p As OleDb.OleDbParameter
                                p = New OleDb.OleDbParameter("@idProv", SqlDbType.Int)
                                p.Value = dtgCoge.Rows(i).Cells(0).Value
                                cmd.Parameters.Add(p)
                                p = New OleDb.OleDbParameter("@Cantidad", SqlDbType.Float)
                                p.Value = dtgCoge.Rows(i).Cells(3).Value
                                cmd.Parameters.Add(p)
                        Mas info:

                        https://msdn.microsoft.com/es-es/lib...v=vs.110).aspx

                        Edición:
                        El proveedor SqlClient es el proveedor nativo para acceso a bases de datos SQLServer, en este caso admite parámetros con nombre, pero eso y alguna que otra diferencia menor funciona como el resto de proveedores de acceso a datos de .Net
                        Una visita a las Normas del foro nunca viene mal

                        Comentario

                        Trabajando...
                        X