Newsgroup: it.comp.lang.visual-basic
Titolo: [?] VB e funzione NewID() di SQL7.

Ciao a tutti!
All'inserimento di un record in una tabella Access, il campo di tipo 'contatore'
della tabella riceve immediatamente il nuovo indice in seguito al metodo AddNew.
In SQL7, invece, come funziona?
Ecco il problema:
ho una tabella con un campo che chiamo ID di tipo 'uniqueidentifier' e che ha
come valore di default la funzione NewID().
Tutto funziona correttamente, in quanto, all'inserimento di un nuovo record, il
campo ID riceve un indice univoco, ma questo succede solo dopo l'utilizzo del
metodo Update.
A me serve sapere quale indice riceve il campo ID già dopo l'uso del metodo
AddNew, in quanto devo usare lo stesso indice per inserirlo in un'altra tabella.
Esempio:
    Tabella1.AddNew
    [...]
    Tabella2.AddNew
    Tabella2!ID = Tabella1!ID
    Tabella2.Update
    Tabella1.Update
Così chiaramente non funziona, in quanto Tabella!ID è ancora a Null quando
voglio leggerne il valore.
Qualcuno ha qualche idea? E' un progetto nuovo nuovo, quindi ho la possibilità
di modificare il tipo di dati delle tabelle senza nessun problema.
Grazie per l'attenzione!
Ciao!!!
--
Esteban
Replace 'nospam' with 'software' in the address for answer.
Hosted by 
www.seber.it


Se non ho interpretato male, ti riferisci a campi autoincrementali,
il cui valore viene generato univocamente dal motore del DB.
In SQL 7, tali campi vengono dichiarati nelle istruzioni di
Create Table con la specifica IDENTITY
Es
CREATE TABLE MiaTabella
(
	Field_Key      Integer IDENTITY(1, 2) NOT NULL,
	Field_A        Integer                NOT NULL,
	Field_B        Varchar (255)          NOT NULL,
	...
)
I valori dopo le parentesi, (1, 2) indicano il valore di inizio, 
(seed) in questo esempio 1, e l'incremento, 2.
Il valore di IDENTITY, quando un singolo record viene inserito,
viene registrato in una variabile di sistema, @@IDENTITY.
Per cui al termine della INSERT, fai una SELECT delle variabili
di sistema:
           SELECT @RowsAffected = @@ROWCOUNT, 
                  @LastIdentity = @@IDENTITY, 
                  @Exception    = @@Error
(@RowsAffected, @LastIdentity, @Exception sono tre variabili Integer
locali, user defined)
Nella seconda Insert usi il valore registrato in @LastIdentity.
Lo puoi anche esportare per metterlo a disposizione di altre 
Stored Procedure o per il codice client, dichiarandolo come parametro
OUTPUT.
Se non usi Stored Procedure ma gestisci tutto con gli oggetti, cerca tra
i metodi di ADO, 'Update Resyinc Property-Dynamic', costante
'AdResyncInserts'.
Guarda su MSDN.
HTH
Ciao 
	Adriano

 Esteban wrote:
[CUT]

E se mentre leggo @@IDENTITY, qualcun'altro ha inserito un nuovo row?
Grazie!!


> E se mentre leggo @@IDENTITY, qualcun'altro ha inserito un nuovo row?
Probabilmente non è una soluzione performante però dovrebbe funzionare.
aggiungi nuovo record in rs1
riempi i campi di rs1
updati rs1
se usi DAO allora rs1.edit
riempi i vari campi di rs2 compreso l'id
riempi i campi rimanenti di rs1 compresi eventuali riferimenti
updati rs2
updati rs1
anche se dal codice che hai scritto non ho capito perchè ti serviva chiudere
rs1 dopo rs2

 Hosted by 
