Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Error Key Violation al copiar tablas (https://www.clubdelphi.com/foros/showthread.php?t=29013)

Mathom 10-01-2006 14:09:53

Error Key Violation al copiar tablas
 
Hola a todos, os comento a ver si me podéis indicar a que es debido un error. Os explico. Tengo una tabla en una dirección con alias (AAA) y al pulsar un botón quiero que dicha tabla se me copie en otra dir. con alias (BBB). Bien, el dódigo que utilizo es el siguiente:

Código:

procedure TFormPrincipal.Realizarcopia1Click(Sender: TObject);
begin
DM.TblDep_seg.Insert;
DM.TblDep_seg.FieldByName('Nombre').AsString := DM.TblDep.fieldbyname('Nombre').AsString;
DM.TblDep_seg.FieldByName('Cod_dep').AsString := DM.TblDep.fieldbyname('Cod_dep').AsString;
DM.TTblDep_seg.Post;
DM.TblDep_seg.Refresh;
end;

El campo "Cod_dep" es clave primaria. Tanto Cod_dep como Nombre son String´s y la tablas son Paradox.

Bien, pues cuando pulso dicho botón me aparece el mensaje de error "Key Violation". Tiene que ver con la clave primaria?? que estoy haciendo mal??

Gracias de antemano y un saludo.

Neftali [Germán.Estévez] 10-01-2006 14:15:47

Seguramente en la tabla destino ya existe un valor igual al que estás intentando copiar.

Mathom 10-01-2006 14:33:46

Antes que nada y como siempre gracias Neftali:). Efectivamente, lo que quiero hacer es una especie de copia de seguridad muy simple por lo que habrá datos que estarán en las dos tablas. Como puedo hacer para poder copiar datos repetidos??

lucasarts_18 10-01-2006 14:52:53

Hola:

Si están definido en la otra tabla como llave primaria no podrás copiar esos datos repetidos porque el motor se encargará de mantener dicha consistencia.

Hasta Luego -

Mathom 10-01-2006 18:50:47

Entonces cómo podría hacer para copiar una tabla entera machacando resultados??, ya que la aplicación tendrá otro botón que será restaurar la copia, es decir, la acción inversa (de la tabla de seguridad a la original).

:)

Mathom 10-01-2006 18:52:06

Quizás creando una tabla nueva??...respetaría las claves??

maeyanes 10-01-2006 19:06:56

O eliminando los registros de la tabla destino antes de hacer la copia...

ContraVeneno 10-01-2006 19:21:28

o tal vez:
Código:

insertar
 si hay error de violación de clave entonces
  actualizar


Mathom 11-01-2006 13:03:53

Ya estoy aquí, he estado probando y me compila pero después al intentar ejecutarlo se me cuelga, os indico el código a ver si sabeis que pasa...fijo que es un error en un while y no lo veo....

Código:

procedure TFormPrincipal.Realizarcopia1Click(Sender: TObject);
begin
  while not DM.TblDepartamentos_seg.Eof do
          DM.TblDepartamentos_seg.Delete;

  while not DM.TblDepartamentos.Eof do
    DM.TblDepartamentos_seg.Insert;
    DM.TblDepartamentos_seg.FieldByName('Nombre').AsString := DM.TblDepartamentos.fieldbyname('Nombre').AsString;
    DM.TblDepartamentos_seg.FieldByName('Cod_dep').AsString := DM.TblDepartamentos.fieldbyname('Cod_dep').AsString;
    DM.TblDepartamentos_seg.Post;
    DM.TblDepartamentos_seg.Refresh;
end;

Gracias por vuestra ayuda:p

Mathom 11-01-2006 13:10:39

no hagais caso, me he dejado el begin:eek:. Lo siento mea culpa....

Mathom 11-01-2006 13:21:20

Perdón por el error anterior. Ya me funciona, también se me había olvidado poner que las tablas fuesen adelantando un registro. Al final para aquel que le interese el código ha quedado del siguiente modo:

Código:

