EL buho Preguntó ================ Buenas foro. No sé si habrá salido ya este tema por aquí en el foro (He buscado quizá mal, y no lo he visto...ultimamente no encuentro casi nada, será la edad...) Como ya sabrán (algunos de ustedes) yo no me dedico a la programacion profesionalmente, sino por aficion y puro entretenimiento desde mi casa. Digo esto, por que yo jamás he utilizado grandes cantidades de datos en tablas de Access y/o en otros entornos y por lo tanto carezco de experiencia al respecto. Dicho esto, algunos de vds que tienen experencia al respecto en grandes volumenes de información... ¿Cual se ejecuta mas rapido en consultas de acción? Docmd.runsql Sql ó Currentdb.Execute Sql Gracias por sus comentarios. Les leeré, si les hay, después del paseito que me voy a dar por las afueras de Valladolid, aprovechando el tiempo, aún soportable que tenemos y de paso anulo un poco el efecto dañino del tabaco. RESPUESTAS ========== Aca dice que execute es 200% más efectivo que runsql... (test 13) http://www.microsoft.com/officedev/articles/movs101.htm Sashka ------------------- Según la documentación, la acción Docmd.RunSQL permite no usar una transacción. Si ejecutas una transacción y si la actualización/inserción/borrado de algún registro falla, no se modifica ningún registro. Si no usas transacción obtendrías una mejora de velocidad (según la documentación), pero podría ocurrir que unos registros se vean afectados por la sentencia y otros no. Personalmente lo de no usar transacciones no me deja muy tranquilo. Sería necesario evaluar qué problemas provocaría que unos registros se vean afectados por la sentencia y otros no. Por ej Docmd.RunSQL "Delete From Clientes Where Clientes.Saldo = 0 ..." Si hay 5000 clientes con saldo 0 y por el motivo X (reglas de validación, bloqueos, ...) hay un error borrando el 2501, resulta que los primeros 2500 ya me los he cepillado. Si usas transacción no creo que haya muchas diferencias. No lo sé porque siempre uso el método execute de un objeto database. Para mí, la principal diferencia entre la acción RunSql y el método Execute es que cada acción RunSql es una transacción independiente. No puedo ejecutar varias en una sola transacción. Con el método execute sí puedo. Ricardo Hernadez --------------------------------------------------- Rircardo, muchas gracias, ha sido muy instructivo. No obstante quisiera comentarte lo que he creido entender y el concepto que tengo al respecto en estos momentos, para que en su caso me corrijas o confirmes lo que digo. Por defecto Docmd.RunSql Sql utiliza transacciones (Valor True del seundo parametro), lo que implica entonces mas lentitud, si bien más seguridad. Supongo que internamente en esta accion «Docmd.RunSql», está implicito el proceso Begitrans(Antes de variar/eliminar el primer registro) posteriormente Committrans para confirmar en caso de no haber detectado error y si hubiera detectado error, hacer un Rollback.(Recalco lo de IMPLICTO, no transparente al usuario, es decir, se ejecuta de forma interna) Es decir, si no utilizo el segundo parametro de Docmd.RunSql en realidad estoy untilizando una transaccion, lo que implica que «internamente» access utiliza conceptualmente, los metodos Begi-Comm y/o en caso de error Roll. Lo que implica mayor lentitud, pues supongo que segun se va desarrollandola transaccion, Access debe almacenar en memoria o fichero temporal (Esto ya no lo sé) lo que va realizando: Si al final ha sido correcto, lo vuelca, si no ha sido correcto no lo vuelca y lo queda como estaba. Por eso te decia que simula literalmente el proceso completo Begitrans Committrans (Si correcto) ó RollBack(Si ha habido errores) ¿Correcto? El metodo Execute ya lo tengo menos claro. En efecto es mas rapido,lo que implica que no permite transacciones implictas..¿O si? (Digo implictas, no reales con los metodos Begitrans etc) Es que al final de tu texto no he entendido bien lo que dices con «No puedo ejecutar varias en una sola transacción. Con el método execute sí puedo.» EL concepto que tenía del método execute es que si le desarrollamos de esta forma: Db.Execute Sql, Dbfailonerror en realidad estariamos en el mismo caso que con Docmd.RunSql Sql, True ¿Correcto? Es que leo en la ayuda: «En un espacio de trabajo Microsoft Jet, si proporciona una instrucción SQL sintácticamente correcta y tiene los permisos apropiados, el método Execute no falla - aunque no se pueda modificar o eliminar ni una sola línea. Por tanto, utilice siempre la opción dbFailOnError cuando use el método Execute para realizar una consulta de actualización o eliminación. Esta opción genera un error interceptable y anula todos los cambios, si cualquiera de los registros afectados está bloqueado y no se pueden actualizar o eliminar.» Si bien, tambien leo posteriormente (Lo que implica que posiblemente Db.Execute Sql, Dbfailonerror sea igual de lento que DoCmd.RunSql), decía, leo posteriormente: «Para obtener un mejor rendimiento, en espacio de trabajo Microsoft Jet, especialmente en un entorno multiusuario, anide el método Execute en una transacción. Utilice el método BeginTrans en el objeto Workspace activo y a continuación utilice el método Execute y complete la transacción utilizando el método CommitTrans en el Workspace. Esto evita cambios en el disco y libera los bloqueos que se puedan haber establecido mientras se ejecutaba la consulta.» En cualquier caso y visto los visto, dada la velocidad actual de los actuales ordenadores y la simplicidad de la sintaxis Docmd.Runsql Sql, para volumnes de informacion *no muy elevados*, ésta sea la mejor, simplemente abogando por la seguridad e integridad de los datos..¿Correcto? Muy agradecido, de verdad, por tu tiempo y amabilidad. -- Saludos desde Valladolid Francisco Javier García Aguado --------------------------------------------------------------------------------- RICARDO HERNANDEZ: El método execute permite hacer lo mismo usando o no "DbFailOnError" Lo que te decía con lo de varias sentencias se ve mejor con un ejemplo. El campo Cuentas.Saldo tiene una regla de validación: Saldo >= 0 Private Sub RunSqlTest() Dim wks As DAO.Workspace On Error GoTo 0 Set wks = DBEngine.Workspaces(0) wks.BeginTrans DoCmd.RunSQL "Update Cuentas Set Saldo = Saldo + 500 Where NumCuenta = '1234'", True DoCmd.RunSQL "Update Cuentas Set Saldo = Saldo - 500 Where NumCuenta = '4321'", True wks.Rollback End Sub De entrada, no quiero que me salgan mensajitos en pantalla (aunque podríamos quitarlos con el docmd.SetWarnings). Si la segunda sentencia falla, da lo mismo lo que conteste cuando me salga el mensaje de error y tb da lo mismo que ejecute o no el rollback, el titular de la 1234 tiene 500 de regalo y el de la 4321 se queda como estaba. Si por el contrario, lo hago con el método execute Private Sub ExecuteTest() Dim bResult As Boolean Dim wks As DAO.Workspace Dim dbs As DAO.Database On Error GoTo HandleErr Set wks = DBEngine.Workspaces(0) Set dbs = wks.Databases(CurrentDb.Name) wks.BeginTrans dbs.Execute "Update Cuentas Set Saldo = Saldo + 500 Where NumCuenta = '1234'", dbFailOnError dbs.Execute "Update Cuentas Set Saldo = Saldo - 500 Where NumCuenta = '4321'", dbFailOnError bResult = True ExitHere: On Error Resume Next If bResult Then wks.CommitTrans Else wks.Rollback End If Exit Sub HandleErr: MsgBox Err.Description, vbExclamation bResult = False Resume ExitHere Resume End Sub A diferencia de la acción, el método execute no muestra mensajes de confirmación. Los mensajes de confirmación están muy bien para el uso interactivo, pero no para un programa que a lo mejor lanza muchas sentencias. Por otra parte, este segundo ejemplo es consistente. Si hago el commit le quito a uno y le pongo al otro. Si hago el rollback, ambos se quedan como estaban Esa es la verdadera diferencia que veo entre ambas posibilidades. -------------------------------------------------------------------------------------- Ricardo, gracias de nuevo. No obstante, si bien con Execute si he visto ejemplos que dicho metodo Execute queda anidado dentro de BeginTrans-CommitTrans etc (Es decir dentro de una transaccion...mismamente el que acabas de poner tu) nunca he visto un RunSql anidado de esa forma. Es más, yo creo que no surge ningun efecto. Ah...claro, estoy pensando, que efectivamente ESO ERA PRECISAMENTE lo que me querías comentar !!!!..joer estoy medio tonto..... Ahora si he entendido lo que comentabas en el ultimo parrafo de tu anterior mensaje...ahora si :-) No obstante, insisto, para una consulta masiva, por ejemplo de elimincacion, Docmd.RunSql lleva implicta una transaccion.... Está claro, comprendo el porque utilizas, para ejemplos como el que has puesto, el metodo Execute. Requieres seguridad de que los saldos se transpasen de uno a otro de forma correcta (O Simplemente el transpaso no se haga, si algo ha fallado..) Bueno...creo que por hoy ya basta, que aca es muy tarde. -- Saludos desde Valladolid Francisco Javier García Aguado ------------------------------------------------------------------------------ Paco, yo también me he hecho esta pregunta varias veces y estoy de acuerdo con lo que se ha dicho hasta ahora. Creo que hay otra diferencia. El método Execute es sincrono lo que quiere decir que no sigue a la siguiente instrucción hasta que no se acabado el Execute. En cambio RunSQL es asíncrono, lanza un proceso independiente de Access y se sigue con la siguiente instrucción sin saber si se ha acabado o no la ejecución de la sentencia SQL. Esto puede llevar a resultados distintos cuando se ejecutan varias consultas consecutivas. Al tener que lanzar un proceso independiente RunSQL es más lento porque lanza un programa que después ejecuta la consulta. En cambio Execute se hace directamente, sin intermediarios. En resumen creo que lo mejor es usar Execute pero hay razones prácticas que hacen útil usar RunSQL. Yo solo lo uso para ejecutar consultas definidas que usan parametros, normalmente referencias a controles de formularios, que Execute no puede encontrar. Saludos, Valentín Playá Serra Sonotronic S.A. Madrid, España FIN DEL HILO ¿Queda Claro? Gracias a todos los participantes