Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Tablas planas (https://www.clubdelphi.com/foros/forumdisplay.php?f=20)
-   -   Problema con Key violation (https://www.clubdelphi.com/foros/showthread.php?t=3418)

fortran 05-09-2003 18:40:23

Problema con Key violation
 
A ver si alguien me puede echar una mano con esto. Tengo el siguiente código:

Código:

Procedure ActualizarTablaVisitas;
var
  aux : integer;
  nueva : TDataSource;
Begin

// Ir al último Lugar de la tabla
  with modulodedatos do
  Begin
    nueva := tablavisitas.MasterSource;
    Tablavisitas.MasterSource := nil;
    Tablavisitas.last;
    aux := TablavisitasIndice_visitas.value;
    aux := aux+1;
    TablaVisitas.Append;
    TablaVisitasIndice_visitas.value := aux;
    TablaVisitasClave_Cliente.value := TablaClientesCodigo_Cliente.value;
    TablaVisitasfechavisita.value := date;
    Tablavisitas.edit;
    Tablavisitas.post;
    Tablavisitas.mastersource := nueva;
  End;
End;

Por algún motivo me rompe al intentar hacer el post. Me da un error de Key violation :confused: no se muy bien que hacer
Además me pasa algo raro, cuando lo uso por primera vez, todo parece funcionar perfectamente, la cosa falla cuando intento ejecutarlo después de haber añadido un registro con este procedimiento.

Gracias de antemano por vuestra atención

marcoszorrilla 05-09-2003 20:15:28

El error viene dado por que tienes la clave primaria repetida.

Conéctate a una rejilla mientras haces todo el proceso para así saber en cada momento cual es la última clave que le añades....

Una vez detectes el error, quizás el último registro no contiene el valor que esperas?

Una vez detectado el error tienes el evento Beforeinsert, para hacer las comprobaciones pertinentes.

Un Saludo.

fortran 06-09-2003 16:16:32

Hola Marcos:

He hecho lo que me has dicho y sigo teniendo problemas. Verás, lo que pasa es que al incluir el registro es como si no lo viera (aunque me aparece en el DBGrid).

Miré en el Database desktop y la última figura como metida, con su número de registro, código de cliente... todo correcto. Pero al ejecutar el procedimiento se queda justo en el registro anterior al que he creado con este procedimiento.

La verdad es que no se que hacerle, ¿no se porque no me va a la última posición a ver si me puedes echar un cable?.

Otro dato que acabo de observar es que aunque en el Database desktop el orden de los registros es el correcto, en el DBgrid me aparece registro1, registro5 (que es el último) y luego el resto ordenados. Sucede que el registro 1 y el 5 son los que eran detail antes de deshacer la relación Master-detail.

marcoszorrilla 06-09-2003 16:59:18

Tablavisitas.post;
...
Tablavisitas.FlushBuffers;

Esto debiera de ir en el evento AfterPost del ttable.

Ya me dirás si lo arreglas.

Un Saludo.

fortran 09-09-2003 10:02:27

Hola Marcos:

He dicho lo que me decías y sigue sin funcionar. Primero he puesto:

Código:

Procedure ActualizarTablaVisitas;
var
  aux : integer;
  nueva : TDataSource;
Begin

// Ir al último Lugar de la tabla
  with modulodedatos do
  Begin
    Tablavisitas.edit;
    nueva := tablavisitas.MasterSource;
    Tablavisitas.MasterSource := nil;
    Tablavisitas.last;
    aux := TablavisitasIndice_visitas.value;
    TablaVisitas.Append;
    aux := aux+1;
    TablaVisitasIndice_visitas.value := aux;
    TablaVisitasClave_Cliente.value := TablaClientesCodigo_Cliente.value;
    TablaVisitasfechavisita.value := date;
    Tablavisitasempleado.value := Tablaempleadosclaveempleado.value;
    Tablavisitas.post;
    Tablavisitas.FlushBuffers;
    Tablavisitas.mastersource := nueva;

  End;
End;

Y nada, me seguía dando el mismo problema

Luego puse Tablavisitas.Flushbuffers en el evento afterpost y me sigue dando lo mismo.

Considera que el último registro es el anterior al insertado y entonces me repite el TablavisitasIndicevisitas.value y me da Key violation. :confused:

En el dbgrid me sigue saliendo

Registro 1
Registro 5
Registro 2
Registro 3
Registro 4

E intenta meter un registro con el índice = 5

andres1569 09-09-2003 10:22:28

Hola:

Por lo que veo, esa tabla de visitas está ligada a otro Dataset en Master-Detail, de ahí que lo primero que haces es romper ese vínculo (el Edit que pones al principio es innecesario, para eso ya está el Append posterior).

Si está en Master-Detail, lo normal es que se utilice un índice para acelerar ese vínculo, y en ese caso me parece que el campo que tú tienes como Clave primaria de Visitas no es el que se emplea para ligar ambas tablas. Quizás me equivoque pero parece ser que ligas por otro campo, con lo cual la tabla Visitas está indexada por dicho campo y no por Indice_visitas, de ahí que al romper el Master-Detail, los registros no te aparezcan en el orden que tu esperas. Para lograrlo deberías, después de romper el vínculo, asignarle el índice primario, así te aparecerían los registros ordenados por Indice_visitas.

De todas formas, todo esto no me parece muy aconsejable, yo al menos prefiero lanzar un Query "SELECT MAX(Indice_visitas) FROM VISITAS" y le incremento en 1, pero para que esto funcione debes asgurarte de que tras cada inserción llamas a FlushBuffers, como dice Marcos, para que el valor devuelto por la BD esté actualizado. O si estás realizando muchas altas de golpe y quieres ahorrarte ese trabajo extra, lanzar la consulta al principio, guardarla en una variable e irla manteniendo a lo largo de la vida del Form donde realizas esta operación.

Espero te sirva,

Saludos

fortran 29-09-2003 18:16:38

Hola Andrés:

Perdona que mi respuesta se demorara tanto pero he estado de Vacaciones :) , lástima que ya se terminaran :( .

Te cuento, entiendo lo que me cuentas, lo de la Query me parece bien, el problema es que no domino las querys. Intenté hacer algo así, pero no he sido capaz de llevarlo a "buen puerto".

Código:

Procedure ActualizarTablaVisitas;
var
  aux : integer;
  nueva : TDataSource;
  Pregunta : TQuery;
Begin

  with modulodedatos do
  Begin
    Pregunta:= TQuery.create(Application);
    Pregunta.DatabaseName := Modulodedatos.Tablavisitas.DatabaseName;
    Pregunta.SQL.Text := 'select max (indice_visitas) from Tablavisitas';
    Pregunta.open;
    aux := pregunta.fieldbyname(tablavisitasindice_visitas.value).asinteger;
    TablaVisitas.Append;
    aux := aux+1;
    TablaVisitasIndice_visitas.value := aux;
    TablaVisitasClave_Cliente.value := TablaClientesCodigo_Cliente.value;
    TablaVisitasfechavisita.value := date;
    Tablavisitasempleado.value := Tablaempleadosclaveempleado.value;
    Tablavisitas.post;
    Tablavisitas.FlushBuffers;
 
  End;
End;

Pero (además de no saber si el procedimiento utilizado es correcto o no) no puedo compilar porque me dice que los tipos integer y string son incompatibles en la línea

aux := pregunta.fieldbyname(tablavisitasindice_visitas.value).asinteger;

Para la primera solución que propones tengo el problema de que no se como asignarle el índice primario.

Mira a ver si me puedes echar un cable y si de paso me recomiendas algún sitio donde leer algo sencillo para comenzar a manejarme con las Querys.

Gracias por tu atención.

marcoszorrilla 29-09-2003 18:32:51

Creo que si nos expusieras la situación de la siguiente manera te podríamos ayudar mucho mejor.

1º.-Tabla 1 contiene xxx
2º.- Tabla2 contiene yyyy
Esta relacionada con la primera a través del campo JJJJJJ

Quiero hacer esto: Lo que sea pero sin código, nada más lo que pretendes hacer.

Un Saludo.

fortran 30-09-2003 16:27:13

Creo que tienes razón Marcos:

Allá va la información.

Tabla 1: TablaClientes

Campos... Codigo_cliente, Nombre_Cliente, Numero_visitas, ultima_visita...

Tabla 2: TablaVisitas

Campos... Indice_Visitas, Clave_cliente, Productos_visita, descuento_realizado, Precio...

Hay una relación master-Detail entre las dos tablas y por los campos codigo_cliente y clave_cliente.

Lo que quiero hacer añadir un registro con el campo Indice_visitas incrementado en una unidad cada vez que se produzca una visita y eliminarle el registro si borro una visita. El campo indice_visitas es de tipo integer.

Gracias por la atención que me estais prestando.

marcoszorrilla 01-10-2003 08:29:26

La solución, es mucho más fácil, en una tabla auxiliar, guardas el último registro, (el número del índice) y cada vez que des un alta incrementas en uno dicho número, si el alta se consolida incrementas el contador en la tabla auxiliar, sino lo dejas como estaba para la próxima, de esta manera te ahorras el trabajo de soltar la relación maestro detalle y el resto de complicaciones.

Un Saludo.

fortran 01-10-2003 12:03:40

Gracias Marcos:

Funciona a la perfección. De todos modos me interesaría algún libro, apuntes, página web... en las que se explicara desde el principio y sencillito las cuestiones de acceso a bases de datos, alias, querys... ¿sabes de algo de esto?

Gracias por todo.

marcoszorrilla 01-10-2003 15:31:22

Está muy bien "la cara oculta de Delphi", creo recordar que la versión 4, se podía bajar gratis de la página del autor Ian Marteens.

También es excelente cualquier libro al respecto del Marco Cantù.

Un Saludo.

fortran 02-10-2003 09:27:43

Gracias Marcos:

Ya he conseguido "La Cara Oculta de Delphi 4" que creo que fue la última "Cara Oculta". A ver si lo leo y me pongo un poco al día de algo.

andres1569 02-10-2003 13:17:18

Hola, si vas a trabajas con Delphi 6.0, el último libro de Caras Ocultas es el referente a esa versión, la 6. Según leo en la web del autor, hay una promoción por liquidación de existencias.

Eso si te interesa el libro impreso, no sé si el que has obtenido es la versión electrónica gratuita.

fortran 03-10-2003 09:27:01

Hola Andrés:

Gracias por la información. Por el momento estoy trabajando con D5 y la versión que tenía de "La Cara Oculta de Delphi 4" era la versión electrónica. Supongo que me acabaré comprando "La Cara Oculta de Delphi 6", parece bastante buena oferta.

andres1569 03-10-2003 09:42:40

Ja, ja, ja, no quiero que parezca que soy un comercial de Ian Marteens, te puse esa aclaración porque decías que creías que "La Cara Oculta de Delphi 4" era la última de la saga, sólo para aclarar que existe para la versión 6 también, y según leo piensa escribir otra para la 8.

Saludos

fortran 03-10-2003 10:04:18

Ja,ja,ja, muy bueno Andrés.
No, no pienso que seas comercial de Ian Marteens, si me lo pienso comprar es porque me gusta tener algún que otro libro impreso (sobre todo si lo recomiendan tanto como este) y no todos en formato eléctrónico.


La franja horaria es GMT +2. Ahora son las 10:31:42.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi