Update y replace

1,170 views
Skip to first unread message

Jorge Galván Pérez

unread,
Oct 29, 2015, 10:56:24 AM10/29/15
to Comunidad de Visual Foxpro en Español
Como se dice en mi país tengo un arroz con mando, creo que estoy mesclando las coas.



Tengo un sistema elaborado en VFP 9 con manejo de tablas nativas, quiero cambiar a que se maneje con una base de datos (mysql, sqlserver, etc).

El sistema utiliza append blank y replace.

La primera fase es cambiar todos los append y replace con los insert y update con las tablas nativas luego la segunda fase seria el cambio a pasar los datos a la base de datos.


Trabajo con buffers y vistas actualizables, las vistas actualizables es donde se emplea los append y replace.

Mis inquietudes son:

1.- Tengo que cambiar ese append y replace por insert, update????
2.- veo que la instrucción update tiene el where que me condiciona al registro para que este solo sea actualizado, pero esta instrucción (update) recorre todo mi vista actualizable condicionada al where???
si esto es cierto cosa que creo como hago si tengo un proceso donde debo recorrer registro por registo y actualizar ese mismo registro y asi sucesivamente hasta que sea fin de archivo.
¿¿como se hace para que se actualize ese registro sin que recorra toda la vista?? y consecutivamente???

Muchas Gracias, de antemano..

Antonio Meza

unread,
Oct 29, 2015, 11:43:19 AM10/29/15
to Comunidad de Visual Foxpro en Español
Prueba con FoxyDb

Si estas usando vistas actualizables, entonces lo que tienes que hacer es obtener los cursores de esas vistas pero con FoxyDb,

FoxyDb usa buffering, por lo que ya no vas a necesitar aplicarlo manual al cursor si no usando funciones para ello.

saludos
Antonio Meza

Carlos Miguel FARIAS

unread,
Oct 29, 2015, 1:47:03 PM10/29/15
to Grupo Fox
El append y el insert agregan un registro por vez. La diferencia es que el append lo agrega en blanco y luego debes aplicar replace para completar los datos.
En el insert metes registros con datos en un paso.
El replace actualiza el registro actual, salvo que tenga una clausula FOR/WHILE. El update actualiza todos los registros que cumplen con la condición del Where.
El procedimiento que instrumentaría sería el siguiente.
Con un SELECT, crear un cursor con todos los registros que estarían en condiciones de actualizar (importante recuperar los datos con la clave primaria). crear un cursor vacio con lugar para la clave primaria y los datos a actualizar.
Luego con un SCAN sobre el cursor (que es local) efectuar las modificaciones del caso y agregando los registros al cursor auxiliar (el creado vacio) y no, modificando el el cursor original.
Luego, recorrer el segundo cursor (que tiene datos modificados y primaria) y con la primaria, hacer un update sobre los registros correspondientes.
Puedes, si quieres, omitir el cursor auxiliar, y modificar sobre el cursor origen, o ir disparando los updates directamente a medida que lees y cambias el cursor original.
La forma de instrumentar es variada, dado que por ejemplo, si procesas todo el cursor y creas un auxiliar, podes retrotraer cambios bajo alguna circunstancia. O puede que tengas que procesar todo, para obtener un valor total, que debe luego meterse en la BD.
Si, siempre ten en cuenta que SQL procesa contra conjuntos de registros, y para acotar los involucrados debes usar la clausula WHERE (lo más seguro es incluir la clausula primaria).
Esto es totalmente al reves de REPLACE, donde si no pones nada, actualiza el registro actual, y solo procesa varios (conjunto) si hay un FOR o WHILE que extienda la selección.
Saludos: Miguel, La Pampa (RA)

Larga Vida y Prosperidad
Que la Fuerza los acompañe hasta pensar en SQL

Jorge Galván Pérez

unread,
Oct 29, 2015, 2:03:43 PM10/29/15
to Comunidad de Visual Foxpro en Español
Gracias Miguel por aclarar mis dudas.

Te comento que tengo una tabla dbf y creo un cursor actualizable.
En este cursor agrego registros, modifico y puedo eliminar registros todo lo hago con update, insert y delete.

Una vez que he incluido, modificado y si acaso eliminado registros antes de hacer el tableupdate, tengo que actualizar un campo que esta en el cursor y preguntar si esta vacio entonces tengo que grabarle un numero que se va incrementando a medida que encuentre registros cuyo campo este en blanco.

Con un siclo recorriendo el cursor y preguntando si el campo esta vacio y utilizo el replace y luego incremento el valor para el próximo registro que tenga el campo vacio, lo hace perfecto. mi problema es que no se como hacerlo con el update.

Podras darme una mano.

Gracias.

Carlos Miguel FARIAS

unread,
Oct 29, 2015, 2:11:22 PM10/29/15
to Grupo Fox
Sobre que tipo de tablas? DBFs?

Jorge Galván Pérez

