none
Conflicto de llave duplicada RRS feed

  • Pregunta

  • Estimados, el día de hoy me ha pasado algo sumamente interesante y extraño verán, desde hace 6 meses vengo trabajando un sistema que lo tuve que ir investigando de a pocos, ya que nadie me capacito ni me enseño como estaba estructurado todo, pero ese no es el caso. En este sistema encontré cosas interesantes, una de ellas es que hay una tabla general que tiene todos los consecutivos de las otras tablas. En todos los procedimientos se consulta esta tabla general, se extrae el último consecutivo y se le suma 1. No lo había visto antes y pues me pareció interesante. Todo marchaba bien, pero el día de hoy por algún motivo al llegar a determinado número me aparece un error en la base de datos que dice que hay un conflicto de llave duplicada, pero al momento de revisar no hay dicho conflicto. Estuve dándole vueltas por mucho rato hasta que decidí saltarme los consecutivos, es decir me salte por ejemplo del consecutivo 24500 al 25000 y grande fue mi sorpresa al notar que funcionaba todo, pero al intentar insertar con el consecutivo 24501 me daba error de llave. Esto sin duda me dejó perplejo y no lo sé explicar de ninguna forma. Quisiera que por favor alguien me pudiera dar detalle de que es lo que sucedió aquí y si se puede corregir de alguna manera para no saltarme los consecutivos. Gracias
    viernes, 20 de noviembre de 2015 14:00

Respuestas

  • Carlos Sk

    Bueno en ese caso entonces, primero probaría volviendo a generar el indice de la clave primaria (ALTER INDEX ........... REBUILD).

    Y eso no funca!!! Renombraria la tabla (Backup) y creo nuevamente la tabla con su correspondiente Primary Key, he importaría nuevamente todos los registros para no perder nada. 

    Saludos 

    • Marcado como respuesta Carlos Sk viernes, 20 de noviembre de 2015 19:47
    viernes, 20 de noviembre de 2015 14:58

Todas las respuestas

  • Hola Carlos Sk,

    Yo en tu lugar, habilitaría una Auditoria sobre esa tabla o ejecutaría un SQL Profiler. Para ver que esta haciendo internamente sobre esa tabla.

    viernes, 20 de noviembre de 2015 14:11
  • Hola,

    Hice uso del SQL Profiler y pude notar allí que había este problema de llaves. Hice el respectivo debug haciendo seguimiento de los parámetros que asignar las llaves y los insert. Ya en desesperación hice los insert de manera manual, pero me seguía apareciendo el mensaje de duplicidad de llaves, pero no era así. Sin duda hay algo más a fondo, pero no soy un gran conocedor de base de datos. Por mi bastaría con saltarme los consecutivos y decir listo, pero todo tiene un porque y quiero saberlo, es por eso que acudo a ustedes.

    viernes, 20 de noviembre de 2015 14:17
  • Es posible que esa tabla tenga triggers? Puedes comprobarlo?

    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA

    viernes, 20 de noviembre de 2015 14:51
    Moderador
  • Carlos Sk

    Bueno en ese caso entonces, primero probaría volviendo a generar el indice de la clave primaria (ALTER INDEX ........... REBUILD).

    Y eso no funca!!! Renombraria la tabla (Backup) y creo nuevamente la tabla con su correspondiente Primary Key, he importaría nuevamente todos los registros para no perder nada. 

    Saludos 

    • Marcado como respuesta Carlos Sk viernes, 20 de noviembre de 2015 19:47
    viernes, 20 de noviembre de 2015 14:58
  • Saludos,

    Suena como codigo de la aplicación la que controla el consecutivo, es correcto lo que pienso o es un trigger o sp lo que hace esta función?.

    viernes, 20 de noviembre de 2015 15:35
  • Hola,

    Lo que controla el consecutivo es un sp en la base de datos

    viernes, 20 de noviembre de 2015 16:40
  • Hola Carlos Sk,

    A ver, vamos con calma para encontrar el origen del problema que mencionas, no sin antes hacerte llegar mis puntos de vista respecto al caso en mención.

    A lo que tu llamas interesante yo le llamo innecesario y de seguro podríamos encontrar mas puntos en contra que a favor, de hecho, lo más simple es definir la columna como identidad (propiedad IDENTITY) que hará el trabajo tedioso por nosotros, también puedes lograr lo mismo creando un objeto de base de datos SEQUENCE.

    Por otro lado, mencionas que obtienes un error de clave duplicada a razón de un valor que aparentemente existe y que la base de datos - en aras de salvaguardar la integridad de los datos - rechaza la operación. Lo que quiero que tengas claro en este punto es que no necesariamente el error se desencadena en la tabla en la que haces la inserción, el error podría estar produciéndose en cualquier otra tabla que realice una operación a razón de la inserción, ya te habían comentado que revises algún trigger que esté haciendo algo "tras telones" o podría tratarse de la tabla donde se encuentran los correlativos, ya que mencionas que esa tabla se actualiza luego de cada operación.

    En cualquier caso, si obtienes un error de duplicidad es que se está intentando atentar contra un índice único o alguna restricción (UNIQUE) que para el caso las diferencias no viene al caso, lo importante es conocer cual es el objeto (índice) que reclama el atentado. Intenta ejecutar una instrucción INSERT desde Managment Studio, verás que en la descripción del error se menciona el nombre de la restricción que intentas infringir, que como te mencione podría ser un índice único o una restricción UNIQUE, recuerda también que el error no necesariamente tiene como origen la tabla donde se efectúa la inserción. Pues bien, teniendo el nombre a mano lo que queda es averiguar que tabla la contiene, y que columnas son las afectas (un índice o restricción podría ser compuesto si intervienen varias columnas) entre algo más de información de importancia. Te dejo una consulta que retorna la tabla origen y las columnas afectas, en la clausula WHERE coloca el nombre del objeto que reclama la infracción:

    SELECT 
    	ind.name [INDICE],
    	tab.name [TABLA],
    	cols.name [COLUMNAS],	
    	ind.is_primary_key [IS PRIMARY KEY],
    	ind.is_unique [IS UNIQUE],
    	ind.type_desc [TIPO]	
    FROM 
    	sys.indexes ind
    	INNER JOIN sys.index_columns ind_cols ON (ind_cols.index_id = ind.index_id)
    	INNER JOIN sys.columns cols ON (cols.object_id = ind_cols.object_id)
    		AND (cols.object_id = ind.object_id)
    		AND (cols.column_id = ind_cols.column_id)
    	INNER JOIN sys.tables tab ON (tab.object_id = cols.object_id)
    WHERE 
    	ind.name = 'NOMBRE_DEL_OBJETO';

    Intentaré dar seguimiento a tus respuestas pero ante cualquier duda estoy seguro que los colegas podrás apoyarte, ando últimamente muy copado por ser fin de año, suerte y coméntanos como te fue.

    viernes, 20 de noviembre de 2015 17:38
  • Hola, gracias por sus respuestas. Hice muchas verificaciones, pero lo que al final resolvió el problema fue lo propuesto por Angel Luis Eduardo Gomez sobre volver a generar el índice. 
    viernes, 20 de noviembre de 2015 19:50