Newsgroup: it.comp.www.asp
Titolo: AddNew: come recuperate l'ID?

Come posso farmi dire quale valore è stato attribuito automaticamente al
campo ID (contatore in Access, identity in SQL)?
Ho una tabella "Prova" con due campi aggiungo un nuovo record.
Ecco i due campi:
1) ID identity,
2) Nome varchar.
Come posso farmi dire quale valore è stato attribuito automaticamente al
campo ID, se non chiudendo e riaprendo il recordset?
Per ovviare all'inconvendiente io chiudo il recordset e poi lo riapro con
questa stringa sql:
select Max(ID) as NuovoID from Prova;
Nel Firld NuovoID c'è il mio valore. Ma per ottenerlo sono costretto a
chiudere e riaprore il RecordSet.
Grazie e chi mi vorrà rispondere
D. Colombo

Se usi connection.execute("INSERT INTO...") non devi chiudere il recorset
(anzi, non ti serve proprio per fare la insert), ma solo aprirlo subito
dopo, il problema pero' e' che non hai la certezza che l'ID che ricevi sia
il tuo usando Max(ID), perche' se due utenti inseriscono contemporaneamente
potresti leggere l'ID sbagliato.
La cosa migliore sarebbe fare una query usando tutti i campi che hai
inserito per rileggere lo stesso record.
Oppure non usare un contatore ma 'generare' l'ID in base ad altri parametri
(in questo modo lo calcoli direttamente).
Davide

"begin tran qry1; set nocount on; insert into prova (nome) values ('pippo');
set nocount off; select max(id) as nuovoid from prova; commit tran qry1";
In questo modo inserisci e riprendi l'ID in una sola "botta" (senza il
problema che qualcun altro nel frattempo inserisca un altro campo).

 2) Nome varchar.
Su access se usi l'addnew sul recordset, appena dopo l'esecuzione
dell'addnew il campo ID del record creato e' accessibile e contiene proprio
l'id che ti serve, devi solo andarlo a leggere.
Questo almeno che non si sveglino e cambino l'implementazione (ado 2.5?) e
se sei su access 97.
In 'full sql' direi che la risposta di Cristiano e' una di quelle da
conservare.
Ciao, Fabio Zed Zamparelli

Questa me la conservo! Grazie.
Ciao, Fabio Zed Zamparelli
Cristiano Larghi <C.La...@Micronix.it> wrote in message
10n1np8$f8c$1...@fe2.cs.interbusiness.it...


conservare.
no, non direi: se ad esempio si esegue una compattazione, l'identity
ritornato non è detto che sia il max(field), xchè una compattazione
elimina i record precedentemente cancellati, renendo quindi
disponibile il completamento della numerazione; inoltre, non è sempre
possibile racchiudere in una transazione quel processo.
il metodo più usato con sqlsrv è l'uso della variabile d'ambiente
@identity, che contiene l'ultimo valore identity impostato dal motore.
Il problema (cercate su msdn, c'è un articolo sul knowledge base ma
non ricordo quale) è che con ado non si fa in tempo a leggerlo, xchè
dopo il metodo .update la connessione s'è chiusa; 
il metodo allora comunemente usato tra vb-ado-sqlsrv è quello di farsi
una stored procedure sul database, che non fa altro che inserire con
una insert i dati, e restituire la variabile con l'identity con un bel
RETURN @IDENTITY.
--------
MATRO
YahooMessenger:matrello, Icq:matro
RealPopup, the freeware winpopup replacer
http://members.tripod.com/Matro/realpopup.html

Interessante ma non ho capito, se esegui la query "in un solo colpo" quali
sono i rischi di non avere l'ID corretto?
(Chiedo perché uso questa sintassi da un po' in Intranet e Internet senza
problemi).
Cosa intendi per compattazione in sql?
Ci sono anche altri metodi per cambiare la numerazione o forzarne i valori,
ma nel mio esempio il risultato ottenuto dovrebbe essere corretto; se cambia
subito dopo anche la tua soluzione (tra l'altro ottima) non serve.
Grazie 100.000


sono i rischi di non avere l'ID corretto?
si certo, fai bene a chiederlo, visto l'argomento spinoso! come fai tu
non ci sono problemi, nel tuo ambiente e nelle tue problematiche.
mi spiego meglio: occhio che in questo thread confondiamo i nostri
espedienti nei nostri ambienti con altri.
esempi concreti:
1) Cristiano si basa sul fatto che max(identity) corrisponde
all'ultimo identity inserito. Questo mi sembra che in sqlsrv almeno
nella versione 7 sia giusto, ma NON è una regola generale: in Access,
ad esempio, basta fare un compact del database (a questo mi riferivo)
ed ecco che l'assegnazione interna del valore di identity "riempie" i
buchi di record precedentemente marchiati come cancellati e
fisicamente eliminati dalla compattazione. In SQLSrv7, l'identity può
"ricominciare" se il contatore raggiunge il bound superiore (dipende
dal tipo di dato assegnato al campo identity e dal fattore di
incremento)
2) sempre Cristiano, imposta un contesto transazionale che non è detto
sia possibile in tutti gli ambienti: ad esempio la mia transazione
potrebbe essere del tipo lock-ottimistico su diverso codice in
esecuzione, cosicchè se qualcuno mi inserisce un record da un altro
task mentre io stò eseguendo il mio codice (lungo...), ecco che non è
detto che l'identity generato sia lo stesso che mi risulta dal
max(identity). (spero di essere stato chiaro)
Ciò non toglie, come dicevo prima, che la soluzione di Cristiano vada
benissimo nella SUA realtà.
3) La soluzione di Fabio, come lui stesso dice, si adatta solo
all'ambiente Access: io stesso la usavo e l'ho dovuta poi modificare
(dopo aver perso diverso tempo a capire che cavolo c'era che non
andava!) quando il db aperto era sqlsrv e non Access.
Purtroppo non c'è un metodo generico per prelevare l'identity da una
fonte dati qualunque. Io normalmente utilizzo una stored procedure su
sqlsrv7, che inserisce il record e ritorna l'identity (@@IDENTITY),
anche perchè i tempi di inserimento sono inferiori rispetto alla
controparte ADO (usate il profiler e vedrete come gli insert da ADO
sono visti rispetto ad una storedproc). Comunque anche altri metodi
vanno benissimo, purchè, per essere comunque compatibili, si basino
sull'utilizzo della variabile di ambiente @@IDENTITY.
Su MSDN, leggete questi simpatici articoli:
PRB: ADO Not Returning @@IDENTITY Value After AddNew
ID: Q195224 
INFO: Identity (AutoIncrement) Columns in ADO or RDS
ID: Q195910 


Chiarissimo, grazie.
Avevo dato per scontato che si parlasse di sql7, non credo che begin tran...
funzioni con access (ma in realtà non ho mai provato).

funzioni con access (ma in realtà non ho mai provato).
si, access le transazioni le supporta!
BeginTrans
CommitTrans
Rollback
:-)


Veramente prezioso Matro, grazie e spero di continuare a leggerti spesso.
Ciao, Fabio Zed Zamparelli