Que considerar para migrar de Dbf a MySql?

797 views
Skip to first unread message

acmc

unread,
Oct 11, 2017, 5:57:19 PM10/11/17
to Comunidad de Visual Foxpro en Español
Hola Foxeros,

Les cuento que me solicitan migrar los datos de un sistema desarrollado con tablas dbf hacía MySql, yo ya he trabajado con MySql pero no directamente con Fox, las tablas nativas no tienen un campo ID unico, todas las tablas tienen su llave primaría de acuerdo al contenido y este no se repite, es decir, la tabla clientes tiene un campo c_cte  el cual es un consecutivo tipo caracter rellenado con ceros a la izquierda y así todas las demas tablas, lo que se me ocurrio para poderlas migrar ya a un esquema con su respectivo id númerico autoincrementable es agregar dicho campo a todas las tablas dbf y asignarles su consecutivo y así tal cual migrarlas, no se si así sea lo correcto o de que manera será ideal?

Salu2!!

Irwin Rodriguez

unread,
Oct 11, 2017, 6:20:45 PM10/11/17
to publice...@googlegroups.com
En base a lo que comentas entonces estas trabajando las validaciones en el cliente, esta logica tendria que cambiar en un ambiente cliente/servidor ya que de nada sirve mudarte a un SGBD cuando las validaciones de integridad las estas realizando en el cliente, lo ideal (pero no siempre es lo que se hace) es dejar que el mismo SGBD se encargue de mantenerla integridad de los datos y para esto se requiere de un buen diseño de tablas y demás.

Mi consejo ahora que estas comenzado es que diseñes bien tu base de datos y que le dejes la integridad al motor. Toca cambiar la filosofia de trabajo pero creeme, valdrá la pena, de lo contrario te estarías arrastrando los mismos errores del pasado.

Saludos...!
--
Irwin Rodríguez
Analista Programador

+593 0994903424
Latacunga - Ecuador

Carlos Miguel FARIAS

unread,
Oct 12, 2017, 8:49:51 AM10/12/17
to Grupo Fox, vfp-a-python
Respuesta OT
Como migrar de dbf a mysql via python (S.E.U O.)
# -*- encoding: utf-8 -*-

""" Ejemplo transferencia dbf a mysql con python
la librería que lee dbf no transfiere indices (no tiene sentido,
se crea en BD. No maneja campos de dbf que fueron agregados en VFP 9
ej. varchar, pero si maneja los memos

En algunos casos, habrá que adaptar la plantilla de inserción o incorporar
alguna conversión de datos. Python es más potente que vfp para tratamientos
de strings
"""

import mysql.connector
from dbfread import DBF

# Plantilla inserción. Asume que las columnas leidas están en el orden indicado
# en la plantilla
sql_para_insert = ("INSERT INTO una_tabla_mySQL "
"(una_columna, otra_columna, y_otra_mas, y_otra) "
"VALUES (%s, %s, %s, %s)")

conexion = mysql.connector.connect(user='spock', database='tuDB',
password='long life and prosperity')
cursor = conexion.cursor()

# reemplazar nombres carpetas por los apropiados.
# el metodo DBF del modulo dbfread crea el cursor y funciona como un iterador
# poniendo en cada vuelta del bucle una fila de la tabla de registro
for registro in DBF('c:\carpeta_sistema\carpeta_bd\cada_tabla.dbf'):
# cada registro tiene los datos de una fila de la tabla
# para acceder a los datos de una columna se usa registro['nombre_columna']
cursor.execute(sql_para_insert, registro)

conexion.commit() # Asegura datos con un commint expres
cursor.close() # cierra el cursor
conexion.close() # cierra conexión base datos
Sacando comentarios, 10 instrucciones de código.
Saludos: Miguel, La Pampa (RA)
Larga Vida y Prosperidad
Que la Fuerza los acompañe

Antonio Meza