procedure TFormPrincipal.Realizarcopia1Click(Sender: TObject);
begin
  while not DM.TblDepartamentos_seg.Eof do
          DM.TblDepartamentos_seg.Delete;
  DM.TblDepartamentos_seg.Refresh;
  while not DM.TblDepartamentos.Eof do
  begin
    DM.TblDepartamentos_seg.Insert;
    DM.TblDepartamentos_seg.FieldByName('Nombre').AsString := DM.TblDepartamentos.fieldbyname('Nombre').AsString;
    DM.TblDepartamentos_seg.FieldByName('Cod_dep').AsString := DM.TblDepartamentos.fieldbyname('Cod_dep').AsString;
    DM.TblDepartamentos_seg.Post;
    DM.TblDepartamentos_seg.Refresh;
    DM.TblDepartamentos_seg.Next;
    DM.TblDepartamentos.Next;
  end;
end;

Gracias por vuestra ayuda.

Mathom 12-01-2006 11:45:35

Hola a todos, de nuevo con mis problemas...seguramente tontos.

Recordais que quería hacer una copia de seguridad (esplicada más arriba) y que, resumiendo, tenía que borrar los registros antes de copiarlos??? Bien, pues en eso estoy, el caso es que tengo tablas maestro- detalle. La idea es borrar todas las tablas una por una por lo que el código se me queda del siguiente modo:

Código:

procedure TFormPrincipal.Realizarcopia1Click(Sender: TObject);
begin
  DM.TblPedidos_seg.First;
  while not DM.TblPedidos_seg.Eof do
  begin
    DM.TblArticulosPedido_seg.First;
    while not DM.TblArticulosPedido_seg.Eof do
      DM.TblArticulosPedido_seg.Delete;
    DM.TblPedidos_seg.Delete;
    DM.TblPedidos_seg.Refresh;
  end;

    DM.TblAlbaranes_seg.First;
    While not DM.TblAlbaranes_seg.Eof do
    begin
      DM.TblDetalleAlbaranes_seg.First;
      while not DM.TblDetalleAlbaranes_seg.Eof do
          DM.TblDetalleAlbaranes_seg.Delete;
      DM.TblAlbaranes_seg.Delete;
      DM.TblAlbaranes_seg.Refresh;
    end;
..............

DM.TblDepartamentos_seg.First;
  while not DM.TblDepartamentos_seg.Eof do
          DM.TblDepartamentos_seg.Delete;
  DM.TblDepartamentos_seg.Refresh;
...........

El final del código sería la copia de las tablas pero primero esto.
EL tema es que lo ejecuto y al pulsar en ralizar copia me aparece el mensaje de error:

"TblPedidos_seg:Cannot perfom this operation on an empty dataset"

El caso es que me borra los registros u posteriormente saca este error por lo que la aplicación (la copia de seguridad, o sea, lo borrados de las otras tablas) se detiene. El resto de la aplicación sigue funcionando.

Si la acaba de borrar la de pedidos por que da el error?? en todo caso no debería ser si estuviese vacia desde un principio??

