Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Conexión con bases de datos
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Conexión con bases de datos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 24-06-2014
giulichajari giulichajari is offline
Miembro
 
Registrado: nov 2012
Posts: 306
Poder: 12
giulichajari Va por buen camino
no se puede agregar la clave foranea

Tengo un datamodule con 3 sqlquery (sqlquery1, sqlquery2, y aux).
Y en la bd tengo una tabla persona y una tabla cliente. En la tabla cliente tengo el idpersona, pero algo falla al querer agregar un cliente, mne agrega los datos de la tabla madre solamente.

Los procedimientos son:

Código Delphi [-]
procedure Tferreteria.inserpersona(persona:Tpersona);
begin
  dm:=Tconsultas.Create(nil);
   dm.SQLQuery1.Close;
   dm.SQLQuery1.SQL.Add('insert into persona (nombreyape, domicilio)values (:nombreyape,:domicilio);');

   with dm.SQLQuery1 do
    begin
      ParamByName('nombreyape').AsString:=persona.nombreyape;
      ParamByName('domicilio').AsString:=persona.domicilio;


    end;
    dm.SQLQuery1.ExecSQL();
     dm.SQLQuery1.Close;
end;


Código Delphi [-]
procedure TFerreteria.insercliente(cliente:Tcliente);
begin
    dm:=Tconsultas.Create(nil);
    dm.SQLQuery2.Close;


    dm.SQLQuery2.SQL.Add ('insert into clientes(idpersona,cuit,cuil) values (:idpersona,:cuit,:cuil);');
    with dm.SQLQuery2 do
    begin
    dm.aux.SQL.Add('select max(idpersona) from persona as idp;');
    dm.aux.ExecSQL();
      ParamByName('idpersona').Value:=dm.aux.ParamByName('idp').AsInteger;
      ParamByName('cuit').Value:=cliente.cuit;
      ParamByName('cuil').Value:=cliente.cuil;
    end;
    dm.SQLQuery2.ExecSQL();
    dm.SQLQuery2.Close;
end;

Espero alguien pueda ayudarme, los sqlquery tienen los parametros en la propiedad TParams.. agregados.

Gracias
Responder Con Cita
  #2  
Antiguo 26-06-2014
Avatar de duilioisola
[duilioisola] duilioisola is offline
Miembro Premium
 
Registrado: ago 2007
Ubicación: Barcelona, España
Posts: 1.734
Poder: 20
duilioisola Es un diamante en brutoduilioisola Es un diamante en brutoduilioisola Es un diamante en bruto
En tu código ejecutas el query de aux. En su lugar deberías abrirlo.
Si lo ejecutas no obtendrás resultados. Esta instrucción está pensada para ejecutar cosas como un insert/update/delete que no devuelvan nada.
No recuerdo si la instrucción es Open u OpenSQL.
Código Delphi [-]
procedure TFerreteria.insercliente(cliente:Tcliente);
begin
    dm:=Tconsultas.Create(nil);
    dm.SQLQuery2.Close;

    dm.SQLQuery2.SQL.Add ('insert into clientes(idpersona,cuit,cuil) values (:idpersona,:cuit,:cuil);');
    with dm.SQLQuery2 do
    begin
    dm.aux.SQL.Add('select max(idpersona) from persona as idp;');

     // Aquí debes abrir el dataset.
    dm.aux.Open;
      
      ParamByName('idpersona').Value:=dm.aux.ParamByName('idp').AsInteger;
      ParamByName('cuit').Value:=cliente.cuit;
      ParamByName('cuil').Value:=cliente.cuil;
    end;
    dm.SQLQuery2.ExecSQL();
    dm.SQLQuery2.Close;
end;

De todos modos yo organizaría un poco mejor el código y creo además que te falta liberar el objeto creado (Tconsultas).
Si me permites:
Código Delphi [-]
procedure TFerreteria.insercliente(cliente:Tcliente);
begin
    dm := Tconsultas.Create(nil);
    try
        // Obtengo el Id de la persona
        dm.aux.SQL.Add('select max(idpersona) from persona as idp;');
        // Aquí debes abrir el dataset.
        dm.aux.Open;

        // Inserto el cliente
        with dm.SQLQuery2 do
        begin
            Close;
            SQL.Add ('insert into clientes(idpersona,cuit,cuil) values (:idpersona,:cuit,:cuil);');
            ParamByName('idpersona').Value:=dm.aux.ParamByName('idp').AsInteger;
            ParamByName('cuit').Value:=cliente.cuit;
            ParamByName('cuil').Value:=cliente.cuil;
            ExecSQL();
            Close;
        end;
        dm.aux.Close;
    finally
        // Creo que aquí deberías liberar el objeto TConsultas
        dm.Free;
    end;
