PDA

Ver la Versión Completa : Obtener ClaveMaestra del registro insertado.


jplj
18-05-2004, 23:09:13
Tengo dos tablas en una DB de Access 97.

Campos Tabla1:
Id: Autonumérico y Clave Maestra.
Numero: Numérico.
Nombre: Texto.
Campos Tabla2:
Id: Autonumérico y Clave Maestra.
Numero: Numérico


He creado una relación de uno a varios entre los campos Tabla1-Id y Tabla2-Numero en la que se exige integridad referencial.

Con ADO estoy intentando insertar un registro en Tabla1 y simultánemente insertar en Tabla2 una serie de registros vinculados al registro que inserto en Tabla1.


var
i, j, k : Integer;
begin

ADOTable1.Append;
ADOTable1Numero.AsInteger:= i;
ADOTable1Nombre.AsString:= 'Número : ' +IntToStr(i);
ADOTable1.Post;
// Ahora asignar a k el valor del campo Id del registro insertado en Tabla1
for j:= 0 to 15 do
begin
ADOTable2.Append;
ADOTable2Numero.AsInteger:= k;
end;
ADOTable2.Post;


El problema lo tengo para obtener el valor que se le ha asignado al campo ID al insertar el registro en la Tabla1, teniendo en cuenta que simultáneeamente otras apliaciones pueden realizar lo mismo.

¿Cómo podría obtenerlo?

Gracias de antemano.

__cadetill
19-05-2004, 00:17:20
mmmm, no he trabajado con ADO, pero creo que hay algún error en ese código que has puesto

si Id es autonumérico.... ¿por qué le asignas un valor?
si Id es autonumérico.... después del Post puedes consultar su valor, ¿no?

Podría quedar algo así


var
i, j : Integer;
begin
ADOTable1.Append;
ADOTable1Nombre.AsString:= 'Número : ' +IntToStr(i);
ADOTable1.Post;
i := ADOTable1Numero.AsInteger;

// Ahora asignar a k el valor del campo Id del registro insertado en Tabla1
for j:= 0 to 15 do
begin
ADOTable2.Append;
ADOTable2Numero.AsInteger:= i;
ADOTable2.Post;
end;


Repito, no he trabajado con ADO, así que no se como funciona exactamente el tema de refrescos y tal en este motor

sanxpue
19-05-2004, 00:42:14
Mi amigo cadetill

si Id es autonumérico.... ¿por qué le asignas un valor?
¡¡Nunca le da un valor al Autonumerico ahora si viste mal

Y bueno la cosa es que este tema se ha tratado muchas veces

Funciona bien si no lo van a usar varias instancias con un solo Last


var
i, j, k : Integer;
begin
ADOTable1.Append;
ADOTable1Numero.AsInteger:= i;
ADOTable1Nombre.AsString:= 'Número : ' +IntToStr(i);
ADOTable1.Post;

ADOTable1.Last;
K := ADOtable1ID.AsInteger;

// Ahora asignar a k el valor del campo Id del registro insertado en Tabla1
for j:= 0 to 15 do
Begin
beginADOTable2.Append;
ADOTable2Numero.AsInteger:= k;
end;
ADOTable2.Post;
End;


Ahora si lo van a usar varios no se si TADOTable tenga la opcion de exclusive
:eek:

__cadetill
19-05-2004, 00:49:38
Mi amigo cadetill

si Id es autonumérico.... ¿por qué le asignas un valor?
¡¡Nunca le da un valor al Autonumerico ahora si viste mal

:o :o :o no se en que estaría pensado!!! Tienes razón!!! :D

Pero bueno, sigo pensando que, justo despues del Post (que no hace falta hacer un Last ya que te encuentras en el registro en cuestión) tienes el valor del ID accediendo al campo de la tabla tal y como muestras (o yo quería mostrar). El cursor no se mueve del registro mientras no realices otro Append (Insert), Next, Last, Prior o First

PD: si es que ya es hora de irse a la cama!!!! :D

jachguate
19-05-2004, 01:00:04
Bueno... el cursor no se mueve de registro en el dataset, pero me parece (salvo que ADO trabaje sensiblemente diferente al BDE en esta parte) que el registro no estará "actualizado". Es decir, no mostrará el valor asignado al campo en la base de datos.

En el caso del BDE, lo que ocurre es que éste motor se basa en la llave primaria para hacer un refresh del registro inmediatamente después de insertarlo, de manera que cualquier asignación hecha del lado del servidor, via triggers por ejemplo, se refleje en el cliente.

