none
EJECUTAR TRUNCATE CON RESTRICCIONES RRS feed

  • Pregunta

  • Buenas a todos/as

    Programo en vb.net y uso SQL SERVER

    al intentar vaciar las tablas Factura y Destalle factura me sale este error. (USANDO TRUNCATE).

    no se puede truncar la tabla una restricción foreign key hace referencia a ella. 
    

    este es mi código fuente: 

     Using cnx As New SqlConnection(cadenaConexion)
    
                    cnx.Open()
    
                    Dim actualizar As String = "truncate table dbo.Tbla_Factura"
    
                    Using cmd As New SqlCommand(actualizar, cnx)
    
                        cmd.ExecuteNonQuery()
                        MsgBox("Tabla Vaciada con Éxito ")
    
                    End Using
                End Using
    
                Using cnx As New SqlConnection(cadenaConexion)
    
                    cnx.Open()
    
                    Dim actualizar As String = "truncate table dbo.Tbla_DetalleFactura"
    
                    Using cmd As New SqlCommand(actualizar, cnx)
    
                        cmd.ExecuteNonQuery()
                        MsgBox("Tabla Vaciada con Éxito ")
    
    
                    End Using
                End Using
    

    Existe la posibilidad de antes de ejecutar el código anterior, de PRIMERO, eliminar las registraciones, luego ejecutar el TRUNCATE, y por ultimo otro código que vuelva a poner las restricciones como estaban.

    Espero su ayuda, por favor de responder. 


    • Cambiado Enrique M. Montejo martes, 2 de enero de 2018 15:48 Pregunta relacionada con SQL Server.
    viernes, 29 de diciembre de 2017 15:21

Respuestas

  • Existe la posibilidad de [...] PRIMERO, eliminar las registraciones, luego ejecutar el TRUNCATE, y por ultimo [...] vuelva a poner las restricciones como estaban.

    Como poder, podrías. Pero tiene un problema grave: las restricciones existen por una buena razón, que es la de garantizar la integridad referencial de las tablas. Es decir, se trata de que en una tabla hija, el valor siempre tenga que existir en la tabla madre. Por ejemplo, que nunca exista un detalle de factura cuya factura no exista. Si quitases la restricción y vaciases la tabla madre, se quedarían registros en la tabla hija no concordantes con la tabla madre, por lo que luego no podrías volver a añadir la restricción. El único caso en que no habría problema sería el de que la tabla hija estuviese ya vacía de antemano. Pero si está ya vacía, no vale la pena que hagas un truncate, que tiene ventajas de velocidad si la tabla tiene muchos registros, pero no ganas nada si la tabla está vacía. Para eso es mejor que hagas un DELETE (que con la tabla vacía será instantáneo) en lugar del truncate. El Delete no tiene problemas con las restricciones, salvo en el caso de que realmente existan valores que rompan la integridad referencial, en cuyo caso el Delete dará el oportuno error (a no ser que exista un "on delete cascade").
    • Propuesto como respuesta Pablo RubioModerator viernes, 29 de diciembre de 2017 16:41
    • Marcado como respuesta EliannyRD viernes, 29 de diciembre de 2017 23:19
    viernes, 29 de diciembre de 2017 16:32
  •  yo pensaba que después de vaciar las tablas CON DELETE, el peso de los ficheros de la base de datos iba a disminuir considerablemente,

    No. Tanto con delete como con truncate el tamaño del fichero no disminuye. Lo que ocurre es que el espacio que ocupaban los registros borrados se marca internamente como "disponible" y la próxima vez que insertas registros en la base de datos se aprovecha ese espacio. Esto se hace por razones de rendimiento, para evitar que el archivo se fragmente por el disco al decrecer y luego volver a crecer. También aumenta la velocidad al disminuir el número de crecimientos, que es una operación lenta.
    • Marcado como respuesta EliannyRD sábado, 30 de diciembre de 2017 14:50
    sábado, 30 de diciembre de 2017 10:01
  • quiero por favor que me digan si este es el código correcto

    En principio parece correcto, y debería reducirte el tamaño de los archivos. Sin embargo, es una mala práctica hacer esto sobre una base de datos que se encuentre en producción. Da lugar a una fragmentación interna de la base de datos y el rendimiento disminuye. Solo se recomienda hacer el "shrink" si es una base de datos de pruebas con la que estás experimentando y durante los experimentos generaste una gran cantidad de registros inútiles cuyo espacio ahora quieres recuperar.

    Pero si es para ponerla en producción, se recomienda evitar el Shrink. Créala con el tamaño máximo que sea previsible alcanzar, y mantenla permanentemente con ese tamaño.

    sábado, 30 de diciembre de 2017 10:04