unread,
Oct 29, 2015, 2:20:37 PM10/29/15
to Comunidad de Visual Foxpro en Español
Si utilizo tablas nativas DBF y creo un cursor actualizable sobre esa tabla.


CREATE SQL VIEW


DBSETPROP('WorkRetenciones', 'View', 'Tables','Retenciones')

DBSETPROP....

CURSORSETPROP('Buffering',5, 'WorkRetenciones')

Carlos Miguel FARIAS

unread,
Oct 29, 2015, 2:29:49 PM10/29/15
to Grupo Fox
Sobre DBFs, en pensamiento rápido, posiblemente perfeccionable.

LOCAL lbFaltan AS BOOLEAN, liCuentas AS INTEGER
lbFaltan = .T.
liCuenta = 0

WHILE lbFaltan
   SELECT TOP 1 clavePrimaria FROM tablaActualizo WHERE EMPTY(campoEnCuestion) INTO CURSOR temporal
   IF _TALLY = 1
      lcClave = temporal.clavePrimaria
      liCuenta = liCuenta + 1
      UPDATE tablaActualizo SET campoDondeCuento = liCuenta WHERE clavePrimaria = lcClave
   ELSE
      lbFaltan = .F.
   ENDIF
ENDDO

o reemplazo el WHILE por algo mas compacto

SELECT clavePrimaria FROM tablaActualizo WHERE EMPTY(campoEnCuestion) INTO CURSOR temporal
SELECT temporal
SCAN
   lcClave = temporal.clavePrimaria
   liCuentas = liCuentas + 1
   UPDATE tablaActualizo SET campoDondeCuento = liCuentas WHERE clavePrimaria = lcClave
ENDSCAN

o habría que probar

LOCAL liCuenta AS INTEGER
liCuenta = 0
UPDATE tablaActualizo SET campoDondeCuento = Contador(@liCuenta) WHERE EMPTY(campoEnCuestion)

FUNCTION Contador(piCuenta)  && Parámetro local, recibido por referencia
   piCuenta = piCuenta + 1
   RETURN piCuenta
ENDFUNC

Saludos: Miguel, La Pampa (RA)

Larga Vida y Prosperidad
Que la Fuerza los acompañe

Jorge Galván Pérez

unread,
Oct 29, 2015, 2:50:34 PM10/29/15
to Comunidad de Visual Foxpro en Español
Miguel sin animos de nada solo de aprender y si no estoy equivocado.


supongamos que en ese cursor tengo 1000 registros

entonces el la rutina:
WHILE lbFaltan
   SELECT TOP 1 clavePrimaria FROM tablaActualizo WHERE EMPTY(campoEnCuestion) INTO CURSOR temporal
   IF _TALLY = 1
      lcClave = temporal.clavePrimaria
      liCuenta = liCuenta + 1
      UPDATE tablaActualizo SET campoDondeCuento = liCuenta WHERE clavePrimaria = lcClave
   ELSE
      lbFaltan = .F.
   ENDIF
ENDDO

Primero recorre la tabla y extrae a los registros cuyo campoEnCuestion este vacio (vamos a suponer que todos los registros con el campoEnCuestio este vacio serian los mismos 1000 registros)
luego hace el update y este recorre todos los registros buscando la condición WHERE clavePrimaria = lcClave
luego hace de nuevo la extracion de registros cuyo campoEnCuestion este vacio (ahora deverian ser 999 registros)
y asi sucesivamente????

esa es la manera que trabajaría el select y el update?


Pregunto para saber como funciona y aclarar mis dudas.

Gracias por estar ayudándome.

Carlos Miguel FARIAS

unread,
Oct 29, 2015, 6:08:20 PM10/29/15
to Grupo Fox
En el select, trae solo el primer registro que cumple la condición (SELECT TOP 1...), lo trae, actualiza el campo de control, creo que omiti que rellenara el campo que está en blanco, para que no lo vuelva a traer.
Las otras opciones trabajan distinto, primero trae todos los registros a actualizar, y luego actualiza uno por uno desde el cursor temporal.
El último, en una sola instrucción, actualiza toda la tabla, pero la función (no lo probé) la estaría llamando registro por registro, por lo que como el valor se pasa por referencia, se va incrementando. Esto último no lo probé, pero si funciona, sería lo más compacto de los tres.
Saludos: Miguel, La Pampa (RA)

Larga Vida y Prosperidad
Que la Fuerza los acompañe

Víctor Hugo Espínola Domínguez

unread,
Oct 29, 2015, 7:22:50 PM10/29/15
to publice...@googlegroups.com
Hola Jorge

>Trabajo con buffers y vistas actualizables, las vistas actualizables es donde se emplea los append y replace.

