PDA

Ver la Versión Completa : Problema con Key violation


fortran
05-09-2003, 19:40:23
A ver si alguien me puede echar una mano con esto. Tengo el siguiente 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, 21: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, 17: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, 17: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, 11:02:27
Hola Marcos:

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


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, 11: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, 19: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".


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, 19: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, 17: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, 09: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, 13: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, 16: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, 10: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, 14: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 (http://www.marteens.com/), 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, 10: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, 10: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, 11: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.