unread,
Oct 12, 2017, 9:12:35 AM10/12/17
to Comunidad de Visual Foxpro en Español
Decirte como migrar de DBF a Mysql hay muchas formas, pero no tiene sentido solo migrar por migrar, para darte un buen consejo es necesario que comentes que fin le vas a dar a esa migración de datos, por ejemplo, usar X lenguaje Web, para seguir usando VFP pero ahora con Mysql, etc, etc.

saludos
Antonio Meza

Antonio Meza

unread,
Oct 12, 2017, 9:15:00 AM10/12/17
to Comunidad de Visual Foxpro en Español
Miguel una pregunta, has usado Django? y si lo has usado que tal te ha ido!!! es que estoy entre aprender Djando (phyton) o Laravel (php) para el backend 

saludos
Antonio Meza

Carlos Miguel FARIAS

unread,
Oct 12, 2017, 1:36:01 PM10/12/17
to Grupo Fox
Hola Antonio: Nosotros hicimos capacitación de Django, hice algunos sistemitas básicos, pero justo hubo cambio de autoridades y se compro software de SIU (Sistemas Información Ciudadana) en postgresql y php (framework Toba, también de SIU). Me asignaron un poco la parte de gestión de bd (algo así como DBA). Me aboque ha realizar un aplicativo de análisis de las bd en python (interfaz con TKinter) porque dichos aplicativos tienen bd complejas (+400 tablas cada uno) y no perfectamente normalizadas-documentadas.
Resumiendo lo que hace Django:
Vos definís la bd a nivel objetos, usando clases de django, configuras como se puede acceder al aplicativo generado (rutas válidas navegador). El django te genera todos los abcm (altas, bajas, consultas, modificaciones) básicos (inclusive html, css y js), inclusive las altas encadenadas, relaciones 1 a muchos y muchos a muchos. La integridad referencial te la maneja según lo declares en la bd (mediante las clases)
A eso le podes agregar reglas de negocios (en python).
O sea que lo básico te lo arma rápidamente (depende del hardware y el tamaño de la bd).
Si cambias el modelo de datos, django te hace la migración de la bd, y es reversible (o sea cambias el modelo, te hace la migración, pero podes "des-migrar, retrotrayendo al modelo previo, y más también pero ya no es tan simple).

Sugiero veas https://docs.djangoproject.com/es/1.11/ que muestra como se hace una aplicación django en español.

Ahora estoy trabajando con Flask que es un miniframework para web sobre python, tiene la ventaja de que es mucho más simple que django (la aplicación a desarrollar trabaja con tres tablas (es casi gestor de contenidos que maneja unos 200 registros en la tabla principal y pienso montarlo sobre SQLite, ya que no maneja transacciones).

Laravel no lo conozco, hace +5 años no trabajo con PHP.

te paso la definición del modelo en django de un sistema de turnos

from django.db import models
import datetime
import random

class Sector(models.Model):
    nombre = models.CharField(max_length=120)
    lapso = models.PositiveIntegerField('Lapso')

    def __str__(self):
        return "{0}".format(self.nombre)

    class Meta:
        verbose_name = "Sector"
        verbose_name_plural = "Sectores"

class Tramite(models.Model):
    nombre = models.CharField(max_length=120)
    requisitos = models.CharField(max_length=12288)

    def __str__(self):
        return "{0}".format(self.nombre)

    class Meta:
        verbose_name = "Tramite"
        verbose_name_plural = "Tramites"

class Turno(models.Model):

    ESTADO = ((1, 'Reservado'), (2, 'Confirmado'))

    sector = models.ForeignKey(Sector)
    dni = models.IntegerField()
    apellidos = models.CharField(max_length=35)
    nombres = models.CharField(max_length=30)
    correo = models.CharField('Correo Electrónico', max_length=120)
    fijo = models.CharField('Teléfono Fijo', max_length=50, blank=True, null=True)
    celular = models.CharField('Teléfono Celular', max_length=50)
    domicilio = models.CharField('Domicilio', max_length=80)
    nacimiento = models.DateField('Fecha Nacimiento')
    tramite = models.ForeignKey(Tramite)
    fecha_turno = models.DateField('Fecha Turno')
    hora_turno = models.CharField(max_length=5)
    numero_turno = models.PositiveIntegerField('N° Turno', default=0)
    token = models.CharField(max_length=5, default='')
    reserva = models.DateField()
    confirma = models.DateField()
    estado = models.PositiveIntegerField(choices=ESTADO, default=1)
    recordatorio = models.DateTimeField()

    def __str__(self):
        return "{0} | {1}, {2}".format(self.dni, self.apellidos, self.nombres)

    class Meta:
        verbose_name = "Turno"
        verbose_name_plural = "Turnos"

    def numerodeturno(self, fecha):
        ''' Número de Turno para una Fecha '''
        numero = Turno.objects.filter(fecha_turno=fecha).count()
        if numero == None:
            return 1
        else:
            return numero + 1

    def clavesecreta(self, longitud):
        """ Genera cadena aleatorias """
        caracteres = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
        return ''.join(random.choice(caracteres) for _ in range(longitud))

    def save(self):
        self.sector = 1     # Fijo la Dirección de Tránsito por ahora.
        self.numero_turno = self.numerodeturno(datetime.datetime.today())
        self.token = self.clavesecreta(5)
        super().save()

aca va lo que tienes definir para crear todos los abcm

from django.contrib import admin
from web.models import *

admin.site.register(Sector)
admin.site.register(Tramite)

class TurnoAdmin(admin.ModelAdmin):
    fields = ('dni', 'apellidos', 'nombres', 'correo', 'fijo', 'celular', 'domicilio', 'nacimiento',
               'tramite', 'fecha_turno', 'hora_turno')

admin.site.register(Turno, TurnoAdmin)

esta es la parte de las vistas

from django.http import HttpResponse
from django.template import RequestContext, loader
from django.conf import settings

def index(request):
    t = loader.get_template('index.html')
    c = RequestContext(request)
    return HttpResponse(t.render(c))

Y acá el html del index

{% extends "base.html" %}
{% load static %}

{% block contenido %}
<nav class="navbar navbar-static-top marginBottom-0" role="navigation">
    <div class="navbar-header">
      <a class="navbar-brand" href="#" target="_blank">Municipalidad de Santa Rosa</a>
    </div>

    <nav class="navbar navbar-default" role="navigation">
      <!-- El logotipo y el icono que despliega el menú se agrupan
           para mostrarlos mejor en los dispositivos móviles -->
      <div class="navbar-header">
        <button type="button" class="navbar-toggle" data-toggle="collapse"
                data-target=".navbar-ex1-collapse">
          <span class="sr-only">Desplegar navegación</span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </button>
        <a class="navbar-brand" href="#">Logotipo</a>
      </div>

      <!-- Agrupar los enlaces de navegación, los formularios y cualquier
           otro elemento que se pueda ocultar al minimizar la barra -->
      <div class="collapse navbar-collapse navbar-ex1-collapse">
        <ul class="nav navbar-nav">
          <li class="active"><a href="#">Enlace #1</a></li>
          <li><a href="#">Enlace #2</a></li>
          <li class="dropdown">
            <a href="#" class="dropdown-toggle" data-toggle="dropdown">
              Menú #1 <b class="caret"></b>
            </a>
            <ul class="dropdown-menu">
              <li><a href="#">Acción #1</a></li>
              <li><a href="#">Acción #2</a></li>
              <li><a href="#">Acción #3</a></li>
              <li class="divider"></li>
              <li><a href="#">Acción #4</a></li>
              <li class="divider"></li>
              <li><a href="#">Acción #5</a></li>
            </ul>
          </li>
        </ul>

        <form class="navbar-form navbar-left" role="search">
          <div class="form-group">
            <input type="text" class="form-control" placeholder="Buscar">
          </div>
          <button type="submit" class="btn btn-default">Enviar</button>
        </form>

        <ul class="nav navbar-nav navbar-right">
          <li><a href="#">Enlace #3</a></li>
          <li class="dropdown">
            <a href="#" class="dropdown-toggle" data-toggle="dropdown">
              Menú #2 <b class="caret"></b>
            </a>
            <ul class="dropdown-menu">
              <li><a href="#">Acción #1</a></li>
              <li><a href="#">Acción #2</a></li>
              <li><a href="#">Acción #3</a></li>
              <li class="divider"></li>
              <li><a href="#">Acción #4</a></li>
            </ul>
          </li>
        </ul>
      </div>
    </nav>

</nav>
{% endblock %}

Falta algunos archivos más que no puedo pasar porque estarían mostrando contraseñas y otras configuraciones que por razones obvias no se pueden mostrar.

Pero te da una idea de que toda la parafernalia de abcm lo armas con relativamente codificación.

Conclusión, si vas a realizar un sistema complejo, Django es aplicable, para aplicaciones muy chicas, la curva de aprendizaje inicial es alta, no por lo dificil, si no por lo abundante. (como levantar un tarro de dulce de leche con una grúa portuaria)

Saludos: Miguel

Angel Perez

unread,
Oct 12, 2017, 1:50:33 PM10/12/17
to publice...@googlegroups.com
Haber, el cliente tiene muuuucha información, catalogo de clientes, proveedores, etc, etc, no esta en discusión en que se tiene que hacer un nuevo diseño de la base de datos, pero creo que no se puede descartar la información que se tiene en los DBF, me explico, por ejemplo el catalogo de clientes en el DBF esta bien estructurado, es algo simple al cual sería agregarle otros campos para otros procesos que se van a requerir, el único detalle que veo para poderlo migrar a MySQL es que no tiene un campo ID para la integridad de la tabla, por eso mencionaba yo poderle crear ese campo en los DBF para poder validar posteriormente que el ID tanto del DBF y MySQL sean el mismo para el mismo codigo de Cliente, obvio el ID lo asignaría al momento de ingresarlo a MySQL y lo actualizaría en el DBF y con eso asegurarme que en los demas archivos como por ejemplo facturas asignarle el ID que le corresponda al cliente me explico.

Antonio sobre lo que preguntas sobre que fin le voy a dar te comento que la idea es desarrollar un control de piso con PHP y MySql, que basicamente es captura de datos por cada línea de producción vía tablets y terminales android y seguir manejando VF para los procesos que ya tienen, pero requiero tener ciertos datos cargados en MySql para la parte de PHP

Salu2

Antonio Meza

unread,
Oct 12, 2017, 1:57:54 PM10/12/17
to Comunidad de Visual Foxpro en Español
Gracias por la explicación tan detallada, he leído en infinidad de webs que Django es superior y para proyectos grandes, y este es un proyecto grande, es todo un sistema Administrativo-Contable-Operativo Aduanal!!!!

Actualmente trabajo con VFP y Mysql, por lo que la parte Web seria con Django!! o crear un Api en Django y así poder usar React-js o Vue.js para el lado del cliente.

De todas formas lo poco que he usado Python su sintaxis es super fácil e intuitiva y no decir de las funciones que tiene tan enriquecidas para manejo de array, string, etc.

Definitivamente me voy a poner a estudiar Python y Django!!! y si te animas te invito al proyecto!!!! jejeje

saludos
Antonio Meza

Antonio Meza

unread,
Oct 12, 2017, 2:52:41 PM10/12/17
to Comunidad de Visual Foxpro en Español
Me confundiste un poco, a que le llamas migrar? porque una vez que pases los datos de los DBF a Mysql te debes ir olvidando de los DBF, ahora si quieres hacer una combinación de poder seguir con los dbf he ir alimentando Mysql te va a doler lo mas profundo de tu ser jajajajajaja es BROMA!!!! no te va a doler tan a fondo!!! pero seria doble trabajo y por lo tanto doble problema!!! lo mejor es migrar y olvidarte de los DBF!!

En cuanto a migrar de DBF a Mysql supongamos que tienes tu tabla Clientes.dbf así

Clientes.dbf
clave char(10)
nombre
etc etc etc

y lo vas a migrar a una nueva tabla Clientes en Mysql

Clientes
id int (autoincrementable)
clave char(10)
nombre
etc etc

En primera olvídate del valor ID de Mysql el te lo va a asignar al momento que empieces a subir los registros en la migración, vamos a simular que los subes usando FoxyDb jajajajajaj

* Abres DBF
     Use Clientes as ClientesDbf
* Abres Clientes en Mysql
    oDb.Query("Select * from Clientes","clientes")
    * Nota: Nunca usar Select * es solo demostrativo)
    * Hacer el cursor editable
    oDb.CursorEdit("clientes")
* Recorremos la tabla DBF y vamos insertando los registros
select clientesDbf
     scan
          insert into clientes (clave, nombre, etc, etc) values (clientesDbf.clave, clientesDbf.nombre, etc, etc)
     endscan
* Ya que termino mandas a guardar al servidor Mysql
     odb.Update("clientes")
* Finalizas la transacción
     odb.Commit()

Ya tienes tu catalogo de Clientes en Mysql con un X valor en ID que no tienes la mas mínima idea que valor es y no te interesa jajajaja así que se lo vamos a preguntar sencillamente por el valor CLAVE!!!! 

Por lo tanto ahora vas a subir las facturas y no sabes que valor ID y IDCliente le tocara pero no es problema porque el campo clave tiene la respuesta a tus pecados!!! digo a tus dudas jajaja

facturas.dbf
clave_clien char(10)
folio
fecha
total
etc etc etc

y lo vas a migrar a una nueva tabla Facturas en Mysql

facturas
id int (autoincrementable)
idcliente int
folio
fecha
total
etc etc etc


* Abres DBF
     Use Facturas as FacturasDbf
* Abres Facturas en Mysql
    oDb.Query("Select * from facturas","facturas")
    * Nota: Nunca usar Select * es solo demostrativo)
    * Hacer el cursor editable
    oDb.CursorEdit("facturas")
