Ver Mensaje Individual
  #1 (permalink)  
Antiguo 11/09/2012, 23:12
javahierro
 
Fecha de Ingreso: enero-2012
Mensajes: 23
Antigüedad: 12 años, 11 meses
Puntos: 0
Error de "duplicate key" en inserción cuando no existe tal violación sql

[CODE][HIGHLIGHT="MySQL"]HOla a todos tengo un sp en donde hago una serie de consultas, operaciones, update e insert a varias tablas a la vez, el asunto es el siguiente que en el siguiente sp que les mostraré tenía un problema incialmente de un error 1329 cuando le agregue la cláusula para corregirlo del "handler 1329" me dejo solucionó lo del fetch vacío pero ahora me salió el problema del error 1452 que dice que no puedo ni agregar ni actualizar una fila hija, cosa que no es cierta porque siempre lo termina haciendo en la tabla respectiva "control_situalab"
Lo que no comprendo porque me da ese error de violación de llave ya que el error literalmente que me tira es este:
------------------------------------------------------------------------------------------------------
Query: CALL aplicar_incapacidad_medica(@fec1,@fec2,2,31,@aplic a)

Error Code: 1452
Cannot add or update a child row: a foreign key constraint fails (`saerp`.`control_situalab`, CONSTRAINT `FK_controlSituaLab_empleados` FOREIGN KEY (`idempleado`) REFERENCES `empleados` (`idempleado`))
----------------------------------------------------------------------------------------------------
Me dice eso pero al revisar la tabla si hizo el insert que lleva el sp.

El codigo de mi sp es este:

