none
Ayuda-Demora mucho el insert y update con parametros RRS feed

  • Pregunta

  • Acudo nuevamente a ustedes, en un post anterior se me fue aclarada una duda en un insert con parametros y where, ahora la cuestion es la siguiente, es que demora al insertar en la tabla estando en blanco 18 minutos y al estar la tabla con registros demora mas todavia lo cual pienso yo no deberia demorar tanto tiempo, cabe destacar que son casi 100000 registros que se insertan pero creo que es mucho tiempo, aun asi estando ya la tabla con datos lo cual solo deberia comparar y agregar o actualizar segun consulta demora mas que si la tabla estuviera en blanco,aqui les dejo las consultas y mi codigo, espero me puedan ayudar ya que me preocupa esta situacion.de antemano muchas gracias.

    1-Insertar productos con moneda(CUP)

    INSERT INTO Fac_PrecioEstProducto
                             (idgrupo, idproducto, idmoneda, precio, PorcRecDesc, VolRecDesc)
    SELECT        @IdGrupo AS Expr1, idproducto, @IdMoneda AS Expr2, @Precio AS Expr3, @PorcRecDesc AS Expr4, @VolRecDesc AS Expr5
    FROM            gen_producto AS gp
    WHERE        (codigo = @Codigo) AND (NOT EXISTS
                                 (SELECT        1 AS Expr1
                                   FROM            Fac_PrecioEstProducto AS Fac_PrecioEstProducto_1
                                   WHERE        (gp.idproducto = idproducto) AND (idmoneda = @IdMoneda))) AND (idgrupo = @IdGrupo)

    2-Insertar productos con moneda(CUC)

    INSERT INTO Fac_PrecioEstProducto
                             (idgrupo, idproducto, idmoneda, precio, PorcRecDesc, VolRecDesc)
    SELECT        @IdGrupo AS Expr1, idproducto, @IdMoneda AS Expr2, @Precio AS Expr3, @PorcRecDesc AS Expr4, @VolRecDesc AS Expr5
    FROM            gen_producto AS gp
    WHERE        (codigo = @Codigo) AND (NOT EXISTS
                                 (SELECT        1 AS Expr1
                                   FROM            Fac_PrecioEstProducto AS Fac_PrecioEstProducto_1
                                   WHERE        (gp.idproducto = idproducto) AND (idmoneda = @IdMoneda))) AND (idgrupo = @IdGrupo)

    3-Actualizar precio segun si cambia de precio los productos importados y que existan en la tabla de la bd

    UPDATE       Fac_PrecioEstProducto
    SET                precio = @Precio
    WHERE        (precio > 0) AND (precio <> @Precio) AND (idproducto =
                                 (SELECT        idproducto
                                   FROM            gen_producto
                                   WHERE        (codigo = @Codigo))) AND (idmoneda = @IdMoneda)

    4-Aqui el codigo del boton Insert:

    Private Sub btninsertar_Click(sender As Object, e As EventArgs) Handles btninsertar.Click
            If cmbGrupo.Text = "" Or cmbMonedaCUP.Text = "" Or cmbMonedaCUC.Text = "" Or DataGridView1.RowCount = 0 Then
                MsgBox("Imposible continuar, faltan datos obligatorios (Importe el fichero o Revise Grupos y Monedas)", vbCritical, "ERROR")
            ElseIf cmbMonedaCUP.Text = cmbMonedaCUC.Text Then
                MsgBox("Las monedas no pueden ser iguales...Verifique", vbCritical, "ERROR")
            Else
                Try
                    Me.Cursor = Cursors.WaitCursor
                    For i = 0 To DataGridView1.Rows.Count - 1
                        Dim Producto As String
                        Dim PT As String
                        Producto = DataGridView1.Rows(i).Cells("Código").Value
                        PT = DataGridView1.Rows(i).Cells("PrecioT").Value.ToString
                        SqlConnection1.ConnectionString = "Server= " & Trim(frmLogin.txtServidor.Text) & ";Initial Catalog= " & Trim(frmLogin.txtBD.Text) & ";Uid= " & frmLogin.txtUser.Text & ";Pwd= " & Trim(frmLogin.txtpass.Text)
                        'inserta cup
                        InsertarCUP.Parameters.Item(0).Value = "" & cmbGrupo.SelectedValue & ""
                        InsertarCUP.Parameters.Item(1).Value = "" & cmbMonedaCUP.SelectedValue & ""
                        InsertarCUP.Parameters.Item(2).Value = "" & PT & ""
                        InsertarCUP.Parameters.Item(3).Value = "0"
                        InsertarCUP.Parameters.Item(4).Value = "0"
                        InsertarCUP.Parameters.Item(5).Value = "" & Producto & ""
                        'inserta cuc
                        InsertarCUC.Parameters.Item(0).Value = "" & cmbGrupo.SelectedValue & ""
                        InsertarCUC.Parameters.Item(1).Value = "" & cmbMonedaCUC.SelectedValue & ""
                        InsertarCUC.Parameters.Item(2).Value = "0"
                        InsertarCUC.Parameters.Item(3).Value = "0"
                        InsertarCUC.Parameters.Item(4).Value = "0"
                        InsertarCUC.Parameters.Item(5).Value = "" & Producto & ""
                        'actualizar
                        Actualizar.Parameters.Item(0).Value = "" & PT & ""
                        Actualizar.Parameters.Item(1).Value = "" & cmbMonedaCUP.SelectedValue & ""
                        Actualizar.Parameters.Item(2).Value = "" & Producto & ""
                        SqlConnection1.Open()
                        InsertarCUP.ExecuteNonQuery()
                        InsertarCUC.ExecuteNonQuery()
                        Actualizar.ExecuteNonQuery()
                        SqlConnection1.Close()
                    Next
                    Me.Cursor = Cursors.Default
                    MsgBox("Registros insertados y actualizados con exito", vbInformation, "INFORMACION")
                    SqlConnection1.Close()
                Catch ex As Exception
                    MsgBox(ex.Message)
                    Me.Cursor = Cursors.Default
                End Try
                SqlConnection1.Close()
            End If
        End Sub
    Espero me puedan aclarar.Salu2s

    miércoles, 26 de julio de 2017 15:36