end;

Última edición por duilioisola fecha: 26-06-2014 a las 18:17:58.
Responder Con Cita
  #3  
Antiguo 26-06-2014
giulichajari giulichajari is offline
Miembro
 
Registrado: nov 2012
Posts: 306
Poder: 12
giulichajari Va por buen camino
Gracias

Gracias por responder, voy a probar el codigo.

Lo que me han dicho otros colegas, es que
Código SQL [-]
select max(id)
sirve solo si un solo usuario puede insertar en una tabla.

Porque si varios acceden, por concurrencia, no devolvera exactamente el ultimo id insertado.

Para esto se debe usar mas bien
Código SQL [-]
Select last_insert_id();
que devuelve el de la sesion. Pero no se me ocurre como resolver esto, ya que deberia usar el mismo TSQLQuery?

Saludos
Responder Con Cita
  #4  
Antiguo 26-06-2014
Avatar de duilioisola
[duilioisola] duilioisola is offline
Miembro Premium
 
Registrado: ago 2007
Ubicación: Barcelona, España
Posts: 1.734
Poder: 20
duilioisola Es un diamante en brutoduilioisola Es un diamante en brutoduilioisola Es un diamante en bruto
Yo utilizo IDs para cada registro de la tabla y luego otros campos para los números de orden, pedido, factura, etc.
El ID es un campo obtenido de un generador y el número del documento se calcula en los triggers.
Todo lo hecho en un trigger está dentro de una misma transacción, por lo que si no hay errores al insertar/modificar, la base de datos se ha encargado de que no haya duplicados.

Yo trabajo con Firebird. Esta base tiene generadores que devuelven el número siguiente del actual.
En los eventos BeforePost es donde obtengo un número para mi ID y se lo asigno al parámetro del dataset. Este ID es imposible que se duplique, por lo solo queda esperar a que el SQL se complete y refrescar los datos que sean necesarios (NRO_DOCUMENTO, TOTALES, etc.)

Código Delphi [-]
function TDMMain.DameGenerador(NomGen: string): integer;
var
  Q : THYFIBQuery;
begin
  Result := 0;
  if (Trim(NomGen) > '') then
  begin
     Q := THYFIBQuery.Create(nil);
     try
        with Q do
        begin
           Close;
           DataBase := Self.DataBase;
           SQL.Text := 'SELECT GEN_ID(' + NomGen + ',1) FROM RDB$DATABASE';
           ExecQuery;
           Result := Fields[0].AsInteger;
           Close;
           FreeHandle;
        end;
     finally
        FreeAndNil(Q);
     end;
  end;
end;

procedure TDMFacturas.QMCabeceraBeforePost(DataSet: TDataSet);
var
  existe : smallint;
begin
  // Solo asigno ID si estoy insertando
  if (DataSet.State = dsInsert) then
     DataSet.FieldByName('ID_CAB_FACTURA_CLI').AsInteger := DMMain.DameGenerador('GEN_CAB_FACTURA_CLI');
  [...]
end;

El trigger sería algo así:
Código SQL [-]
créate trigger CAB_FACTURA_CLI_BI0 for FACTURA before insert 0
as
begin
    /* Calculo el ID si vino vacio */
    if ((new.ID_CAB_FACTURA_CLI = 0) or (new.ID_CAB_FACTURA_CLI is null)) then
        newID_CAB_FACTURA_CLI := GEN_ID(GEN_CAB_FACTURA_CLI, 1);

    /* Calculo el siguiente numero de factura */
    select max(numero) from CAB_FACTURA_CLI
    where
    empresa = new.empresa and
    ejercicio = new.ejercicio and
    serie = new.serie
    into new.numero;
  
    /* Si es la primera factura no me habrá devuelto nada util */
    if ((numero =0) or (new.numero is null)) then
        new.numero = 1;

    [...]
end

Última edición por duilioisola fecha: 26-06-2014 a las 21:55:17.
Responder Con Cita
  #5  
Antiguo 27-06-2014
giulichajari giulichajari is offline
Miembro
 
Registrado: nov 2012
Posts: 306
Poder: 12
giulichajari Va por buen camino
bueno

entiendo tu forma de hacerlo. Y esta buena, lo que si es que obtengo el error

Aux:Parameter idp not found, y SI esta declarado en el value de la propiedad PARAMS del componente, es como que no lo esta cargando.

Saludos..
Responder Con Cita
  #6  
Antiguo 27-06-2014
Avatar de duilioisola
[duilioisola] duilioisola is offline
Miembro Premium
 
