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)
-   -   error al ejectuar query dentro de beforepost (https://www.clubdelphi.com/foros/showthread.php?t=51763)

johnlobo 28-12-2007 13:02:53

error al ejectuar query dentro de beforepost
 
Hola a todos,

Estoy desarrollando una aplicación con ADO y ACCESS, y tengo una tabla TADOTable ("tabla") que tiene un autoincremental como PK, y un campo numérico ("código") como código significativo para los usuarios.
Este código significativo tiene que ser continuo (sucesivo sin huecos), y en la gestión de esta continuidad es donde estoy encontrando los problemas.

En el evento Beforepost de la tabla principal, intento hacer un "Select MAX(codigo) FROM tabla" con un TADOQuery para sacar el último código introducido, y guardarlo en el campo "código", y lo que obtengo es un bonito error de esta guisa... "[Microsoft][Controlador ODBC Microsoft Access] Error de sintaxis en la clausula FROM". Obviamente este error no tiene sentido, porque la tabla de la clausula from existe.
Desde otros eventos de la tabla como "onposterror" y "afterpost" también falla... sin embargo desde fuera de los eventos de la tabla funciona perfectamente.

Me imagino que tiene que ser algo relacionado con bloqueos, o con hacer una query sobre una tabla en sus propios eventos, pero llevo dos días buscando información y no logro encontrar la manera de solventarlo.

Alguna idea??

Muchas gracias por adelantado,
John.

juanlaplata 28-12-2007 15:36:54

y por que no puede ser tipo autoincremental ese campo?
si no date una vuelta por el evento OnCalcFields de TTable. Tal ves ahi puedas.

enecumene 28-12-2007 16:45:20

Cita:

Empezado por johnlobo (Mensaje 254775)

En el evento Beforepost de la tabla principal, intento hacer un "Select MAX(codigo) FROM tabla" con un TADOQuery para sacar el último código introducido, y guardarlo en el campo "código", y lo que obtengo es un bonito error de esta guisa... "[Microsoft][Controlador ODBC Microsoft Access] Error de sintaxis en la clausula FROM". Obviamente este error no tiene sentido, porque la tabla de la clausula from existe.
Desde otros eventos de la tabla como "onposterror" y "afterpost" también falla... sin embargo desde fuera de los eventos de la tabla funciona perfectamente.

Hola podrias postear la sentencia completa por aqui?.

Saludos.

waly2k1 28-12-2007 22:41:54

Respuesta...
 
Si lo que quieres es saber cual es el codigo nuevo que se insertó
lo que puedes hacer es una consulta con @@IDENTITY, te paso un ejemplo

Código:

  qryLocate.SQL.Clear;
    qryLocate.SQL.Text := 'SELECT @@IDENTITY AS NewID';
    qryLocate.Active := true;
    iNewID := qryLocate.FieldByName( 'NewID' ).Value;

donde:
iNewID es una variable LongInt declarada anteriormente
NewID es un campo ficticio que me arroja el @@IDENTITY, bah usando un alias.

Esto lo ejecutas apenas hagas el insert en la tabla y no te preocupes por todos los eventos de ADO, es más si puedes evitarlos mejor aún.

Bueno espero te sirva esto y Exitos!!!

johnlobo 30-12-2007 01:36:51

Hola a todos,

Antes de nada gracias por contestar, intentaré daros algo más de información.

Cita:

Empezado por juanlaplata (Mensaje 254808)
y por que no puede ser tipo autoincremental ese campo?
si no date una vuelta por el evento OnCalcFields de TTable. Tal ves ahi puedas.

No puedo utilizar un autoincremental, porque en Access si cancelas la inserción pasa numero, y por tanto deja un hueco.

No entiendo muy bien tu sugerencia sobre el oncalcfields, porque lo que quiero es asegurarme justo antes de insertar el registro que el código en continuo.

John.

johnlobo 30-12-2007 01:48:07

Cita:

Empezado por enecumene (Mensaje 254831)
Hola podrias postear la sentencia completa por aqui?.

Saludos.

Bueno pues ahí va algo de código, aunque puede que no esté muy limpio...


Código:

Function nextArmario() : integer;
var
  aux : integer;
begin
  moduloDeDatosMdt.aux1Qry.Close;
  moduloDeDatosMdt.aux2Qry.SQL.Clear;
  moduloDedatosMdt.aux1Qry.SQL.Add('SELECT MAX(numArmario) FROM armarios');
  moduloDedatosMdt.aux1Qry.Open;
  aux:=moduloDedatosMdt.aux1Qry.Fields[0].AsInteger;
  moduloDeDatosMdt.aux1Qry.Close;
  nextArmario:=aux+1;
end;


procedure TmoduloDeDatosMdt.armariosTblBeforePost(DataSet: TDataSet);
var ultimoArmario : integer;
begin
ultimoArmario:=nextArmario();
if (armariosTbl.FieldByName('numArmario').Asinteger<>ultimoArmario) then
  begin
    armariosTbl.FieldValues['numArmario']:=ultimoArmario;
    showMessage('El número de armario ha cambiado durante la edición del mismo');
  end;
end;

El casque lo pega en la sentencia moduloDedatosMdt.aux1Qry.Open;" de la primera función, que se ejecuta justo antes de hacer un post, cuando la lanza el evento beforepost... he probado esta función fuera de los eventos y funciona perfectamente... :-(

Saludos,
John.

johnlobo 30-12-2007 01:51:15

Pues, es que el problema de los autoincrementales de access es que si se cancela la inserción corre núimero, así que aunque te agradezco tu propuesta, me temo que puedo usarla.

Estoy de acuerdo contigo sobre los eventos ADO, me temo que tienen algo que ver en este tema.

Saludos,
John.

Cita:

Empezado por waly2k1 (Mensaje 254944)
Si lo que quieres es saber cual es el codigo nuevo que se insertó
lo que puedes hacer es una consulta con @@IDENTITY, te paso un ejemplo

Código:

  qryLocate.SQL.Clear;
    qryLocate.SQL.Text := 'SELECT @@IDENTITY AS NewID';
    qryLocate.Active := true;
    iNewID := qryLocate.FieldByName( 'NewID' ).Value;

donde:
iNewID es una variable LongInt declarada anteriormente
NewID es un campo ficticio que me arroja el @@IDENTITY, bah usando un alias.

Esto lo ejecutas apenas hagas el insert en la tabla y no te preocupes por todos los eventos de ADO, es más si puedes evitarlos mejor aún.

Bueno espero te sirva esto y Exitos!!!


enecumene 02-01-2008 14:13:08

Código Delphi [-]
Function nextArmario() : integer;
begin
  moduloDeDatosMdt.aux1Qry.Close;
  moduloDeDatosMdt.aux2Qry.SQL.Clear;
  moduloDedatosMdt.aux1Qry.SQL.Add('SELECT MAX(numArmario)+1 FROM armarios');
  moduloDedatosMdt.aux1Qry.Open;
  aux:=moduloDedatosMdt.aux1Qry.Fields[0].AsString;
  moduloDeDatosMdt.aux1Qry.Close;
end;

Intenta con eso a ver que resulta.

Saludos.

waly2k1 02-01-2008 23:26:28

Autoincremental...
 
El problema en Access con los autoincrementales es que hasta que no
hagas el post en la tabla no puedes saber el valor asignado, y otra cosa: A no ser que tu aplicación sea monousuaria no te sirve el MAX() +1, por lo que no sabes cual es el valor real y la unica manera es seleccionando el valor @@IDENTITY. El problema no es de ADO, simplemente te digo que no te hagas problemas con los eventos porque son muchos y me pasó hace un tiempo que la sucesión de eventos no siempre respetaba un orden especifico, [code]supongo se corrigió ese bug, pero por las dudas descarté todo.

Por lo gral. cuando uso campos de tipo autoincremental lo hago cuando si o si inserto el registro y no cuando el usuario pueda cancelar la inserción.

Sino lo que uso es una tabla con un registro donde estan los últimos valores asignados y a un valor de esos le sumo uno, o sea simulo un Autoinc y llevo yo el control y no Access.

Te pego una función que la invoco cuando quiero insertar el registro

Código:

function TData.GetKey( sField:string ) :LongInt;
begin
    tblClaves.Requery;
    Result := tblClaves.FieldByName( sField ).Value + 1;
end;

Los campos son los nombres de las tablas, entonces paso como parámetro el nombre de la tabla y listo.

Algo así:
Código:

Tabla.FieldByName( 'ID_PROVEEDOR' ).Value:=TData.GetKey('PROVEEDOR');
Edito, me olvidé de decirte que una vez que insertes el registro actualices esa tablita

Código:

procedure TData.SetKey( sField:string );
begin
    tblClaves.Edit;
    tblClaves.FieldByName( sField ).Value := tblClaves.FieldByName( sField ).Value + 1;
    tblClaves.Post;
end;

Algo así:
Código:

TData.SetKey( 'PROVEEDOR');
Bueno espero te sirva de algo, exitos. Y no te compliques mucho.


La franja horaria es GMT +2. Ahora son las 13:36:07.

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