En MySQL y creo que en todas las BD el motor lo hace solo si utilizas START TRANSACTION......COMMIT/ROLLBACK y en medio las operaciones sobre las tablas.
THISFORM.VERIFICADOR=<tabla>.campo_timestamp
SQL="SELECT campo_timestamp FROM <tabla> ID = <id_actual_modificado>"thisform.ClaseDatos.SQL(cSQL,"TEMP_VERIF")IF thisform.ClaseDatos.sql_Records>0 * VERIFICAR QUE PUEDO GUARDAR IF THISFORM.VERIFICADOR <> TEMP_VERIF.campo_timestamp thisform.ClaseDatos.CursorClose("TEMP_VERIF") =MESSAGEBOX("El Registro ha sido actualizado por otro Usuario. Se van a Deshacer los cambios y Refrecar la ventana "+; "actual, para verificar los datos actualizados.",0,"NO SE GUARDARÁ LA INFORMACIÓN - CONCURRENCIA") thisform.clasedatos.Disconnect() thisform.procesoeliminar(.t.) && llamo al deshacer * REFRESCAR TABLAS THISFORM.Refrescar_Tablas() && Refresco los cursores con los datos nuevos RETURN .F. ENDIFENDIFthisform.ClaseDatos.CursorClose("TEMP_VERIF")
......... A partir de aquí ya guarda....
IF thisform.clasedatos.Changes() && SI HAY ALGUN CAMBIO lHAYERROR=.F. IF thisform.clasedatos.Update(<tabla>).... etc....
LOCAL cSQL,cIDMADRE,cFECHA_HORA
Thisform.ClaseDatos.Begin(3)
cIDMADRE=THISFORM.TABLAMADRE+".ID"Thisform.id_madre = 0Thisform.id_madre = &cIDMADREcFECHA_HORA=4Transform(TTOC(DATETIME(),1), "@R 9999-99-99 99:99:99")
cSQL ="INSERT INTO CONCURRENCIA (ID_USUARIO,TERMINALRED,TABLA,ID_REGISTRO,FECHA) "+;"VALUES ("+ALLTRIM(STR(OAPP.USUARIOACTUAL_ID,20))+",'"+OAPP.TERMINALRED+"','"+THISFORM.TABLAMADRE+"',"+ALLTRIM(STR(thisform.id_madre,20))+",'"+cFECHA_HORA+"')"
IF !Thisform.ClaseDatos.SQL(cSQL) Thisform.ClaseDatos.RollBack() if Thisform.ClaseDatos.Error_Odbc=1062 =MESSAGEBOX("El Registro está siendo Modificado por otro usuario. Intentelo más tarde.",0+48,"ATENCIÓN") ELSE =MESSAGEBOX("Error al insertar registro en tabla Concurrencia, Intentelo más tarde...") ENDIF RETURN .F.ELSE Thisform.ClaseDatos.Save() RETURN .T.ENDIF