A ver si me lo aclarais un poco, porque no entiendo nada..:(

gracias...

maeyanes 12-01-2006 15:23:54

Prueba quitando la línea que hace el Refresh...

Es lo único que veo en tu código que podría estar provocando el error.


Saludos...

ContraVeneno 12-01-2006 16:25:18

¿No sería mejor usar un "Drop table" o un "delere from" en lugar de ir borrando registro por registro?

maeyanes 12-01-2006 16:38:47

Tomando lo que dice ContraVeneno, el componente TTable tiene un método llamado EmptyTable que bien te podría servir para lo que buscas.



Saludos...

Mathom 12-01-2006 19:19:54

Gracias....he quitado la línea del refresh y me ha funcionado. Pero no lo entiendo, por que daba el error???

De nuevo, gracias.

Mathom 16-01-2006 19:19:12

Hola e nuevo, vuelvo con mis dudas...me encuentro en el intento de copiar los datos de una tabla maestro detalle a otra maestro-detalle. En un principio intentaba copiar las tablas por separado pero no me aparece la información correcta en la detalle y no me aparecía nada en la pedidos. Ahora estoy probando de otro modo, el código que utilizo es el siguiente:

Código:

DM.TblPedidos.First;
  while not DM.TblPedidos.Eof do
  begin
    DM.TblPedidos_seg.Insert;
    DM.TblPedidos_seg.FieldByName('Id').AsString := DM.TblPedidos.fieldbyname('Id').AsString;
    DM.TblPedidos_seg.FieldByName('Proveedor').AsString := DM.TblPedidos.fieldbyname('Proveedor').AsString;
    DM.TblPedidos_seg.FieldByName('Cod_Pedido').AsString := DM.TblPedidos.fieldbyname('Cod_Pedido').AsString;
    DM.TblPedidos_seg.FieldByName('Nom_Proveedor').AsString := DM.TblPedidos.fieldbyname('Nom_Proveedor').AsString;
    DM.TblPedidos_seg.FieldByName('Fecha').AsString := DM.TblPedidos.fieldbyname('Fecha').AsString;
    DM.TblPedidos_seg.FieldByName('Fecha_prevista').AsString := DM.TblPedidos.fieldbyname('Fecha_prevista').AsString;
    DM.TblPedidos_seg.FieldByName('Fecha_llegada').AsString := DM.TblPedidos.fieldbyname('Fecha_llegada').AsString;
    DM.TblPedidos_seg.FieldByName('Gen_Albaran').AsString := DM.TblPedidos.fieldbyname('Gen_Albaran').AsString;
    while not DM.TblArticulosPedido.Eof do
      begin
        DM.TblArticulosPedido_seg.Insert;
        DM.TblArticulosPedido_seg.FieldByName('Articulo').AsString := DM.TblArticulosPedido.fieldbyname('Articulo').AsString;
        DM.TblArticulosPedido_seg.FieldByName('Id').AsString := DM.TblArticulosPedido.fieldbyname('Id').AsString;
        DM.TblArticulosPedido_seg.FieldByName('Cod_Pedido').AsString := DM.TblArticulosPedido.fieldbyname('Cod_Pedido').AsString;
        DM.TblArticulosPedido_seg.FieldByName('Cantidad').AsString := DM.TblArticulosPedido.fieldbyname('Cantidad').AsString;
        DM.TblArticulosPedido_seg.FieldByName('Ultimo_precio').AsString := DM.TblArticulosPedido.fieldbyname('Ultimo_precio').AsString;
        DM.TblArticulosPedido_seg.Post;
        DM.TblArticulosPedido_seg.Next;
      DM.TblArticulos.Next;
      end;
    DM.TblPedidos_seg.Post;
    DM.TblPedidos_seg.Next;
    DM.TblPedidos.Next;
  end;

Pero me da el siguiente error:

"Corrupt Index. Index E:\webs\Hotels\delphi\DBHG_seg\DB\PEDIDOS.PX"

Entonces mis preguntas son:

- PQ no se pueden copiar las tablas por separado??:confused:
- Es el código lo que hace que me de el error comentado??:confused:

Espero que me podais echar una mano.

Un saludo y gracias...

maeyanes 16-01-2006 19:30:49

El problema puede estar en que en las relaciones maestro-detalle, se necesita que exista el registro padre antes de poder insertar los registros hijos, por aquello de la integridad referencial.

Entonces, en tu código, insertas un registro padre, pero antes de hacer el post, insertas los registros hijos y haces post a cada hijo, pero al no existir un registro padre se produce un error.

Trata haciendo el post del registro padre antes de insertar los registros hijos.



Saludos...

Mathom 17-01-2006 11:52:54

Hola a todos desde lo más profundo de la desesperación..después del último comentario de maeyanes parecía que me había funcionado pero de nuevo me da algún error en tiempo de ejecución, cuando no es un Corrupt Index es un Key Violation y si no un Table is not in insert o edit mode....resumiendo que me desespero. Por lo tanto os quería pedir permiso para poneros todo el código que envuelve ala operación de realizar copia para ver si de una vez por todas lo puedo a echar para adelante. No es demasiado código, y es muy simple (muy repetitivo, lo mismo para cada una de las tablas) pero es bastante y no quisiera ni que os aburrais antes de leerlo ni abusar.

Bien, espero vuestra respuesta para pasaroslo y explicaros como está hecho.

Gracias de antemano y espero no estar abusando pero empiezo a estar un poco (por decir algo) de los nervios.

ContraVeneno 17-01-2006 17:10:32

  • Creo que solo bastaría el "Next" que utilizas para controlar el ciclo "While" pero ¿Para qué sirve la instrucción "Next" que pones despues de cada "Post"?
  • Si lo que quieres copiar el contenido de una tabla en otra, ¿es necesario hacerlo registro por registro? ¿SQL podría funcionar?
  • Con todo respeto, si pones todo el código yo no lo leería :o

Lepe 17-01-2006 18:50:17

Código Delphi [-]
DM.TblPedidos.First;
  while not DM.TblPedidos.Eof do
  begin
    DM.TblPedidos_seg.Insert;
    DM.TblPedidos_seg.FieldByName('Id').AsString := DM.TblPedidos.fieldbyname('Id').AsString;
...
//   no puedes empezar a grabar los detalles, porque la maestra todavia
//   no se ha guardado.
    dm.TblPedidos_seg.Post; //<<<< ahora si se ha guardado el maestro.
//                                 ya podemos empezar con los detalles.
    dm.tblArticulosPedidos.First; // claro, empezamos en el primero.
    while not DM.TblArticulosPedido.Eof do
      begin
        DM.TblArticulosPedido_seg.Insert;
        DM.TblArticulosPedido_seg.FieldByName('Articulo').AsString := DM.TblArticulosPedido.fieldbyname('Articulo').AsString;
...
        DM.TblArticulosPedido_seg.Post;
        DM.TblArticulosPedido_seg.Next; <<<<<end;
    DM.TblPedidos_seg.Post;<<<<<<<<< esto sobra
    DM.TblPedidos_seg.Next;<<<<<<<<< esto sobra
    DM.TblPedidos.Next; // exacto, la misma tabla del bucle.
  end;

Solo me queda un par de dudas.

No sé ni me voy a parar en mirar que campos son los que actuan en la relación maestra-detalle y cuales son claves primarias. Tú debes saberlo exactamente y debes tener mucho cuidado. Si en tblPedidos-tblArticulosPedido lo une un código que tiene el valor 10, puede que ese ya exista en tblPedidos_seg No sé pero es algo a tener en cuenta.

Para los indices, asegurate de que todas las tablas tengan en el evento afterpost ttable.FlushBuffers.

saludos y espero se entienda

Lepe 17-01-2006 18:57:28

Resumiendo:

Código:


maestra.first
while not maestra.eof do
begin
  otraMaestra.Insert
  copiar campos
  otraMaestra.Post

  Detalle.First
  while not Detalle.eof do
  begin
    OtraDetalle.Insert;
    copiar campos
    OtraDetalle.Post;

    Detalle.Next;
  end;
  Maestra.Next;
end;

Ojo con poner instrucciones TTable.DisableControls, porque con tablas paradox y BDE se rompe la relación maestra-detalle, y entonces si que la liamos :D usa TTable.BlockreadSize := 1024 y ttable.BlockReadSize := 0; mira en la ayuda para más información.

saludos de nuevo ;)
saludos.