Si migras a un SGBD externo te conviene olvidarte de las vistas remotas, debido a que ellas deben estar alojadas en una base de datos nativa (DBC) y por lo tanto estará en una carpeta compartida con los problemas de seguridad y concurrencia que implican.
Una alternativa es generar el cursor mediante mediante SQLEXEC y convertirlo a "Cursor acutalizable", adjunto el procedimiento.

>Mis inquietudes son:

>1.- Tengo que cambiar ese append y replace por insert, update????
Como trabajarás sobre el cursor actualizable es cuestión de gusto que uses APPEND BLANK o INSERT INTO y REPLACE o UPDATE, para actualizar la tabla en el servidor UPDATE

>2.- veo que la instrucción update tiene el where que me condiciona al registro para que este solo sea actualizado, pero esta instrucción
>(update) recorre todo mi vista actualizable condicionada al where???
>si esto es cierto cosa que creo como hago si tengo un proceso donde debo recorrer registro por registo y actualizar ese mismo registro y >asi sucesivamente hasta que sea fin de archivo.
>¿¿como se hace para que se actualize ese registro sin que recorra toda la vista?? y consecutivamente???

UPDATE tanto en VFP como en los SGBD utilizan los índices para optimizar el proceso.


Saludos,
Víctor.
Lambaré - Paraguay.

cursoractualizable.txt

Jorge Galván Pérez

unread,
Nov 3, 2015, 8:25:44 PM11/3/15
to Comunidad de Visual Foxpro en Español
Hola miguel

de las opciones que me distes utilize esta

 

SELECT RIFCV FROM WORKRETENCIONES WHERE EMPTY(NROCOMPROB) order BY RIFCV GROUP BY rifCV INTO CURSOR WorkTemp

SELECT WorkTemp

SCAN

lnNro = INCREMENTA_NUMERO()

UPDATE WORKRETENCIONES SET NROCOMPROB = lnNro  WHERE RIFCV = WorkTemp.RIFCV AND EMPTY(NROCOMPROB)

ENDSCAN


Lo que hace o pretendo hacer es que tengo la Vista Actualizable que se llama WORKRETENCIONES y creo un cursor con los registros según el campo RIFCV

luego se incrementa el numero con la función incrementar_numero() y hace el update para todos los registro que sean igual al campo RIFCV y este el campo NROCOMPROB vacio.


El problema que tengo es que como es un vista actualizable y estoy en modo de edición agregando, modificando y eliminando registros y estoy aun no lo actualizo a la tabla dbf, cuando hace el

select solo trae los registros que estaban grabados, los que se an ingresado, modificados o eliminados estas modificaciones no están en el nuevo cursor WorkTemp.



La idea es que hacer las modificaciones o inclusiones luego grabar el numero consecutivo y después es hacer el TABLEUPDATE(1, .f., "WORKRETENCIONES")








Antonio Meza

unread,
Nov 3, 2015, 9:52:35 PM11/3/15
to Comunidad de Visual Foxpro en Español
Cual es tu necesidad real de incrementar un numero en una tabla de mysql?

Por lo poco que entiendo, tienes la información en DBF y estas migrando a Mysql, es correcto?

Como te comente con FoxyDb puedes realizar todo lo que necesites con Mysql de forma muy sencilla y rápida.

Si explicas con mas detalle que necesitas hacer te puedo ayudar usando FoxyDb.

saludos
Antonio Meza

Jorge Galván Pérez

unread,
Nov 4, 2015, 8:54:16 AM11/4/15
to Comunidad de Visual Foxpro en Español
Son tablas nativas dbf y utilizo vistas actualizables

Saludos.

Jorge Galván Pérez

unread,
Nov 4, 2015, 11:12:24 AM11/4/15
to Comunidad de Visual Foxpro en Español
El problema que tengo es que como es un vista actualizable y estoy en modo de edición agregando, modificando y eliminando registros y estos aun no lo actualizo a la tabla dbf,
necesito hacer un select que me traiga ciertos registros este solo trae los registros que estaban grabados, los que se an ingresado, modificados o eliminados estas modificaciones

Carlos Miguel FARIAS

unread,
Nov 4, 2015, 6:17:49 PM11/4/15
to Grupo Fox
Si mandas datos a buffering e indagas la tabla origen, por lógica lo del buffer no será recuperado, porque no está en disco.
No veo sentido de actuar a través de vistas contra dbfs, ya que de por si meten una carga adicional para procesar.
Una vista se justifica en un entorno de bd con multiples aplicaciones compartidas, donde algunas aplicaciones no debe acceder a datos privativos de otras.
Por ejemplo, un sistema de liquidación de haberes no debería estar accediendo a datos sensitivos de RRHH y viceversa, RRHH no puede/debe entrar en liquidaciones.
En empresas relativamente grandes, ambas áreas, trabajan separadas por razones de control por oposición.
Saludos: Miguel, La Pampa (RA)

Larga Vida y Prosperidad
Que la Fuerza los acompañe, hasta la Vista, Baby
Reply all
Reply to author
Forward
0 new messages