www.seber.it
SQL Server simula thread isolati.
Ovvero ad ogni processo viene assegnato un ID ed uno spazio
di lavoro riservato e protetto.
Anche se due richieste agiscono sulla stessa tabella, ognuna 
delle due mantiene i propri valori delle variabili di sistema 
(@@ROWCOUNT, @@ERROR etc) indipendenti dall'altra.
Per operazioni di tipo SELECT, o di create per tabelle temporanee, 
o di comandi EXEC è così.
Comportamento differente invece per le operazioni di alterazione dei
dati, degli schemi, dei diagrammi che impattano sui risultati di
ogni thread attivo.
E quindi, durante le operazioni di INSERT, UPDATE, TRUNCATE, DELETE,
etc., la risorsa, in questo caso la Tabella, è locked e i vari processi 
sono accodati: in tal modo si garantisce l'unicità ed anche l'integrità 
di IDENTITY.
Per i processi queste code sono *quasi* trasparenti:
vedi però, ad esempio, che una delle origini dell'errore 'Timeout
expired'
è proprio questa, ed anche che non è possibile specificare HINTS quali 
NOLOCK durante le operazioni di INSERT/UPDATE.
Puoi essere certo che se più client accedono allo stesso
Server/Database,
comunque lavorano su spazi protetti, e le operazioni non sono mai
parallele quando richiedono operazioni concorrenti: vengono
comunque vagliate singolarmente.
Anche premendo contemporaneamente l'invio da due o più Workstation
ognuna riceverà il suo IDENTITY differente da ogni altro generato,
poichè le operazioni sono sequenziali, accodate in configurazione
LIFO.
È chiaro che operazioni che confliggono, del tipo DELETE, TRUNCATE
dopo INSERT o UPDATE sono fuori dal controllo del DB, che comunque
li esegue nell'ordine specificato, con le relative conseguenze.
Ed è per questo che si pone particolare attenzione, in fase di 
analisi, disegno e programmazione a prevenire situazioni simili,
tramite vincoli espliciti, GRANT mirati, e... Backup frequenti.
Ma tranquillo, non vengono generati @@IDENTITY uguali ad altri
nè il valore può cambiare subendo le conseguenze di INSERT esterne
al thread.
HTH
Ciao
	Adriano

 di lavoro riservato e protetto.
[CUT]
Beh, sono rimasto a bocca aperta!
Grazie Arj!!!!


 rs1 dopo rs2
Non serve affatto: ho chiuso i recordset come se fossero 'anniadiati':
rs1.AddNew
    rs2.AddNew
    rs2.Close
rs1.Close
Ciao e grazie lo stesso!!


 Hosted by 
www.seber.it
Prego, comunque una precisazione è d'obbligo;
Ho scritto:
...
poichè le operazioni sono sequenziali, accodate in configurazione
LIFO.
È chiaro ...
LIFO significa Last In First Out, in alcuni testi tradotti viene
identificato dal termine 'PILA'.
La coda è invece FIFO, First In First Out.
Mi scuso per l'imprecisione.
Ciao
	Adriano

 >


    Tabella1.Update
La sua preoccupazione è di ottenere univocamente l'ID di relazione
tra le due tabelle in modo che operazioni remote *concomitanti*,[ e 
sappiamo che questa è una astrazione, non saranno mai *sincrone* le
due operazioni, neppure se lanciate da un programma multithread 
sofisticato che invia le due richieste parallelamente nello stesso 
istante], abbiano ognuna una informazione di IDENTITY consistente
da trasportare da una tabella all'altra.
Salvando le variabili di sistema in aree locali, non si possono 
verificare disguidi; se la Workstation A esegue il processo, 
riceverà l'IDENTITY dalla prima insert e lo potrà propagare alla 
seconda anche se dalla Workstation B è partita analoga richiesta,
che è comunque in coda alla soddisfazione di A.
Questa dissertazione, oltre a focalizzare il punto su quanto 
effettivamente viene scritto nei tentativi di risposta, ha il 
pregio di darmi la possibilità di ringraziare Andrea per la
sua disponibilità anche via mail privata.
È importante che più voci sottolineino l'importanza di preservare
dati volatili quali i valori delle variabili di sistema.
Grazie 
	Adriano


Zio pal ti fara' un monumento per avere elevato il tono medio dell'italiano
(inteso come lingua) sul NG...
Ciaotutti,
*