none
Eliminar un registro pero que no se elimine el código. RRS feed

  • Pregunta

  • Un saludo a todos:

    En una tabla tengo 3 columnas: "Código, área, descripción". El primary key lo tengo en el código, y necesito que sea un código consecutivo, entonces cuando ejecuto la instrucción de "eliminar" me elimina todo incluyendo el código y se pierde la codificación consecutiva, la pregunta es ¿Qué puedo hacer para que cuando ejecute la instrucción de "eliminar" no se pierda la consecutivo de las códigos?

    Ejemplo:

    Código             área        Descripción

    TR-101-00     XXXX       YYYYYYYYYY

    TR-102-00     XXXX       YYYYYYYYYY

    TR-103-00     XXXX       YYYYYYYYY

    En el ejemplo anterior si elimino el TR-102-00, en la tabla vería los códigos TR-101-00 y TR-103-00, y lo que necesito es que cuando ejecute la instrucción "eliminar", y borro el TR-102-00, entonces en la tabla necesito ver TR-101-00 y TR-102-00.

    Gracias de antemano.

    Saludos

    domingo, 2 de septiembre de 2018 4:13

Respuestas

  • Que tal Alberto:

    Gracias por tus comentarios, voy a trabajar en tus consejos y afortunadamente no voy a crear tablas muy grandes, de hecho van a ser muy pequeñas, entonces creo que el desempeño no se vería muy afectado, pero ya te platicaré cual fue el resultado.

    Saludos!!

    domingo, 2 de septiembre de 2018 15:36
  • De nada. Ademas que no te lo puse, dentro del procedure puedes utilizar un bloque try catch y si ocurre algo que no has controlado acometer en el mismo la excepcion bien sea lanzandola o realizando cualquier log...

    Ya comentas como te fue.

    Un saludo

    domingo, 2 de septiembre de 2018 17:57