Registrado: ago 2007
Ubicación: Barcelona, España
Posts: 1.734
Poder: 20
duilioisola Es un diamante en brutoduilioisola Es un diamante en brutoduilioisola Es un diamante en bruto
[quote=giulichajari;478382]lo que si es que obtengo el error Aux:Parameter idp not found, y SI esta declarado en el value de la propiedad PARAMS del componente, es como que no lo esta cargando.
QUOTE]

Creo que esto se debe a que la sintaxis es incorrecta

Código SQL [-]
/* Tu sintaxis */
select max(idpersona) from persona as idp
/* Esta creo que es la forma correcta */
select max(idpersona) as idp from persona
Responder Con Cita
  #7  
Antiguo 28-06-2014
giulichajari giulichajari is offline
Miembro
 
Registrado: nov 2012
Posts: 306
Poder: 12
giulichajari Va por buen camino
[quote=duilioisola;478385]
Cita:
Empezado por giulichajari Ver Mensaje
lo que si es que obtengo el error Aux:Parameter idp not found, y SI esta declarado en el value de la propiedad PARAMS del componente, es como que no lo esta cargando.
QUOTE]

Creo que esto se debe a que la sintaxis es incorrecta

Código SQL [-]/* Tu sintaxis */ select max(idpersona) from persona as idp /* Esta creo que es la forma correcta */ select max(idpersona) as idp from persona
Y si quiero insertar luego el telefono de la persona? He insertado una persona, un cliente con el id de persona, pero al insertar un telefono el id sera el de cliente...

Saludos
Responder Con Cita
  #8  
Antiguo 28-06-2014
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.038
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
La cara oculta de delphi
Responder Con Cita
  #9  
Antiguo 28-06-2014
giulichajari giulichajari is offline
Miembro
 
Registrado: nov 2012
Posts: 306
Poder: 12
giulichajari Va por buen camino
Logre hacerlo

Logre hacerlo con componentes SQLQuery. Si quieren dejen su opinion.

Código Delphi [-]
procedure Tferreteria.insercliente(cliente:Tcliente;persona:Tpersona;telefono:Ttelefono);



begin
  dm := Tconsultas.Create(nil);
   // dm.SQLQuery1.Close;
    with dm.qpersona do
    begin
      Close;
      SQL.Clear;
      SQL.Add('insert into persona (nombreyape, domicilio) values (:nombreyape, :domicilio);');

      ParamByName('nombreyape').AsString := persona.nombreyape;
      ParamByName('domicilio').AsString := persona.domicilio;


      ExecSQL();
    end;

      with dm.qcliente do
    begin
    Close;
    SQL.Clear;
    SQL.Add('insert into clientes (idpersona, cuit, cuil) values (last_insert_id(), :cuit, :cuil);');

    ParamByName('cuit').AsInteger := cliente.cuit;
    ParamByName('cuil').AsInteger := cliente.cuil;
      ExecSQL();
    end;
    with dm.qtelefono do
    begin
      Close;
      SQL.Clear;
      SQL.Add('insert into telefono (idtipotel, numero)values (:idtipotel,:numero);');
      ParamByName('idtipotel').AsInteger := telefono.tipo;
      ParamByName('numero').AsInteger := telefono.numero;
      ExecSQL();
    end;
    with dm.aux do
    begin
      Close;
      SQL.Clear;
      SQL.Add('select last_insert_id() from persona;');

    end;
    with dm.aux2 do
    begin
      Close;
      SQL.Clear;
      SQL.Add('select last_insert_id() from telefono;');
    end;
    with dm.qpt do
    begin
      Close;
      SQL.Clear;
      SQL.Add('insert into personatel (idpersona,idtelefono) values (:idp,:idt);');
      ParamByName('idp').AsInteger:=dm.aux.ExecSQL();
      ParamByName('idt').AsInteger:=dm.aux2.ExecSQL();
      ExecSQL();
    end;

//    dm.SQLQuery1.ExecSQL();
  end;
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
mostrar campo con clave foranea georgeliners Conexión con bases de datos 3 11-06-2014 22:57:43
identificar un error de clave foranea... pnsd_89 SQL 5 25-03-2011 13:01:03
Campo puede ser clave foranea de dos tabla richy08 Conexión con bases de datos 4 26-01-2010 18:38:54
problema al crear clave foranea anubis Firebird e Interbase 4 28-06-2008 16:24:49
Saber a quien se refiere una clave foránea Cecil Conexión con bases de datos 2 27-09-2007 19:17:50


La franja horaria es GMT +2. Ahora son las 14:44:29.


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
Copyright 1996-2007 Club Delphi