Mathom 18-01-2006 09:13:16

Ante todo gracias a los dos por vustras respuestas, la verdad, hasta me resultaba incómodo pediros permiso para poner todo el código pero son las cosas que tiene la desesperación...diciendo eso voy por partes:

Contraveneno
Cita:

Con todo respeto, si pones todo el código yo no lo leería :o
No te preocupes, es muy lógico, el foro está para ofrecer soluciones, no trabajos enteros ni tener que estar 30 min. leyendo código..realmente el código no es tanto pero hubiese llamado la atención..de ahí que pidiese permiso. Lo dicho, no te preocupes y gracias...:)

Ahora ya, yendo al tema..gracias Lepe, ahora mismo voy a probarlo a ver que tal, sólo un par de cosillas:

Lepe
Cita:

Si en tblPedidos-tblArticulosPedido lo une un código que tiene el valor 10, puede que ese ya exista en tblPedidos_seg No sé pero es algo a tener en cuenta.
Antes de proceder al copiado de las tablas, borro todo el contenido de éstas para que no me pase exactamente eso, que intente copiar un registro que ya esté. Por lo tanto, es correcto lo que estoy intentando hacer, no??

Por último, que se pretende con TTable.BlockreadSize := 1024 y ttable.BlockReadSize := 0;??? De todos modos como tu dices ahora le echaré un vistazo en la ayuda.