Respuestas

  • Bueno pues estoy aqui, les dejo como fue que hice,la operacion demora menos de 30 segundos.les dejo el codigo y las consultas de los command para que vean, ya que me gusta usar los objetos asi me ahorro tener que escribir tanto,al final es POO, no se si sera buena tecnica, pero me gusta usar los objetos del VB.Salu2s

    Private Sub btninsertar_Click(sender As Object, e As EventArgs) Handles btninsertar.Click
            If cmbGrupo.Text = "" Or cmbMonedaCUP.Text = "" Or cmbMonedaCUC.Text = "" Or DataGridView1.RowCount = 0 Then
                MsgBox("Imposible continuar, faltan datos obligatorios (Importe el fichero o Revise Grupos y Monedas)", vbCritical, "ERROR")
            ElseIf cmbMonedaCUP.Text = cmbMonedaCUC.Text Then
                MsgBox("Las monedas no pueden ser iguales...Verifique", vbCritical, "ERROR")
            Else
                Try
                    tablapt() ' creo la tabla
                    Me.Cursor = Cursors.WaitCursor
                    SqlConnection1.ConnectionString = "Server= " & Trim(frmLogin.txtServidor.Text) & ";Initial Catalog= " & Trim(frmLogin.txtBD.Text) & ";Uid= " & frmLogin.txtUser.Text & ";Pwd= " & Trim(frmLogin.txtpass.Text)
                    SqlConnection1.Open()
                    For Each row As DataGridViewRow In DataGridView1.Rows
                        'inserto en la tabla temporal(Parametros y Ejecucion)
                        InsertTablaTemp.Parameters.Item(0).Value = "" & cmbGrupo.SelectedValue & ""
                        InsertTablaTemp.Parameters.Item(1).Value = "" & cmbMonedaCUP.SelectedValue & ""
                        InsertTablaTemp.Parameters.Item(2).Value = "" & cmbMonedaCUC.SelectedValue & ""
                        InsertTablaTemp.Parameters.Item(3).Value = "" & row.Cells("PrecioT").Value & ""
                        InsertTablaTemp.Parameters.Item(4).Value = "" & row.Cells("Código").Value & ""
                        InsertTablaTemp.ExecuteNonQuery()
                    Next
                    'parametros del insert de la moneda cup
                    InsertarCUP.Parameters.Item(0).Value = "0"
                    InsertarCUP.Parameters.Item(1).Value = "0"
                    'parametros del insert de la moneda cuc
                    InsertarCUC.Parameters.Item(0).Value = "0"
                    InsertarCUC.Parameters.Item(1).Value = "0"
                    InsertarCUC.Parameters.Item(2).Value = "0"
                    'ejecuto cunsulta update
                    Actualizar.ExecuteNonQuery()
                    'ejecuto consulta insert cup
                    InsertarCUP.ExecuteNonQuery()
                    'ejecuto consulta insert cuc
                    InsertarCUC.ExecuteNonQuery()
                    'borro la tabla
                    Dim borrotabla As New SqlCommand("If exists(select * from dbo.sysobjects where id = object_id(N'[dbo].[PrecioTopado]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
                    drop table [dbo].[PrecioTopado]", SqlConnection1)
                    borrotabla.ExecuteNonQuery()
                    Me.Cursor = Cursors.Default
                    MsgBox("Registros insertados y actualizados con exito", vbInformation, "INFORMACION")
                    'limpio los combobox y el datagridview
                    cmbGrupo.Text = Nothing
                    cmbMonedaCUP.Text = Nothing
                    cmbMonedaCUC.Text = Nothing
                    DataGridView1.DataSource = Nothing
                    SqlConnection1.Close()
                Catch ex As Exception
                    MsgBox(ex.Message)
                    Me.Cursor = Cursors.Default
                    SqlConnection1.Close()
                End Try
            End If
            SqlConnection1.Close()
        End Sub

    aqui las consultas:

    1-Crear tablapt que lo llamo desde un modulo que tengo donde ahi tengo todas las operaciones para crear o borrar tablas:

    Public Sub tablapt()
            'tabla para la importacion de los precios topados
            Try
                Dim tab As String = "If exists(select * from dbo.sysobjects where id = object_id(N'[dbo].[PrecioTopado]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
    drop table [dbo].[PrecioTopado]
                CREATE TABLE [dbo].[PrecioTopado] (
    [idproducto] [Int] Not NULL,    
        [idgrupo] [Int] Not NULL ,
        [idmonedacup] [Int] Not NULL ,
        [idmonedacuc] [Int] Not NULL ,
        [precio] [numeric](18, 6) Not NULL ,
    ) ON [PRIMARY]"
                Dim cmd As New SqlCommand(tab, sql1)
                sql1.Open()
                cmd.ExecuteNonQuery()
                sql1.Close()
            Catch ex As Exception
                MsgBox(ex.Message)
                sql1.Close()
            End Try
            sql1.Close()
        End Sub

    2-Consulta de InsertTablaTemp:

    INSERT INTO PrecioTopado
                             (idproducto, idgrupo, idmonedacup, idmonedacuc, precio)
    SELECT        idproducto, @idgrupo AS Expr1, @idmonedacup AS Expr2, @idmonedacuc AS Expr3, @Precio AS Expr4
    FROM            gen_producto AS gp
    WHERE        EXISTS
                                 (SELECT        idproducto
                                   FROM            gen_producto
                                   WHERE        (gp.codigo = @Codigo))

    3-Consulta de InsertarCUP:

    INSERT INTO Fac_PrecioEstProducto
                             (idproducto, idgrupo, idmoneda, precio, PorcRecDesc, VolRecDesc)
    SELECT        PrecioTopado.idproducto, PrecioTopado.idgrupo, PrecioTopado.idmonedacup, PrecioTopado.precio, @PorcRecDesc AS Expr1, @VolRecDesc AS Expr2
    FROM            gen_producto AS gp INNER JOIN
                             PrecioTopado ON gp.idproducto = PrecioTopado.idproducto
    WHERE        (NOT EXISTS
                                 (SELECT        1 AS Expr1
                                   FROM            Fac_PrecioEstProducto AS Fac_PrecioEstProducto_1
                                   WHERE        (gp.idproducto = idproducto) AND (PrecioTopado.idmonedacup = idmoneda)))

    4-Consulta de InsertarCUC:

    INSERT INTO Fac_PrecioEstProducto
                             (idproducto, idgrupo, idmoneda, precio, PorcRecDesc, VolRecDesc)
    SELECT        PrecioTopado.idproducto, PrecioTopado.idgrupo, PrecioTopado.idmonedacuc, @Precio AS Expr3, @PorcRecDesc AS Expr1, @VolRecDesc AS Expr2
    FROM            gen_producto AS gp INNER JOIN
                             PrecioTopado ON gp.idproducto = PrecioTopado.idproducto
    WHERE        (NOT EXISTS
                                 (SELECT        1 AS Expr1
                                   FROM            Fac_PrecioEstProducto AS Fac_PrecioEstProducto_1
                                   WHERE        (gp.idproducto = idproducto) AND (PrecioTopado.idmonedacuc = idmoneda)))

    5-Consulta de Actualizar(Update):

    UPDATE       Fac_PrecioEstProducto
    SET                precio = PrecioTopado.precio
    FROM            Fac_PrecioEstProducto INNER JOIN
                             PrecioTopado ON Fac_PrecioEstProducto.idmoneda = PrecioTopado.idmonedacup AND Fac_PrecioEstProducto.idproducto = PrecioTopado.idproducto

    -asi no se demora ni 30 segundos y funciona a la perfeccion.Muchas gracias a los que me respondieron, doy por cerrado este post.Salu2s

    • Marcado como respuesta PedroJ2017 jueves, 27 de julio de 2017 15:23
    jueves, 27 de julio de 2017 15:19

Todas las respuestas

  • hola ...

    Bueno lo que pasa es que estas usando un metodo poco eficiente para insertar los registros , fijate si son 100000 mil registros y los estas insertando 1 a 1 son 100000 veces q vas contra DB...

    Fijate este ejemplo como actualizo datos

    Public Sub ActualizarEnCurvasSqlBulk(dt As DataTable)
                Using destinationConnection(0 To "CnxCervix" - 1) As SqlConnection
                    destinationConnection.Open()
                    Dim consultaSQL As String = "CREATE TABLE [CERVIX].[dbo].[TEMPTABLE]( CCU_ORDEN int, CCU_T_REGISTRO VARCHAR(1),CCU_FECHA_REGISTRO DATE, CCU_CURVA VARCHAR(6), CCU_DIAS real, CCU_SIGNO1 VARCHAR(1), CCU_VALOR real, CCU_SIGNO2 VARCHAR(1), CCU_RENTABILIDAD real)"
                    Dim cmd = new SqlCommand(consultaSQL, destinationConnection)
                    cmd.ExecuteNonQuery()
                    Using bulkCopy As New SqlBulkCopy(destinationConnection.ConnectionString)
                        bulkCopy.DestinationTableName = "[CERVIX].[dbo].[TEMPTABLE]"
                        bulkCopy.WriteToServer(dt)
    
                    End using
                    cmd.CommandText = "UPDATE  T1 SET
                                                       T1.CCU_T_REGISTRO = T2.CCU_T_REGISTRO, T1.CCU_FECHA_REGISTRO = T2.CCU_FECHA_REGISTRO, 
                                                       T1.CCU_CURVA = T2.CCU_CURVA ,T1.CCU_DIAS = T2.CCU_DIAS, T1.CCU_SIGNO1 = T2.CCU_SIGNO1,T1.CCU_VALOR = T2.CCU_VALOR, 
                                                       T1.CCU_SIGNO2 = T2.CCU_SIGNO2,T1.CCU_RENTABILIDAD = T2.CCU_RENTABILIDAD 
                                       FROM  [CERVIX].[dbo].[CVX_CAR_CURVAS] AS T1 INNER JOIN [CERVIX].[dbo].[TEMPTABLE] AS T2 ON T1.CCU_ORDEN = T2.CCU_ORDEN; 
                                       DROP TABLE [CERVIX].[dbo].[TEMPTABLE]"
                    cmd.ExecuteNonQuery()
                    destinationConnection.Close()
    
                End using
    
            End Sub
    
    


    EFRAIN MEJIAS C VALENCIA - VENEZUELA

    miércoles, 26 de julio de 2017 15:52
  • Hola: 

     Pero claro que va a demorar, observa que por cada Row del DataGridView declaras las variables, haces la conexión, tomas los valores del control, agregas valores a los parámetros, etc, esto no debería de ser así.

     La conexión debes de declararla fuera del ciclo, en el ciclo solo debes de insert agregando valores a los parámetros  y ejecutado el comando, previamente establecida la conexión y creadas las consultas.

    Te dejo un ejemplo de como es que debería de ser tu estructura de código para hacer el insert:

    Public Sub Insert(productos As List(Of Model_Producto))
    	'Creamos nuestro objeto de conexion usando nuestro archivo de configuraciones
    	Using cnx As New MySqlConnection(ConfigurationManager.ConnectionStrings("cnnString").ToString())
    		cnx.Open()
    		'Declaramos nuestra consulta de Acción Sql parametrizada
    		Const  sqlQuery As String = "INSERT INTO Producto (Descripcion, Marca, Precio) VALUES (@descripcion, @marca, @precio)"
    		Using cmd As New MySqlCommand(sqlQuery, cnx)
    			'recorremos el objeto List
    			For Each item As var In productos
    				'Limpiamos el cmd para poder agregar nuevos parametros
    				cmd.Clear()
    
    				cmd.Parameters.AddWithValue("@descripcion", producto.Descripcion)
    				cmd.Parameters.AddWithValue("@marca", producto.Marca)
    				cmd.Parameters.AddWithValue("@precio", producto.Precio)
    				'Ejecutamos el command
    				'un consejo que podria serte de mucha utilidad, encierra este codigo en una Transaction
    				'por si acaso un insert llegase a fallar, automaticamente se haga un RollBack de los si insertados
    				'y de esta forma no afectaras la BD con inserciones a medias
    				cmd.ExecuteNonQuery()
    			Next
    		End Using
    	End Using
    End Sub
    En este ejemplo se utiliza un objeto del tipo List que contiene una instancia de la clase Producto, en tu caso podrías recorrer directamente el DataGridView e ir fijando los valores a los parámetros.


    Saludos desde Monterrey, Nuevo León, México!!!

    miércoles, 26 de julio de 2017 16:02
  • Efrain mejias la verdad no entiendo mucho tu codigo, debe ser debido a mi novatez, en cuanto a jose luis mas o menos entendi pero no del todo ahora deje mi codigo asi,,pero aun asi sigue demorando,me puedes ser mas especifico en cuanto a mis datos,solo si no es molestias,,desde ya muchas gracias:

     Private Sub btninsertar_Click(sender As Object, e As EventArgs) Handles btninsertar.Click
            If cmbGrupo.Text = "" Or cmbMonedaCUP.Text = "" Or cmbMonedaCUC.Text = "" Or DataGridView1.RowCount = 0 Then
                MsgBox("Imposible continuar, faltan datos obligatorios (Importe el fichero o Revise Grupos y Monedas)", vbCritical, "ERROR")
            ElseIf cmbMonedaCUP.Text = cmbMonedaCUC.Text Then
                MsgBox("Las monedas no pueden ser iguales...Verifique", vbCritical, "ERROR")
            Else
                Try
                    Me.Cursor = Cursors.WaitCursor
                    SqlConnection1.ConnectionString = "Server= " & Trim(frmLogin.txtServidor.Text) & ";Initial Catalog= " & Trim(frmLogin.txtBD.Text) & ";Uid= " & frmLogin.txtUser.Text & ";Pwd= " & Trim(frmLogin.txtpass.Text)
                    SqlConnection1.Open()
                    For Each row As DataGridViewRow In DataGridView1.Rows
    
                        'inserta cup
                        InsertarCUP.Parameters.Item(0).Value = "" & cmbGrupo.SelectedValue & ""
                        InsertarCUP.Parameters.Item(1).Value = "" & cmbMonedaCUP.SelectedValue & ""
                        InsertarCUP.Parameters.Item(2).Value = "" & row.Cells("PrecioT").Value & ""
                        InsertarCUP.Parameters.Item(3).Value = "0"
                        InsertarCUP.Parameters.Item(4).Value = "0"
                        InsertarCUP.Parameters.Item(5).Value = "" & row.Cells("Código").Value & ""
                        InsertarCUP.ExecuteNonQuery()
                    Next
                    For Each row As DataGridViewRow In DataGridView1.Rows
                        'inserta cuc
                        InsertarCUC.Parameters.Item(0).Value = "" & cmbGrupo.SelectedValue & ""
                        InsertarCUC.Parameters.Item(1).Value = "" & cmbMonedaCUC.SelectedValue & ""
                        InsertarCUC.Parameters.Item(2).Value = "0"
                        InsertarCUC.Parameters.Item(3).Value = "0"
                        InsertarCUC.Parameters.Item(4).Value = "0"
                        InsertarCUC.Parameters.Item(5).Value = "" & row.Cells("Código").Value & ""
                        InsertarCUC.ExecuteNonQuery()
                    Next
                    For Each row As DataGridViewRow In DataGridView1.Rows
                        'actualizar
                        Actualizar.Parameters.Item(0).Value = "" & row.Cells("PrecioT").Value & ""
                        Actualizar.Parameters.Item(1).Value = "" & cmbMonedaCUP.SelectedValue & ""
                        Actualizar.Parameters.Item(2).Value = "" & cmbGrupo.SelectedValue & ""
                        Actualizar.Parameters.Item(3).Value = "" & row.Cells("Código").Value & ""
                        Actualizar.ExecuteNonQuery()
                    Next
                    Me.Cursor = Cursors.Default
                    MsgBox("Registros insertados y actualizados con exito", vbInformation, "INFORMACION")
                    SqlConnection1.Close()
                Catch ex As Exception
                    MsgBox(ex.Message)
                    Me.Cursor = Cursors.Default
                End Try
                SqlConnection1.Close()
            End If
        End Sub

    y mis consultas,revisenla a ver,no creo que el problema sea ahi pero bueno:

    1-inserta cup

    INSERT INTO Fac_PrecioEstProducto
                             (idgrupo, idproducto, idmoneda, precio, PorcRecDesc, VolRecDesc)
    SELECT        @IdGrupo AS Expr1, gp.idproducto, @IdMoneda AS Expr2, @Precio AS Expr3, @PorcRecDesc AS Expr4, @VolRecDesc AS Expr5
    FROM            gen_producto AS gp CROSS JOIN
                             Fac_PrecioEstProducto AS Fac_PrecioEstProducto_2
    WHERE        (gp.codigo = @Codigo) AND (NOT EXISTS
                                 (SELECT        1 AS Expr1
                                   FROM            Fac_PrecioEstProducto AS Fac_PrecioEstProducto_1
                                   WHERE        (gp.idproducto = idproducto) AND (idmoneda = @IdMoneda))) AND (Fac_PrecioEstProducto_2.idgrupo = @IdGrupo)

    2-Inserta CUC

    INSERT INTO Fac_PrecioEstProducto
                             (idgrupo, idproducto, idmoneda, precio, PorcRecDesc, VolRecDesc)
    SELECT        @IdGrupo AS Expr1, gp.idproducto, @IdMoneda AS Expr2, @Precio AS Expr3, @PorcRecDesc AS Expr4, @VolRecDesc AS Expr5
    FROM            gen_producto AS gp CROSS JOIN
                             Fac_PrecioEstProducto AS Fac_PrecioEstProducto_2
    WHERE        (gp.codigo = @Codigo) AND (NOT EXISTS
                                 (SELECT        1 AS Expr1
                                   FROM            Fac_PrecioEstProducto AS Fac_PrecioEstProducto_1
                                   WHERE        (gp.idproducto = idproducto) AND (idmoneda = @IdMoneda))) AND (Fac_PrecioEstProducto_2.idgrupo = @IdGrupo)

    3-actualizo

    UPDATE       Fac_PrecioEstProducto
    SET                precio = @Precio
    WHERE        (precio > 0) AND (precio <> @Precio) AND (idproducto =
                                 (SELECT        idproducto
                                   FROM            gen_producto
                                   WHERE        (codigo = @Codigo))) AND (idmoneda = @IdMoneda) AND (idgrupo = @IdGrupo)

    recuerden que tengo que hacer esos tres procesos o sea los 2 insert y el update, no es uno solo

    salu2s

    miércoles, 26 de julio de 2017 16:44
  • lo probe ahora en la bd que tengo en sql2005 y demora solo 6 minutos que aun asi sigue demorando,cabe aclarar que la bd original de mi empresa esta en sql2000sp4 y demora 30 minutos ahora una cosa mas es que noto que cuando la tabla ya tiene registros cuando buelvo a hacer el insert y update se demora mas que cuando no tiene registros, a que se debe esto
    miércoles, 26 de julio de 2017 17:33
  • Son muchas las operaciones que ejecutas de una en una, y aunque no es la forma tampoco ayuda la manera como tienes escritas las consultas de acción. Te propongo un primer cambio y sobre los resultados vamos refinando los mecanismos.

    Vamos a ejecutar una sola consulta por ciclo conteniendo las tres operaciones (en realidad son sólo dos operaciones que viendo el código ya te darás cuenta a que me refiero)

    - Consulta SQL

    DECLARE @idproducto int = (SELECT idproducto FROM gen_producto WHERE codigo = @Codigo);
    INSERT INTO Fac_PrecioEstProducto
        (idgrupo, idproducto, idmoneda, precio, PorcRecDesc, VolRecDesc)
    SELECT        
        @IdGrupo, gp.idproducto, @IdMoneda, r.precio, r.PorcRecDesc, r.VolRecDesc
    FROM            
        gen_producto AS gp
        CROSS APPLY (VALUES (@Precio, 0, 0), (0, 0, 0)) r (precio, PorcRecDesc, VolRecDesc)
    WHERE        
        gp.codigo = @Codigo 
        AND NOT EXISTS (
    	   SELECT 1 FROM Fac_PrecioEstProducto 
    	   WHERE idproducto = gp.idproducto AND idmoneda = @IdMoneda AND idgrupo = @IdGrupo);
    UPDATE  Fac_PrecioEstProducto
    SET	   precio = @Precio
    WHERE   precio > 0 AND precio <> @Precio AND idproducto = @idproducto 
    	   AND idmoneda = @IdMoneda AND idgrupo = @IdGrupo
    GO


    - Aplicación

    Try
    	Me.Cursor = Cursors.WaitCursor
    
    	Using Conn As New SqlConnection("Cadena de conexión")
    		Conn.Open()
    
    		Dim ConsultaSQL = "Pegar aquí consulta SQL completa"
    
    		For Each row As DataGridViewRow In DataGridView1.Rows
    			Dim cmd As New SqlCommand(ConsultaSQL, Conn)
    
    			cmd.Parameters.AddWithValue("@IdGrupo", cmbGrupo.SelectedValue)
    			cmd.Parameters.AddWithValue("@IdMoneda", cmbMonedaCUP.SelectedValue)
    			cmd.Parameters.AddWithValue("@Precio", row.Cells("PrecioT").Value)
    			cmd.Parameters.AddWithValue("@Codigo", row.Cells("Código").Value)
    
    			cmd.ExecuteNonQuery()
    		Next
    
    	End Using
    
    	MsgBox("Registros insertados y actualizados con exito", vbInformation, "INFORMACION")
    
    	Me.Cursor = Cursors.Default
    Catch ex As Exception
    	MsgBox(ex.Message)
    End Try

    Ejecuta sobre la versión 2005 de SQL Server y coméntanos los resultados.


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.

    miércoles, 26 de julio de 2017 18:05
  • voy a probar y te cuento, aunque veo que solo indicas un idmoneda, el valor del cmbmonedacup y tienen que ser dos valores o sea el id en moneda cup y el id en monecuc(cmbmonedacuc) o sea serian dos registros por cada idproducto uno con el id moneda cup que tiene precio, y el otro id moneda cuc que el precio es 0.voy a probar y te cuento.
    miércoles, 26 de julio de 2017 18:32
  • cuando ejecuto me salta este error:

    Sintaxis incorrecta cerca de '('.

    Sintaxis incorrecta cerca de la palabra clave 'VALUES'.

    Debe declarar la variable escalar "@idproducto".

    el codigo lo tengo asi:

     Private Sub btninsertar_Click(sender As Object, e As EventArgs) Handles btninsertar.Click
            If cmbGrupo.Text = "" Or cmbMonedaCUP.Text = "" Or cmbMonedaCUC.Text = "" Or DataGridView1.RowCount = 0 Then
                MsgBox("Imposible continuar, faltan datos obligatorios (Importe el fichero o Revise Grupos y Monedas)", vbCritical, "ERROR")
            ElseIf cmbMonedaCUP.Text = cmbMonedaCUC.Text Then
                MsgBox("Las monedas no pueden ser iguales...Verifique", vbCritical, "ERROR")
            Else
                Try
                    Me.Cursor = Cursors.WaitCursor
                    SqlConnection1.ConnectionString = "Server= " & Trim(frmLogin.txtServidor.Text) & ";Initial Catalog= " & Trim(frmLogin.txtBD.Text) & ";Uid= " & frmLogin.txtUser.Text & ";Pwd= " & Trim(frmLogin.txtpass.Text)
                    SqlConnection1.Open()
                    Dim str = "DECLARE @idproducto int = (SELECT idproducto FROM gen_producto WHERE codigo = @Codigo);
    INSERT INTO Fac_PrecioEstProducto
        (idgrupo, idproducto, idmoneda, precio, PorcRecDesc, VolRecDesc)
    SELECT        
        @IdGrupo, gp.idproducto, @IdMoneda, r.precio, r.PorcRecDesc, r.VolRecDesc
    FROM            
        gen_producto AS gp
        CROSS APPLY (VALUES (@Precio, 0, 0), (0, 0, 0)) r (precio, PorcRecDesc, VolRecDesc)
    WHERE        
        gp.codigo = @Codigo 
        AND NOT EXISTS (
    	   SELECT 1 FROM Fac_PrecioEstProducto 
    	   WHERE idproducto = gp.idproducto AND idmoneda = @IdMoneda AND idgrupo = @IdGrupo);
    UPDATE  Fac_PrecioEstProducto
    SET	   precio = @Precio
    WHERE   precio > 0 AND precio <> @Precio AND idproducto = @idproducto 
    	   AND idmoneda = @IdMoneda AND idgrupo = @IdGrupo
    GO"
                    For Each row As DataGridViewRow In DataGridView1.Rows
                        Dim cmd As New SqlCommand(str, SqlConnection1)
                        cmd.Parameters.AddWithValue("@IdGrupo", cmbGrupo.SelectedValue)
                        cmd.Parameters.AddWithValue("@IdMoneda", cmbMonedaCUP.SelectedValue)
                        cmd.Parameters.AddWithValue("@Precio", row.Cells("PrecioT").Value)
                        cmd.Parameters.AddWithValue("@Codigo", row.Cells("Código").Value)
    
                        cmd.ExecuteNonQuery()
                    Next
                    Me.Cursor = Cursors.Default
                    MsgBox("Registros insertados y actualizados con exito", vbInformation, "INFORMACION")
                    SqlConnection1.Close()
                Catch ex As Exception
                    MsgBox(ex.Message)
                    Me.Cursor = Cursors.Default
                    SqlConnection1.Close()
                End Try
                SqlConnection1.Close()
            End If
        End Sub

    miércoles, 26 de julio de 2017 18:37
  • ¿Qué nivel de compatibilidad tiene tu base de datos en la instancia de SQL Server 2005? ¿80? ¿90?

    Si tienes un nivel de compatibilidad 80 entonces no va a reconocer la instrucción CROSS APPLY.

    Vamos de otra manera para que pueda funcionar -incluso en la versión 2000- y aprovechamos en corregir el caso de los valores distintos de moneda.

    - Consulta

    DECLARE @idproducto int
    SET @idproducto = (SELECT idproducto FROM gen_producto WHERE codigo = @Codigo)
    INSERT INTO Fac_PrecioEstProducto 
        (idgrupo, idproducto, idmoneda, precio, PorcRecDesc, VolRecDesc)
    SELECT @IdGrupo, gp.idproducto, @IdMonedaCUP, @Precio, 0, 0
    FROM gen_producto AS gp WHERE gp.codigo = @Codigo AND NOT EXISTS (
    	   SELECT 1 FROM Fac_PrecioEstProducto 
    	   WHERE idproducto = gp.idproducto AND idmoneda = @IdMoneda AND idgrupo = @IdGrupo)
    UNION ALL
    SELECT @IdGrupo, gp.idproducto, @IdMonedaCUC, 0, 0, 0
    FROM gen_producto AS gp WHERE gp.codigo = @Codigo AND NOT EXISTS (
    	   SELECT 1 FROM Fac_PrecioEstProducto 
    	   WHERE idproducto = gp.idproducto AND idmoneda = @IdMoneda AND idgrupo = @IdGrupo)
    UPDATE Fac_PrecioEstProducto SET precio = @Precio WHERE precio > 0 AND precio <> @Precio 
    AND idproducto = @idproducto AND idmoneda = @IdMoneda AND idgrupo = @IdGrupo
    

    - Aplicación

    Dim ConsultaSQL = "Pegar aquí consulta completa"
    
    For Each row As DataGridViewRow In DataGridView1.Rows
    	Dim cmd As New SqlCommand(ConsultaSQL, Conn)
    
    	cmd.Parameters.AddWithValue("@IdGrupo", cmbGrupo.SelectedValue)
    	cmd.Parameters.AddWithValue("@IdMonedaCUP", cmbMonedaCUP.SelectedValue)
    	cmd.Parameters.AddWithValue("@IdMonedaCUC", cmbMonedaCUC.SelectedValue)
    	cmd.Parameters.AddWithValue("@Precio", row.Cells("PrecioT").Value)
    	cmd.Parameters.AddWithValue("@Codigo", row.Cells("Código").Value)
    
    	cmd.ExecuteNonQuery()
    Next


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.
    miércoles, 26 de julio de 2017 18:53
  • voy a probar ahora mismo aunque te hago una correcion:

    UNION ALL
    SELECT @IdGrupo, gp.idproducto, @IdMonedaCUC, 0, 0, 0
    FROM gen_producto AS gp WHERE gp.codigo = @Codigo AND NOT EXISTS (
    	   SELECT 1 FROM Fac_PrecioEstProducto 
    	   WHERE idproducto = gp.idproducto AND idmoneda = @IdMoneda(aqui debe ir @IdMonedaCUC) AND idgrupo = @IdGrupo)
    UPDATE Fac_PrecioEstProducto SET precio = @Precio WHERE precio > 0 AND precio <> @Precio 
    AND idproducto = @idproducto AND idmoneda = @IdMoneda(y aqui @IdMonedaCUP porque el update solo va a valer en la moneda cup,dime si estoy en lo cierto) AND idgrupo = @IdGrupo

    miércoles, 26 de julio de 2017 19:04
  • Si, has las correctivas que consideres oportunas, ese cambio hazlo en las dos consultas de selección y en la consulta de actualización que en los tres casos está como @idMoneda


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.
    miércoles, 26 de julio de 2017 19:07
  • si ya hice los cambio,pero ahora estoy notando que se va a demorar mas ya va por 5minutos y a añadido solamente 26430 registros de un total aproximadamente 94000.que pasara..aunque se que la consulta es algo compleja ya que tiene que comparar varios datos..uff..esto me tiene loco ya..
    miércoles, 26 de julio de 2017 19:12
  • se demoro 15 minutos en añadir 78672 registros.uff y fue en sql2005 no quiero ni probar en 2000. ya no se ni que hacer,no se si es que se demorara asi o hay algo mal..
    miércoles, 26 de julio de 2017 19:22
  • Tengo una sugerencia a ver que dicen:

    Tengo pensado crear una tabla temporal con las columnas (codigo, idgrupo, idmonedacup, idmonedacuc, PorcRecDesc, VolRecDesc) donde codigo lo voy a sacar del archivo que importo, el grupo del que selecciono en el cmbgrupo, el idmonedacup el que selecciono en el cmbmonedacup, el idmonedacuc del que selecciono en cmbmonedacuc, y los otros dos valores en 0.donde hare un insert con esos datos en la tabla temporal, luego de ahi hago el insert y update a la tabla fac_precioestproducto solo comparando el codigo de la tabla temporal con la de gen producto y que me inserte el que no exista y me actualize el que haya cambiado el precio,no se si sera lo mismo,pero bueno,,que me recomiendan

    miércoles, 26 de julio de 2017 19:30
  • tengo que salir ahora de momento,cuando regrese les comento lo que hice.no demora ni 20 segundos en hacer la operacion..gracias.hasta mas tarde.salu2s
    miércoles, 26 de julio de 2017 20:34
  • Bueno pues estoy aqui, les dejo como fue que hice,la operacion demora menos de 30 segundos.les dejo el codigo y las consultas de los command para que vean, ya que me gusta usar los objetos asi me ahorro tener que escribir tanto,al final es POO, no se si sera buena tecnica, pero me gusta usar los objetos del VB.Salu2s

    Private Sub btninsertar_Click(sender As Object, e As EventArgs) Handles btninsertar.Click
            If cmbGrupo.Text = "" Or cmbMonedaCUP.Text = "" Or cmbMonedaCUC.Text = "" Or DataGridView1.RowCount = 0 Then
                MsgBox("Imposible continuar, faltan datos obligatorios (Importe el fichero o Revise Grupos y Monedas)", vbCritical, "ERROR")
            ElseIf cmbMonedaCUP.Text = cmbMonedaCUC.Text Then
                MsgBox("Las monedas no pueden ser iguales...Verifique", vbCritical, "ERROR")
            Else
                Try
                    tablapt() ' creo la tabla
                    Me.Cursor = Cursors.WaitCursor
                    SqlConnection1.ConnectionString = "Server= " & Trim(frmLogin.txtServidor.Text) & ";Initial Catalog= " & Trim(frmLogin.txtBD.Text) & ";Uid= " & frmLogin.txtUser.Text & ";Pwd= " & Trim(frmLogin.txtpass.Text)
                    SqlConnection1.Open()
                    For Each row As DataGridViewRow In DataGridView1.Rows
                        'inserto en la tabla temporal(Parametros y Ejecucion)
                        InsertTablaTemp.Parameters.Item(0).Value = "" & cmbGrupo.SelectedValue & ""
                        InsertTablaTemp.Parameters.Item(1).Value = "" & cmbMonedaCUP.SelectedValue & ""
                        InsertTablaTemp.Parameters.Item(2).Value = "" & cmbMonedaCUC.SelectedValue & ""
                        InsertTablaTemp.Parameters.Item(3).Value = "" & row.Cells("PrecioT").Value & ""
                        InsertTablaTemp.Parameters.Item(4).Value = "" & row.Cells("Código").Value & ""
                        InsertTablaTemp.ExecuteNonQuery()
                    Next
                    'parametros del insert de la moneda cup
                    InsertarCUP.Parameters.Item(0).Value = "0"
                    InsertarCUP.Parameters.Item(1).Value = "0"
                    'parametros del insert de la moneda cuc
                    InsertarCUC.Parameters.Item(0).Value = "0"
                    InsertarCUC.Parameters.Item(1).Value = "0"
                    InsertarCUC.Parameters.Item(2).Value = "0"
                    'ejecuto cunsulta update
                    Actualizar.ExecuteNonQuery()
                    'ejecuto consulta insert cup
                    InsertarCUP.ExecuteNonQuery()
                    'ejecuto consulta insert cuc
                    InsertarCUC.ExecuteNonQuery()
                    'borro la tabla
                    Dim borrotabla As New SqlCommand("If exists(select * from dbo.sysobjects where id = object_id(N'[dbo].[PrecioTopado]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
                    drop table [dbo].[PrecioTopado]", SqlConnection1)
                    borrotabla.ExecuteNonQuery()
                    Me.Cursor = Cursors.Default
                    MsgBox("Registros insertados y actualizados con exito", vbInformation, "INFORMACION")
                    'limpio los combobox y el datagridview
                    cmbGrupo.Text = Nothing
                    cmbMonedaCUP.Text = Nothing
                    cmbMonedaCUC.Text = Nothing
                    DataGridView1.DataSource = Nothing
                    SqlConnection1.Close()
                Catch ex As Exception
                    MsgBox(ex.Message)
                    Me.Cursor = Cursors.Default
                    SqlConnection1.Close()
                End Try
            End If
            SqlConnection1.Close()
        End Sub

    aqui las consultas:

    1-Crear tablapt que lo llamo desde un modulo que tengo donde ahi tengo todas las operaciones para crear o borrar tablas:

    Public Sub tablapt()
            'tabla para la importacion de los precios topados
            Try
                Dim tab As String = "If exists(select * from dbo.sysobjects where id = object_id(N'[dbo].[PrecioTopado]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
    drop table [dbo].[PrecioTopado]
                CREATE TABLE [dbo].[PrecioTopado] (
    [idproducto] [Int] Not NULL,    
        [idgrupo] [Int] Not NULL ,
        [idmonedacup] [Int] Not NULL ,
        [idmonedacuc] [Int] Not NULL ,
        [precio] [numeric](18, 6) Not NULL ,
    ) ON [PRIMARY]"
                Dim cmd As New SqlCommand(tab, sql1)
                sql1.Open()
                cmd.ExecuteNonQuery()
                sql1.Close()
            Catch ex As Exception
                MsgBox(ex.Message)
                sql1.Close()
            End Try
            sql1.Close()
        End Sub

    2-Consulta de InsertTablaTemp:

    INSERT INTO PrecioTopado
                             (idproducto, idgrupo, idmonedacup, idmonedacuc, precio)
    SELECT        idproducto, @idgrupo AS Expr1, @idmonedacup AS Expr2, @idmonedacuc AS Expr3, @Precio AS Expr4
    FROM            gen_producto AS gp
    WHERE        EXISTS
                                 (SELECT        idproducto
                                   FROM            gen_producto
                                   WHERE        (gp.codigo = @Codigo))

    3-Consulta de InsertarCUP:

    INSERT INTO Fac_PrecioEstProducto
                             (idproducto, idgrupo, idmoneda, precio, PorcRecDesc, VolRecDesc)
    SELECT        PrecioTopado.idproducto, PrecioTopado.idgrupo, PrecioTopado.idmonedacup, PrecioTopado.precio, @PorcRecDesc AS Expr1, @VolRecDesc AS Expr2
    FROM            gen_producto AS gp INNER JOIN
                             PrecioTopado ON gp.idproducto = PrecioTopado.idproducto
    WHERE        (NOT EXISTS
                                 (SELECT        1 AS Expr1
                                   FROM            Fac_PrecioEstProducto AS Fac_PrecioEstProducto_1
                                   WHERE        (gp.idproducto = idproducto) AND (PrecioTopado.idmonedacup = idmoneda)))

    4-Consulta de InsertarCUC:

    INSERT INTO Fac_PrecioEstProducto
                             (idproducto, idgrupo, idmoneda, precio, PorcRecDesc, VolRecDesc)
    SELECT        PrecioTopado.idproducto, PrecioTopado.idgrupo, PrecioTopado.idmonedacuc, @Precio AS Expr3, @PorcRecDesc AS Expr1, @VolRecDesc AS Expr2
    FROM            gen_producto AS gp INNER JOIN
                             PrecioTopado ON gp.idproducto = PrecioTopado.idproducto
    WHERE        (NOT EXISTS
                                 (SELECT        1 AS Expr1
                                   FROM            Fac_PrecioEstProducto AS Fac_PrecioEstProducto_1
                                   WHERE        (gp.idproducto = idproducto) AND (PrecioTopado.idmonedacuc = idmoneda)))

    5-Consulta de Actualizar(Update):

    UPDATE       Fac_PrecioEstProducto
    SET                precio = PrecioTopado.precio
    FROM            Fac_PrecioEstProducto INNER JOIN
                             PrecioTopado ON Fac_PrecioEstProducto.idmoneda = PrecioTopado.idmonedacup AND Fac_PrecioEstProducto.idproducto = PrecioTopado.idproducto

    -asi no se demora ni 30 segundos y funciona a la perfeccion.Muchas gracias a los que me respondieron, doy por cerrado este post.Salu2s

    • Marcado como respuesta PedroJ2017 jueves, 27 de julio de 2017 15:23
    jueves, 27 de julio de 2017 15:19