Todas las respuestas

  • Es decir, en resumidas cuentas quieres que cuando se elimina un registro entonces todos los registros cuyo código sea posterior al eliminado se actualicen para disminuir en una unidad su código. Esto va a ser costosísimo si la tabla es grande y eliminas uno de los códigos del principio.

    Pero si a pesar de todo quieres hacerlo, se podría conseguir añadiendo un trigger sobre el DELETE y que dentro del trigger se haga algo parecido a esto: update laTabla set codigo = codigo-1 where codigo>codigoBorrado. Pero digo "parecido" porque en realidad tus códigos no son numéricos así que no basta con poner "codigo-1", tendrás que usar Substring, Left, Right y Len para trocear la parte numérica, decrementarla, y volver a combinar las partes. Y para hacer el trigger bien hecho tienes que prever el caso de que se borren varios registros de golpe, lo cual complica las cosas más.

    Otra opción sería hacer lo mismo desde el código cliente, suponiendo que tengas un único programa cliente capaz de borrar esos registros. En ese caso, tienes la ventaja de que puedes forzar los borrados a que ocurran de uno en uno, con lo que se simplifica la condición del Update.

    Pero si la tabla puede ser grande, y dado el coste de renumerar todos los registros cuando borras uno, se puede recurrir a otra opción, que es la de simplemente marcar el registro con algún código especial que signifique "borrado", y luego tener un proceso de renumeración que se ejecute cuando las reglase de negocio lo requieran y que recorra de una vez toda la tabla reajustando todos los códigos de una sola vez.

    domingo, 2 de septiembre de 2018 6:49
  • Igualmente a lo que te dijo Alberto, te aconsejo un trigger, e igualmente te digo que si la tabla está muy poblada, va a ser costoso en ir enumerando registro por registro 

    domingo, 2 de septiembre de 2018 6:55
  • Hola Gabriel632:

    Si bien los borrados son siempre conflictivos y más aun cuando hacen lo que tu pides, esta sería una posible solución, donde se intenta mantener lo que indicas, y además en un escenario de alta concurrencia.

    Pero para poder aplicarla, te recomiendo que lo utilices dentro de un procedimiento almacenado, que no utilices nunca, directamente un borrado. Desde mi opinión cualquier otro escenario te sería imposible, de controlar, porque si ocurre un error de borrado. No tienes manera posible de controlarlo, y se produce un desbarajuste.....

    CREATE TABLE codigos
    (Codigo      VARCHAR(100)
     PRIMARY KEY,
     area        VARCHAR(100),
     descripcion VARCHAR(100)
    );
    GO
    INSERT INTO codigos
    (codigo,
     area,
     descripcion
    )
    VALUES
    ('TR-101-00',
     'XX',
     'YY'
    ),
    ('TR-102-00',
     'XX',
     'YY'
    ),
    ('TR-103-00',
     'XX',
     'YY'
    ),
    ('TR-104-00',
     'XX',
     'YY'
    ),
    ('TR-105-00',
     'XX',
     'YY'
    ),
    ('TR-106-00',
     'XX',
     'YY'
    );
    GO
    DELETE FROM CODIGOS
    WHERE CODIGO LIKE 'TR-103-00';
    INSERT INTO codigos
    (codigo,
     area,
     descripcion
    )
    VALUES
    ('TR-1010-00',
     'XX',
     'YY'
    );
    GO
    CREATE PROCEDURE SP_BORRADOS(@CODIGO VARCHAR(100))
    AS
    
    /*PUEDES CHEQUERAR SI EL CODIGO DE BORRADO NO ES EL ÚLTIMO */
    
         BEGIN
             SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    		 
    		 declare @miCodigo int = (SELECT max(CAST(SUBSTRING(CODIGO, 4, CHARINDEX('-', CODIGO, 4)-4) AS INT) )
    FROM codigos
    ) /* obtengo en maximo valor entero de la tabla */
    		declare @elEntrante int = (CAST(SUBSTRING(@codigo, 4, CHARINDEX('-', @codigo, 4)-4) AS INT))
    		IF (@miCodigo<>@elEntrante)
    		BEGIN
    
    /*BLOQUEO DE TABLA PARA QUE NADIE INSERTE MIENTRAS TU BORRAS, AL FINALIZAR LA TRANSACCION SE DESBLOQUEA SOLA. */
    
             ;WITH CTE
                  AS (
                  SELECT ROW_NUMBER() OVER(ORDER BY CAST(SUBSTRING(CODIGO, 4, CHARINDEX('-', CODIGO, 4)-4) AS INT))+100 AS FILA,
                         CAST(SUBSTRING(CODIGO, 4, CHARINDEX('-', CODIGO, 4)-4) AS INT) AS CADENA,
                         CODIGO AS COD
                  FROM CODIGOS)
                  UPDATE A
                    SET
                        CODIGO = 'TR-'+CAST(C.FILA AS VARCHAR)+'-00'
                  FROM CODIGOS A
                       INNER JOIN CTE C ON C.COD = A.CODIGO
                  WHERE FILA < CADENA;
    			END
    			ELSE
    				DELETE FROM CODIGOS WHERE CODIGO =@CODIGO
             
    		 END;
    RETURN
    EXEC SP_BORRADOS
         'TR-103-XX';
    GO
    SELECT * FROM codigos
    
    
    
    
    

    Espero te ayude.

    Un saludo

    domingo, 2 de septiembre de 2018 7:40
  • Que tal Alberto:

    Gracias por tus comentarios, voy a trabajar en tus consejos y afortunadamente no voy a crear tablas muy grandes, de hecho van a ser muy pequeñas, entonces creo que el desempeño no se vería muy afectado, pero ya te platicaré cual fue el resultado.

    Saludos!!

    domingo, 2 de septiembre de 2018 15:36
  • Si, como le comento a Alberto no van a ser tablas grandes, ya les platicaré el resultado.

    Gracias y saludos!!

    domingo, 2 de septiembre de 2018 15:38
  • Javi gracias por el aporte, voy a considerar el script para solucionar el problema, ya te platicaré el resultado. 

    Saludos!!

    domingo, 2 de septiembre de 2018 15:40
  • De nada. Ademas que no te lo puse, dentro del procedure puedes utilizar un bloque try catch y si ocurre algo que no has controlado acometer en el mismo la excepcion bien sea lanzandola o realizando cualquier log...

    Ya comentas como te fue.

    Un saludo

    domingo, 2 de septiembre de 2018 17:57