Bueno, voy a intentar...gracias amigos!!:D

Mathom 18-01-2006 10:22:40

Una cosilla más...Lepe comenta

Cita:

Para los indices, asegurate de que todas las tablas tengan en el evento afterpost ttable.FlushBuffers.
Sería exactamente ttable.FlushBuffers y ttable se refiere a la tabla en la cual estamos o sería TblPedidos.FlushBuffers, TblAlbaran.FlushBuffers, y así sucesivamente..(esto por supuesto cada una en su tabla).

Cuando te refieres a todas las tablas son todas todas o todas las que terminan en "_seg"???

De nuevo gracias y perdón por mi inexperiencia.:o

Lepe 18-01-2006 11:49:49

Bueno... en realidad no es para los índices, pero si puede ayudar. Eso hace que los datos se escriban a disco desde la RAM, así despues de grabar auque haya un corte de luz, los datos no se pierden.

Puedes usar un solo evento AfterPost para todas los TTables. Seleccionas una tabla, te vas al inspector de objetos y en el evento Afterpost escribes "AfterPostTodasLasTablas"

En su interior escribes esto:
Código Delphi [-]
TTable(Sender).FlushBuffers

Ahora mantienes presionada la tecla Shift (alternar mayusculas y minúsculas) y vas dando clics a todas las tablas, una vez que las tienes todas seleccionadas a la vez, vuelves al inspector de Objetos, y en el evento AfterPost eliges de la lista desplegable el que tú has hecho.

Todas las tablas comparten el mismo evento, y puesto que el parámetro Sender es la tabla que se mande hacer el Post, hará el Flushbuffers para todas ellas ;)

Cuando digo tablas, me refiero a todos los TTables que tengas en tu programa.

¿Perdonarte por tu inexperiencia? ni hablar, agradecerte que te intereses por todos los temas que se han comentado ;)

saludos

Mathom 25-01-2006 10:06:28

Hola a todos, siento haber tardado en responder...estaba malito.

A ver, creo que es el último problemilla que se me presenta...resulta que si realizo la copia de seguridad me funciona correctamente, ahora...si le vuelvo a dar a realizar copia me da un error "Master Record Missing".

Si cierro la aplicación y la vuelvo a arrancar y pulso de nuevo copia de seguridad me lo vuelve a hacer correctamente, es decir, no puedo ejecutarlo dos veces en la aplicación sin cerrarla y arrancarla de nuevo...

...a que puede ser debido???

si soluciono esto habré terminado y seré feliz....al fin.

Gracias a todos...:)

poniente 26-01-2006 10:09:51

no se como crear nuevo tema
 
Cita:

Empezado por Neftali
Seguramente en la tabla destino ya existe un valor igual al que estás intentando copiar.

Hola soy nuevo en este foro y no se como crear un nuevo tema,
agradeceria que me lo explicasen, muchisimas gracias y perdonad mi
ignorancia.

GRACIAS

Neftali [Germán.Estévez] 26-01-2006 10:32:32

Cita:

Empezado por poniente
Hola soy nuevo en este foro y no se como crear un nuevo tema

Hola y bienvenido.

(1) Desde la página principal de ClubDelphi: http://www.clubdelphi.com pulsa en Foros; Parte superior derecha.
(2) Selecciona el foro más adecuado para tu tema.
(3) Por encima de los mensajes verás un botón que pone "Nuevo Hilo".

Antes de escribir te recomiendo que leas la guía de estilo
Cuando escribas, escoge un título que describa bien el problema y explica lo que te pasa con detalle y dando datos de con qué trabajas (Delphi, Base de Datos, versiones que utilizas,...)
Si es referente a código, es bueno que también coloques algún trozo del código.

Un saludo.


La franja horaria es GMT +2. Ahora son las 14:06:07.

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