Todas las respuestas

  • Existe la posibilidad de [...] PRIMERO, eliminar las registraciones, luego ejecutar el TRUNCATE, y por ultimo [...] vuelva a poner las restricciones como estaban.

    Como poder, podrías. Pero tiene un problema grave: las restricciones existen por una buena razón, que es la de garantizar la integridad referencial de las tablas. Es decir, se trata de que en una tabla hija, el valor siempre tenga que existir en la tabla madre. Por ejemplo, que nunca exista un detalle de factura cuya factura no exista. Si quitases la restricción y vaciases la tabla madre, se quedarían registros en la tabla hija no concordantes con la tabla madre, por lo que luego no podrías volver a añadir la restricción. El único caso en que no habría problema sería el de que la tabla hija estuviese ya vacía de antemano. Pero si está ya vacía, no vale la pena que hagas un truncate, que tiene ventajas de velocidad si la tabla tiene muchos registros, pero no ganas nada si la tabla está vacía. Para eso es mejor que hagas un DELETE (que con la tabla vacía será instantáneo) en lugar del truncate. El Delete no tiene problemas con las restricciones, salvo en el caso de que realmente existan valores que rompan la integridad referencial, en cuyo caso el Delete dará el oportuno error (a no ser que exista un "on delete cascade").
    • Propuesto como respuesta Pablo RubioModerator viernes, 29 de diciembre de 2017 16:41
    • Marcado como respuesta EliannyRD viernes, 29 de diciembre de 2017 23:19
    viernes, 29 de diciembre de 2017 16:32
  • No, eso no funcionará. El Truncate da un error por el mero hecho de existir la Foreign Key, incluso aunque no exista ninguna fila que la infrinja. En cambio el Delete no tiene ese problema.
    viernes, 29 de diciembre de 2017 17:13
  • Gracias a todas por sus recomendaciones

    Como no puedo usar TRUNCATE, Por tal razón estoy usando DELETE. con este codigo: 

    Using cnx As New SqlConnection(cadenaConexion)
     
                    cnx.Open()
     
                    Dim actualizar As String = "delete  from Tbla_Factura"
     
     
                    Using cmd As New SqlCommand(actualizar, cnx)
     
                        cmd.ExecuteNonQuery()
                        MsgBox("Tabla Vaciada con Éxito ")
     
                    End Using
                End Using
     
                Using cnx As New SqlConnection(cadenaConexion)
     
                    cnx.Open()
     
                    Dim actualizar As String = "delete from Tbla_DetalleFactura"
     
     
                    Using cmd As New SqlCommand(actualizar, cnx)
     
                        cmd.ExecuteNonQuery()
                        MsgBox("Tabla Vaciada con Éxito ")
     
     
                    End Using
                End Using

    Las tablas están vaciadas, pero los ficheros de base datos (DbSistemaFactura, DbSistemaFactura_log) pesan lo mismo (1 GB). 

    Es decir, que yo pensaba que después de vaciar las tablas CON DELETE, el peso de los ficheros de la base de datos iba a disminuir considerablemente, sin embargo, pesa casi igual que antes. 

    Es como si borra la información, pero sigue oculto en la base de datos.

    Espero su ayuda, por favor. 


     

    • Editado EliannyRD viernes, 29 de diciembre de 2017 18:05
    viernes, 29 de diciembre de 2017 17:59
  • Reducí el tamaño de los ficheros así: 

    Using cnx As New SqlConnection(cadenaConexion)
                    cnx.Open()
                    Dim actualizar As String = "DBCC SHRINKDATABASE(DbSistemaFactura, 10)"
    
                    Using cmd As New SqlCommand(actualizar, cnx)
                        cmd.ExecuteNonQuery()
                        MsgBox("Reducción base de datos con éxito")
                        BtnReducirBaseDeDatos.Enabled = False
    
                    End Using
                End Using
    
    Using cnx As New SqlConnection(cadenaConexion)
                    cnx.Open()
    
                    Dim actualizar As String = "DBCC SHRINKFILE (DbSistemaFactura_Log, 1)"
    
                    Using cmd As New SqlCommand(actualizar, cnx)
    
                        cmd.ExecuteNonQuery()
                        MsgBox("Reducción el archivo log a 1 MB con éxito")
                        BtnReducirLog.Enabled = False
    
                    End Using
                End Using
    
    
    quiero por favor que me digan si este es el código correcto, o si le falta algo, por favor. 

    viernes, 29 de diciembre de 2017 19:10
  •  yo pensaba que después de vaciar las tablas CON DELETE, el peso de los ficheros de la base de datos iba a disminuir considerablemente,

    No. Tanto con delete como con truncate el tamaño del fichero no disminuye. Lo que ocurre es que el espacio que ocupaban los registros borrados se marca internamente como "disponible" y la próxima vez que insertas registros en la base de datos se aprovecha ese espacio. Esto se hace por razones de rendimiento, para evitar que el archivo se fragmente por el disco al decrecer y luego volver a crecer. También aumenta la velocidad al disminuir el número de crecimientos, que es una operación lenta.
    • Marcado como respuesta EliannyRD sábado, 30 de diciembre de 2017 14:50
    sábado, 30 de diciembre de 2017 10:01
  • quiero por favor que me digan si este es el código correcto

    En principio parece correcto, y debería reducirte el tamaño de los archivos. Sin embargo, es una mala práctica hacer esto sobre una base de datos que se encuentre en producción. Da lugar a una fragmentación interna de la base de datos y el rendimiento disminuye. Solo se recomienda hacer el "shrink" si es una base de datos de pruebas con la que estás experimentando y durante los experimentos generaste una gran cantidad de registros inútiles cuyo espacio ahora quieres recuperar.

    Pero si es para ponerla en producción, se recomienda evitar el Shrink. Créala con el tamaño máximo que sea previsible alcanzar, y mantenla permanentemente con ese tamaño.

    sábado, 30 de diciembre de 2017 10:04