El talón de aquiles de este mecanismo, por supuesto, son las asignaciones del lado del servidor a algún campo que forma parte de la clave primaria. Esto es simplemente imposible con el BDE, y dado que se basa en el "minimo común" de todas las BD's, supongo que no idearon la forma de realizarlo.

Conozco algunos motores de base de datos que implementan un mecanismo para prevenir esto, pero varia de motor en motor... creo que el único que no tiene un mecanismo para identificar de nuevo al registro es interbase/firebird, aunque habría que consultar a los expertos...

ADO funciona de otra forma?

Hasta luego.

;)

__cadetill
19-05-2004, 01:09:58
Bueno... el cursor no se mueve de registro en el dataset, pero me parece (salvo que ADO trabaje sensiblemente diferente al BDE en esta parte) que el registro no estará "actualizado". Es decir, no mostrará el valor asignado al campo en la base de datos.
Por este preciso motivo decía que no sabía como ADO se comportaba con el refresco de los datos. Si te da el valor de forma inmediata, no hay problema, sino.... ya lo dejo en manos de gente que conozca bien este motor

jplj
19-05-2004, 21:10:26
El código que he puesto es un ejemplo, sólo eso.

En cuanto a recuperar el valor del campo Tabla1-Id tras el Post, lo intenté en: la línea de código tras el post, en el evento afterpost de la tabla y en el evento SetText y Validate del campo con el mismo resultado 0.

Otra forma que se me ha ocurrido es utilizar una sentencia SQL, aunque no sé si es factible crear una sentencia que insert un registro y devuelva la fila insertada.

Si teneis cualquier sugerencia os la agradecería.

Saludos
Juan P.

jachguate
19-05-2004, 21:32:26
A mi saber no es posible recuperar la fila seleccionada. Access no tiene algun mecanismo tipo generadores que te permita asignar el código desde el cliente??

roman
19-05-2004, 21:39:51
Vamos a ver, que no estoy entendiendo lo qe dice jachguate:

Si tengo una tabla en paradox con un campo autonumérico e inserto un registro, inmediatamente depués del post puedo obtener el valor que se asignó al campo.

:confused:

jachguate
19-05-2004, 22:41:34
Bueno... ya sabes que Paradox es un caso especial del BDE, al igual que los DBF's, y no se si algun otro. Lo que yo digo es aplicable para bases de datos SQL (al menos desde el punto de vista del propio BDE, pues Access sigue cayendo en esta categoria, segun mi criterio).

Hasta luego.

;)

roman
19-05-2004, 22:54:55
Pues el problema es raro. Acabo de hacer la prueba con ADO con Access y es como suponía cadetill, el valor del autonumérico lo obtengo inmediatamente después del Post. De hecho esto lo había ya señalado sanxpue desde un principio, si bien él agrega el uso de Last.

jplj
20-05-2004, 00:18:33
Bien por lo que dice Roman algo debo estar haciendo mal.

Acabo de hacer nuevamente la prueba con el código siguiente:


procedure TForm1.Button5Click(Sender: TObject);
var
k: Real;
begin
ADOTable1.Append;
ADOTable1Numero.AsInteger:= 1000;
ADOTable1Nombre.AsString:= 'Número : ' +IntToStr(1000);
ADOTable1.Post;
k:= ADOTable1Id.AsFloat;
MessageDlg('Id registro insertado: ' + FloatToStr(k), mtInformation,
mbOk], 0);
end;


Y el valor de de k es siempre cero.

La cadena de conexión es:


Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin;
Data Source=E:\Documents and Settings\casa\Mis
Documentos\Trabajo\Estudio_ADO\bd2.mdb;
Mode=Share Deny None;Extended Properties="";
Jet OLEDB:System database="";Jet OLEDB:Registry Path="";
Jet OLEDB:Database Password="";Jet OLEDB:Engine Type=4;
Jet OLEDB:Database Locking Mode=0;Jet OLEDB:Global Partial Bulk Ops=2;
Jet OLEDB:Global Bulk Transactions=1;
Jet OLEDB:New Database Password="";
Jet OLEDB:Create System Database=False;
Jet OLEDB:Encrypt Database=False;
Jet OLEDB:Don't Copy Locale on Compact=False;
Jet OLEDB:Compact Without Replica Repair=False;
Jet OLEDB:SFP=False


Utilizo Acces 97 y Delphi 7.

¿dónde está el error?