Código MySQL:
Ver original
  1. DECLARE CONTINUE HANDLER FOR 1329 SET no_hay_accpers=1;
  2.    
  3.     #Obtenemos porcentaje de incapacidad y dias maximos de incapacidad con responsabilidad patronal
  4.     SELECT porc_pago_incap, dias_max_pago_incap, modalidad_planilla
  5.     INTO porc_tblconfig, dias_tblconfig, modpln_tblconfig
  6.     FROM empresas INNER JOIN configuraciones USING(codconfig) WHERE codempresa=1;      
  7.    
  8.     #Obtenemos planilla de sueldos activa
  9.     SET plnsuel = (SELECT plnsueldo);
  10.    
  11.     #Abrimos Result set
  12.     OPEN rg_accpers;
  13.    
  14.     #Leemos e iteramos la colección abierta
  15.     leer_bucle:LOOP
  16.         #Revisamos si hay filas que recorrer, sino lo hay salimos del bucle
  17.         IF no_hay_accpers = 1 THEN
  18.             #Da el pase para salir del flujo del Result Set una vez finalizada sus iteraciones o simplemente el cursor venia vacío
  19.             LEAVE leer_bucle;
  20.         END IF;
  21.         #Este IF funciona con LOOP ... END ó REPEAT ... END REPEAT
  22.        
  23.     #Controlamos el recorrido del flujo para ver si nos salimos
  24.     IF no_hay_accpers = 0 THEN
  25.  
  26.         #Extraemos valores del Result set
  27.         FETCH rg_accpers INTO idemp, porc, dura, pago_incap_maxdias, codsolic, rgcont, fecha_in, fecha_fn, dura_cub;       
  28.          
  29.         #Este módulo de cálculos solo aplica para planillas mensuales
  30.         IF (DAY((SELECT fecha2)) > 27) THEN
  31.        
  32.             #Modalidad de pago de la planilla
  33.             CASE modpln_tblconfig
  34.                 WHEN 'S' THEN #Modalidad semanal
  35.                     SET factor_sueldo = 4;             
  36.                 WHEN 'Q' THEN #Modalidad quincenal
  37.                     SET factor_sueldo = 2;
  38.                 ELSE #Modalidad mensual
  39.                     SET factor_sueldo = 1;
  40.             END CASE;
  41.             #Màximo de dias a pagar por incapacidad. Incapacidades solo se pagaran en el corte de planilla de fin de mes
  42.             SET vp_dias_maxpag = 30;
  43.             #Sueldo siempre se dividirá entre 30 días no importando la modalidad de la planilla    
  44.             IF (SELECT dias_laborables)<28 THEN
  45.                 SET dias_lab = 30;
  46.             ELSE
  47.                 SET dias_lab = 30;         
  48.             END IF;
  49.            
  50.             #Ningun dia de incapacidad pagado
  51.             SET dura_real = dura;
  52.             SET dura_cub_real = dura_cub;  
  53.             #Se decide si la empresa pagará la incapacidad
  54.             IF dura_cub_real = 0 AND !vp_calcIncap THEN        
  55.                 IF dura_real > dias_tblconfig THEN  #Incapacidad 25%
  56.                     IF porc > 0 THEN #La empresa le pagará la incapacidad
  57.                         IF dura_real > vp_dias_maxpag THEN
  58.                             SET vp_dias_res = dura - vp_dias_maxpag;
  59.                             SET vp_dias_pag = dura - vp_dias_res;
  60.                             SET dura = vp_dias_pag; #Dias a pagar en planilla
  61.                             SET dura_cub = vp_dias_pag; #Dias cubiertos del total de dias de incapacidad   
  62.                             SET vp_calcIncap = TRUE;
  63.                         ELSE                           
  64.                             SET dura = dura;
  65.                             SET dura_cub = dura;   
  66.                             SET vp_calcIncap = TRUE;
  67.                         END IF;
  68.                     ELSE #La empresa no le pagará la incapacidad
  69.                         SET vp_calcIncap = FALSE;              
  70.                     END IF;                
  71.                 ELSE #Incapacidad 3 dias max
  72.                     IF pago_incap_maxdias THEN #La empresa le pagara la incapacidad
  73.                         IF dura_real > vp_dias_maxpag THEN
  74.                             SET vp_dias_res = dura - vp_dias_maxpag;
  75.                             SET vp_dias_pag = dura - vp_dias_res;
  76.                             SET dura = vp_dias_pag; #Dias a pagar en planilla
  77.                             SET dura_cub = vp_dias_pag; #Dias cubiertos del total de dias de incapacidad   
  78.                             SET vp_calcIncap = TRUE;
  79.                         ELSE                           
  80.                             SET dura = dura;
  81.                             SET dura_cub = dura;   
  82.                             SET vp_calcIncap = TRUE;
  83.                         END IF;
  84.                     ELSE #La empresa no le pagara la incapacidad
  85.                         SET vp_calcIncap = FALSE;
  86.                     END IF;                    
  87.                 END IF;
  88.                 SET ctrl_situalab = TRUE;
  89.             END IF;
  90.        
  91.             #No se han pagado todos los dias de incapacidad, hay pendientes
  92.             IF dura_cub_real > 0 AND dura_real != dura_cub_real AND !vp_calcIncap THEN         
  93.                 SET vp_dias_res = dura - dura_cub;
  94.                 IF vp_dias_res > vp_dias_maxpag THEN
  95.                     SET vp_dias_res = dura - vp_dias_maxpag;
  96.                     SET vp_dias_pag = dura - vp_dias_res;
  97.                     SET dura = vp_dias_pag; #Dias a pagar en planilla
  98.                     SET dura_cub = vp_dias_pag; #Dias cubiertos del total de dias de incapacidad
  99.                     SET vp_calcIncap = TRUE;
  100.                 ELSE                   
  101.                     SET dura = vp_dias_res;
  102.                     SET dura_cub = vp_dias_res;
  103.                     SET vp_calcIncap = TRUE;
  104.                 END IF;
  105.                 SET ctrl_situalab = TRUE;
  106.             END IF;
  107.            
  108.             #Obtenemos cálculos respectivos a la incapacidad
  109.             IF vp_calcIncap THEN
  110.                 IF dura_real > dias_tblconfig THEN #Incapacidad de 25%
  111.                     IF porc > 0 THEN #Empresa decidió pagar el 25% correspondiente a los dias de incapacidad
  112.                         SET sueldo = (SELECT sueldo_base+sueldo_vari AS suel FROM empleados WHERE idempleado=idemp);
  113.                         SET monto_incap = dura * ( (sueldo * factor_sueldo) / dias_lab);
  114.                         SET pago_incap = monto_incap * (porc / 100);
  115.                     ELSE #Empresa decidió no pagarlos
  116.                         SET pago_incap = 0;            
  117.                     END IF;        
  118.                 ELSE #Incapacidad de 3 dias max        
  119.                     IF pago_incap_maxdias THEN #Pagará inncapacidad
  120.                         SET sueldo = (SELECT sueldo_base + sueldo_vari AS sue FROM empleados WHERE idempleado=idemp);
  121.                         SET monto_incap = dura * ( (sueldo * factor_sueldo) / dias_lab);
  122.                         SET pago_incap = monto_incap;
  123.                     ELSE #No pagará incapacidad
  124.                         SET pago_incap = 0;
  125.                     END IF;
  126.                 END IF;
  127.                
  128.                 #Actualizamos el detalle de la planilla en tabla deta_planilla_docus
  129.                 IF pago_incap > 0 THEN         
  130.                     INSERT INTO deta_planilla_docus (codplnsuel, codaccpers, idempleado, tipo_doc) VALUES (plnsuel, codsolic, idemp, 'PLNSUEL');
  131.                     SET id_deta_pln_docus = (SELECT numero FROM deta_planilla_docus ORDER BY numero DESC LIMIT 1);                         
  132.                     #Obtenemos algunos datos
  133.                     SET incmed_dias_detaplnsuel = (SELECT duracion FROM deta_planilla_docus WHERE numero = id_deta_pln_docus AND codplnsuel = plnsuel AND codaccpers = codsolic AND idempleado = idemp);
  134.                     SET incmed_monto_detaplnsuel = (SELECT monto FROM deta_planilla_docus WHERE numero = id_deta_pln_docus AND codplnsuel = plnsuel AND codaccpers = codsolic AND idempleado = idemp);
  135.                     #Actualizamos los dias incapacitados en tabla deta_plnsueldos. Si aplica       
  136.                     UPDATE deta_planilla_docus SET                 
  137.                         duracion = IF(dura > 0, incmed_dias_detaplnsuel + dura_cub, 0),
  138.                         monto = IF(pago_incap > 0, incmed_monto_detaplnsuel + pago_incap, 0)
  139.                         WHERE numero = id_deta_pln_docus AND codplnsuel = plnsuel AND codaccpers = codsolic AND idempleado = idemp;
  140.                 END IF;            
  141.    
  142.                 #Actualizamos los dias incapacitados cubiertos en tabla accpers_deta. Si aplica
  143.                 UPDATE accpers_deta SET
  144.                     duracion_cub = dura_cub_real + dura_cub
  145.                     WHERE idempleado = idemp AND codaccpers = codsolic;                        
  146.             END IF;
  147.            
  148.             #Hacemos bitácora de la situación laboral del empleado
  149.             IF ctrl_situalab THEN
  150.                 INSERT INTO control_situalab (idempleado, fecha1, fecha2, codsitualab, codplnsuel, tipodoc)
  151.                     VALUES (idemp, fecha_in, fecha_fn, 3, plnsuel, 'PLNSUEL');                 
  152.             END IF;
  153.                        
  154.             #Dias de incapacidad pagados en su totalidad o simplemente accpers aplicada porque empresa no quiso pagar incapacidad
  155.             IF (dura_real = (dura_cub_real + dura_cub) && pago_incap>0) THEN
  156.                 SET vp_okAccpers = TRUE;                 
  157.             ELSEIF (!pago_incap_maxdias && pago_incap=0) THEN
  158.                 SET vp_okAccpers = TRUE;
  159.             ELSEIF (porc > 0 && pago_incap=0) THEN
  160.                 SET vp_okAccpers = TRUE;
  161.             END IF;
  162.        
  163.             IF vp_okAccpers THEN
  164.                 UPDATE accpers SET aplicada = 1 WHERE codaccpers = codsolic;
  165.             END IF;            
  166.         END IF;
  167.                
  168.  
  169.        
  170.             #Contamos las iteraciones
  171.             SET contador = contador + 1;
  172.             #Tamaño del Result set coincide con las iteraciones hechas
  173.                
  174.             #Si el Result set filtrado es igual a la cantidad de UPDATE hechas
  175.             SET aplicada = contador; #1; #Indicar al usuario que se efectuo la operación correctamente
  176.             #SET @aplicada_INCMED = 1;
  177.     END IF;    
  178.        
  179.     END LOOP leer_bucle;
  180.    
  181.     #Cerramos la colección Result set
  182.     CLOSE rg_accpers;
  183.    
  184.     #Inicializamos el controlador utilizado
  185.     SET no_hay_accpers = 0;
  186.    
  187.     #No encontró registros
  188.     IF contador = 0 THEN
  189.         #Indicar al usuario que no se llevo a cabo la operacion porque no arrojo nada la consulta
  190.         SET aplicada = 0; #Parametro de salida para SP local       
  191.     END IF;