* Vas a necesitar Clientes de Mysql pero no todos los campos
    oDb.Sql("Select id, clave", "clientes")
* Recorremos la tabla DBF y vamos insertando los registros en facturas
select facturasDbf
     scan
          insert into facturas (folio, fecha, etc, etc) values (facturasDbf.folio, facturasDbf.fecha, etc, etc)
          * Buscar la clave del cliente de facturasDBF en Clientes de Mysql
          Select Clientes
          locate for clientes.clave = facturasDbf.clave_clien
          replace facturas.idcliente with clientes.id in facturas
     endscan
* Ya que termino mandas a guardar al servidor Mysql
     odb.Update("facturas")
* Finalizas la transacción
     odb.Commit()

Y listo tienes tu tabla Clientes en Mysql con X valor en ID, y que pormedio del Campo CLAVE puedes saber que valor tiene y lo pasaste al campo Facturas.idcliente en Mysql y así lo harás con las demás tablas. OJO!!! ya no ocupas tener en tu tabla Facturas el campo CLAVE este fue sustituido por IDCLIENTE pues ya olvídate de las claves carácter para relacionar tablas en Mysql jajajaja

espero te de una idea!!

saludos
Antonio Meza

Angel Perez

unread,
Oct 12, 2017, 3:12:18 PM10/12/17
to publice...@googlegroups.com
Gracias Antonio por tu explicacación, 
Es así como lo había visualizado, solo quería que me lo corroborará alguien de experiencia como tu ;), en cuanto a los DBF's coincido contigo, lo ideal sería dejarlos de usar, pero una cosa es lo que uno quiere y otra la que el cliente te pide, lo principal en este caso es desarrollar el control de piso y ya despues que vean las ventajas poder migrar todo lo demas.. y si la idea es trabajar con FoxyDb la parte de VF con MySql para lo que ya tienen y lo nuevo con PHP y MySql

Salu2!!
Reply all
Reply to author
Forward
0 new messages