Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Conexión con bases de datos (https://www.clubdelphi.com/foros/forumdisplay.php?f=2)
-   -   Copiar registro de una Tabla a otra Tabla, sin repetirse (https://www.clubdelphi.com/foros/showthread.php?t=45235)

MaMu 27-06-2007 00:52:44

Copiar registro de una Tabla a otra Tabla, sin repetirse
 
Despues de 42 horas sin dormir, me encuentro con que no puedo conseguir algo muy sencillo, tengo dos tablas, y quiero añadirle registros de una a la otra, unicamente cuando estos sean distintos, y lo que hago es lo siguiente:
QAux--->Tabla A
QEstadisticas---->Tabla B

Quiero copiar de A en B, solo aquellos registros que no sean identicos a los de B, segun una condicion X.

Código Delphi [-]
 for h:=0 to QAux.RecordCount-1 do
    begin
      b:=0;
      for j:=0 to QEstadisticas.RecordCount-1 do
        begin
          if QAux.FieldByName('conceptoDEBE').AsString=QEstadisticas.FieldByName('valor').AsString
            then b:=b+1 else b:=b;
          QEstadisticas.Next;
        end;
        if b=0
          then begin
            QEstadisticas.Insert;
            try
              QEstadisticas.FieldByName('categoria').AsString:='Gastos Generales';
              QEstadisticas.FieldByName('valor').AsString:=QAux.FieldByName('conceptoDEBE').AsString;
              QEstadisticas.FieldByName('cantidad').AsInteger:=QAux.FieldByName('cantidad').AsInteger;
              QEstadisticas.FieldByName('subtotal').AsCurrency:=QAux.FieldByName('importe').AsCurrency;
              QEstadisticas.Post;
            except
              QEstadisticas.Cancel;
            end;
          end;
      QAux.Next;
    end;

Pero me copia aun los que estan repetidos, es decir, son identicos en ambas tablas, A y B.

Que estoy haciendo mal? (ademas de no dormir, pero tengo que terminar si o si para poder tomarme unos dias de descanso)

Saludos

vtdeleon 27-06-2007 01:57:14

Que base de datos usas?

Lo mejor es usar sentencias SQL!

Código SQL [-]
Insert into TablaA
  (Select * from TablaB 
   Where TablaB.CampoID<>TablaA.CampoID)
Sino utiliza Locate para buscar el campo llave.

El codigo b:=b no tiene sentido, quita eso!

MaMu 27-06-2007 03:02:51

Cita:

Empezado por vtdeleon
Que base de datos usas?

Lo mejor es usar sentencias SQL!


Código SQL [-]Insert into TablaA
(Select * from TablaB
Where TablaB.CampoID<>TablaA.CampoID)


Sino utiliza Locate para buscar el campo llave.

El codigo b:=b no tiene sentido, quita eso!

Uso Access, y no uso la sentencia sql, porque las tablas son diferentes, solo comparten 3 campos, cuyos FieldNames son diferentes. Lo que no entiendo, es porque me repite uno de los valores.

seara2005 27-06-2007 03:09:44

Copiar Registro de una tabla a otra sin repetirse
 
Prueba algo así como esto

Código Delphi [-]
procedure TransferirDatos(Sender: TObject);
begin
   QAux.First;
  While Not(QAux.Eof) do
    Begin
       If Not(QEstadisticas.Locate('Valor',QAuxConceptoDebe.Value,[loCaseInsensitive])) then
         Begin
            QEstadisticas.Insert;
            try
              QEstadisticas.FieldByName('categoria').AsString:='Gastos Generales';
              QEstadisticas.FieldByName('valor').AsString:=QAux.FieldByName('conceptoDEBE').AsString;
              QEstadisticas.FieldByName('cantidad').AsInteger:=QAux.FieldByName('cantidad').AsInteger;
              QEstadisticas.FieldByName('subtotal').AsCurrency:=QAux.FieldByName('importe').AsCurrency;
              QEstadisticas.Post;
            except
              QEstadisticas.Cancel;
            end;
         End;
      QAux.Next;
    End;
end;

egostar 27-06-2007 03:17:08

Haber si esto te puede servir

Código Delphi [-]
function TForm1.No_Existe(Dato:String):Bool;
begin
  Query1.Close; 
  Query1.SQL.Text := 'SELECT * FROM ESTADISTICAS WHERE VALOR = :dato';
  Query1.ParamByName('Dato').AString := Dato;
  Query1.Open;
  If RecordsCount = 0 then
     Result := True
  else Result := False;
end;

........
........
While not QAux.EoF do begin
   if No_Existe(QAux.FieldByName('conceptoDEBE').AsString) then begin
      QEstadisticas.Insert;
      try
        QEstadisticas.FieldByName('categoria').AsString:='Gastos Generales';
        QEstadisticas.FieldByName('valor').AsString:=QAux.FieldByName('conceptoDEBE').AsString;
        QEstadisticas.FieldByName('cantidad').AsInteger:=QAux.FieldByName('cantidad').AsInteger;
        QEstadisticas.FieldByName('subtotal').AsCurrency:=QAux.FieldByName('importe').AsCurrency;
        QEstadisticas.Post;
      except
        QEstadisticas.Cancel;
      end;
   end;
   QAux.Next;
end;

Aunque lo hice al aire porque no tengo mi Delphi, puede haber algun error.

Salud OS.

Edito: Se me adelanto sara2005, y me parece una muy buena idea la del LOCATE.

vtdeleon 27-06-2007 04:22:25

Cita:

Uso Access, y no uso la sentencia sql,
Mejor aun, y mas razon para usar las sentencias.
Cita:

porque las tablas son diferentes, solo comparten 3 campos, cuyos FieldNames son diferentes
Eso no importa.

Danos detalles de las tablas, los campos relacionados, y el campo Id (el cual no queires que se repita).

Neftali [Germán.Estévez] 27-06-2007 09:42:36

Cita:

Empezado por mamu
Quiero copiar de A en B, solo aquellos registros que no sean identicos a los de B, segun una condicion X.
Pero me copia aun los que estan repetidos, es decir, son identicos en ambas tablas, A y B.

Lo que veo es que haces dos for anidados para recorrer ambas tablas. Para el primer registro de la primera copiarás todos los de la segunda que son diferentes, pero igual para el segundo de la primera, el tercero de la primera,....

Creo que estás haciendo más recorridos de la cuenta; Recorre una única tabla y dentro de ese busca en la segunda (sea con SQL como te han dicho o con un Locate).

MaMu 27-06-2007 20:32:39

SOLUCIONADO

Gracias a todos, tome un poco de cada una de las sugerencias de ustedes y logre solucionarlo.

Muchas Gracias

egostar 27-06-2007 21:04:40

Cita:

Empezado por mamu
SOLUCIONADO

Gracias a todos, tome un poco de cada una de las sugerencias de ustedes y logre solucionarlo.

Muchas Gracias

Hola mamu

Muchos de nosotros te agradeceriamos que postearas la solución para consultas futuras, de esa manera, quien tenga un problema similar trendrá de primera mano la solución a sus dudas.

Salud OS.

Crashthebig 03-07-2007 05:17:23

Solucion
 
deberas declarar la tabla de la que copiaras los datos con el nombre: tblsource, y la tabla a la que copiaras los datos con el nombre de: tbldest.

y copia este codigo en algun boton
Código Delphi [-]
 var
   i : integer;
   fldDest, fldSource : TField;
 begin
   with tblDest do begin
     Append;
     for i := 0 to FieldCount - 1 do
     begin
       fldDest := Fields[i];
       if not (fldDest.ReadOnly or fldDest.Calculated) then
       begin
         fldSource := tblSource.FindField(fldDest.FieldName);
         if assigned(fldSource) then
         begin
           fldDest.DataSet.Edit;
           fldDest.AsString := fldSource.AsString
         end
       end
     end;
   {Post}
   end

esta sentencia copiara el registro activo de la tabla tblsource a la tabla tbldest

Vales08 06-04-2013 21:24:08

Buenas tardes, me meto en este hilo porque tengo la misma consulta...
Pasar registros de una tabla a otra, pero sin que se repitan. yo lo hago mediante dos dbgrid y en un boton puse el codigo que paso seara2005, lo modifiqué segun mi programa, pero el problema esta en que me carga el registro tantas veces como registros hay cargado en la tabla.. (ejemplo: si tengo 3 registros en total cargado en la tabla principal, me carga el registro 3 veces en la otra tabla).

Como puedo solucionar eso? o que estoy haciendo mal.. Les paso mi codigo para que me puedan ayudar..
Código Delphi [-]
DM.Q_alim.First;
  While Not(DM.Q_alim.Eof) do
    Begin
       If Not(DM.Q_plan_y_alim.Locate('ID_ALIM',DM.Q_alimID_ALIM.Value,[loCaseInsensitive])) then
         Begin
            DM.DSET_plan_y_alim.Insert;
            try
              DM.DSET_plan_y_alimESTADO.Value:=0;
              DM.DSET_plan_y_alim.FieldByName('ID_ALIM').AsInteger:=DM.DSET_alim.FieldByName('ID_ALIM').AsInteger;
              DM.DSET_plan_y_alim.FieldByName('ID_PLAN').AsInteger:=DM.DSET_plan_alim.FieldByName('ID_PLAN_A').AsI  nteger;
              DM.DSET_plan_y_alim.Post;
            except
              DM.DSET_plan_y_alim.Cancel;
            end;
         End;
      DM.Q_alim.Next;
    End;

Aclaro: a la hora de la inserción uso el DataSet porque el Query no me permite el ingreso de registros ya que es de solo lectura.

Muchas gracias

ecfisa 07-04-2013 00:45:18

Hola Vales08.

También podes pasar registros de una tabla a otra, sin que aquellos se repitan, de este modo:
Código SQL [-]
INSERT INTO TABLA_DESTINO (ID, CP1, CP2 ,...)
SELECT ID, CP1, CP2,... 
FROM TABLA_ORIGEN T1
WHERE NOT EXISTS (SELECT T2.ID, T2.CP1, T2.CP2 ,...
                  FROM TABLA_DESTINO T2
                  WHERE T1.ID = T2.ID
                    AND T1.CP1 = T2.CP1
                    AND T1.CP2 = T2.CP2
                    ...)

Saludos.

Vales08 08-04-2013 19:13:29

ecfisa muchas gracias por la respuesta..
Eh probado el código pero me salta un error y no se que puede ser..
Error:
Cita:

Dynamic SQL Error
SQL error code = -804
Count of columns does not equal count of values
El codigo:
Código Delphi [-]
DM.Q_plan_y_alim.Active:=False;
with DM.Q_plan_y_alim.SQL do
  begin
    Clear;
    Add('INSERT INTO PLAN_Y_ALIM (ID_PLAN_Y_ALIM, ID_ALIM, ID_PLAN)');
    Add('SELECT ID_ALIM ');
    Add('FROM ALIMENTOS ');
    Add('WHERE NOT EXISTS (SELECT PLAN_Y_ALIM.ID_PLAN_Y_ALIM, PLAN_Y_ALIM.ID_ALIM, PLAN_Y_ALIM.ID_PLAN ');
    Add('FROM PLAN_Y_ALIM ');
    Add('WHERE ALIMENTOS.ID_ALIM = PLAN_Y_ALIM.ID_ALIM)');
  end;
DM.Q_plan_y_alim.Active:=True;

Me gustaria que me orientaras a saber donde puede estar el problema..

ecfisa 08-04-2013 20:15:18

Hola Vales08.

A primera vista, en la línea:
Código SQL [-]
 Add('INSERT INTO PLAN_Y_ALIM (ID_PLAN_Y_ALIM, ID_ALIM, ID_PLAN)');
indicas que vas a insertar valores en tres columnas de la tabla PLAN_Y_ALIM.

Pero en las líneas:
Código SQL [-]
 Add('SELECT ID_ALIM');
 Add('FROM ALIMENTOS');
Solo seleccionas una columna de la tabla ALIMENTOS, es que decir que faltaría especificar dos columnas de dicha tabla para ser insertados en las columnas ID_ALIM e ID_PLAN de la tabla PLAN_Y_ALIM

Saludos.

Vales08 08-04-2013 23:03:48

Ahh claro..
Lo que sucede es que en la tabla PLAN_Y_ALIM solo tengo el ID_PLAN_Y_ALIM y luego las forenkey ID_ALIM (Pertenece a la tabla ALIMENTOS) y ID_PLAN (pertenece a la tabla PLANES_ALIM).
Entonces lo que yo necesito es que al seleccionar un registro de la tabla ALIMENTOS, ese registro se guarde en la tabla PLAN_Y_ALIM, donde se genera un ID_PLAN_Y ALIM y se le asigna el ID_ALIM seleccionado y el ID_PLAN de la tabla PLANES_ALIM (ese id sale de un alta que hago antes). No se si se entiende.
el codigo tendria que quedar asi entonces:

Código Delphi [-]
DM.Q_plan_y_alim.Active:=False;
with DM.Q_plan_y_alim.SQL do
  begin
    Clear;
    Add('INSERT INTO PLAN_Y_ALIM (ID_ALIM, ID_PLAN)');
    Add('SELECT ID_ALIM ');
    Add('FROM ALIMENTOS ');
    Add('WHERE NOT EXISTS (SELECT PLAN_Y_ALIM.ID_ALIM, PLAN_Y_ALIM.ID_PLAN ');
    Add('FROM PLAN_Y_ALIM ');
    Add('WHERE ALIMENTOS.ID_ALIM = PLAN_Y_ALIM.ID_ALIM');
    Add('AND PLANES_ALIM.ID_PLAN_A = PLAN_Y_ALIM.ID_PLAN)')
  end;
DM.Q_plan_y_alim.Active:=True;

Seria mas o menos asi??

ecfisa 08-04-2013 23:35:29

Hola Vales08.


Si, si el campo ID de la tabla PLAN_Y_ALIM se genéra automáticamente sólo sería necesario completar esos campos.

Pero cuando te referis a:
Cita:

Entonces lo que yo necesito es que al seleccionar un registro de la tabla ALIMENTOS, ese registro se guarde en la tabla PLAN_Y_ALIM...
No me queda en claro si es lo que estas precisando... Por que la sentencia SQL que te puse en el mensaje #12, copia todos los campos no repetidos de una tabla a otra (que es de lo que se trataba inicialmente el hilo)

Saludos.

Vales08 08-04-2013 23:43:48

Ahh entonces estoy equivocada con el codigo.. Yo necesito pasar archivos de una tabla a otra sin repetir, pero no todos, si no los que yo voy seleccionando desde una grilla..
Mil disculpas por haber ocupado tu tiempo en algo que no era. Y muchas gracias por tu dedicación.

Neftali [Germán.Estévez] 09-04-2013 09:05:53

Cita:

Empezado por Vales08 (Mensaje 458285)
Yo necesito pasar archivos de una tabla a otra sin repetir, pero no todos, si no los que yo voy seleccionando desde una grilla..

En ese caso deberás pasarlos 1 a 1 realizando un recorrido por los que tienes seleccionados en el DBGRid.
Para el recorrido puedes utilizar la propiedad SelectedRows y para cada registro hacer la copia.

Código Delphi [-]
var
  i: Integer;
begin
  if DBGrid1.SelectedRows.Count > 0 then  begin
    with DBGrid1.DataSource.DataSet do  begin
      for i := 0 to DBGrid1.SelectedRows.Count-1 do  begin
        GotoBookmark(Pointer(DBGrid1.SelectedRows.Items[i]));
        
        => Realizar la copia del registro actual....


      end;
    end;
  end
end;

Vales08 09-04-2013 15:24:21

Bien y en la parte donde tengo que realizar la copia del registro lo hago con el codigo SQL como el que me habias pasado antes? o hay alguna forma para hacerlo con codigo delphi?

Neftali [Germán.Estévez] 09-04-2013 17:18:08

Cita:

Empezado por Vales08 (Mensaje 458311)
Bien y en la parte donde tengo que realizar la copia del registro lo hago con el codigo SQL como el que me habias pasado antes? o hay alguna forma para hacerlo con codigo delphi?

Puedes hacerlo con SQL puedes utilizar una sentencia similar a la de arriba.

Para hacerlo utilizando comandos en Delphi, revisa código como este:

Código Delphi [-]

  DS.Append;
  DS.FieldByName('Codigo').AsString := ACod;
  DS.FieldByName('Nombre').AsString := ANombre;
  ....
  DS.Post;


La franja horaria es GMT +2. Ahora son las 10:44:25.

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