21/8/11

Migrar o manipular una base de datos de MySQL a Access


Cuando era estudiante y llevaba materias de bases de datos, el ver las tablas como tablas hacía complicado el trabajo, sin embargo cuando uno veía las tablas como conjuntos, era sencillo pensar en uniones, intersecciones, diferencias y otras operaciones de conjuntos.

Nunca se me hizo difícil la materia de bases de datos, al contrario se me hacía un poco aburrida y sin grandes retos, a pesar que me dejaban tareas de realizar consultas complicadas, siempre encontraba la manera de realizarlas (no siempre de la mejor manera pero salían).

En el aspecto profesional tuve alguna vez un trabajo donde mi labor era administrar una base de datos, no era la gran cosa, la base de datos estaba en Access pero estaba creciendo y la iban a migrar a Oracle (eso creo ya no estuve para esa migración).

Durante ese lapso de tiempo me acostumbre a realizar consultas en Access, seguramente muchos lo odian, pero en mi caso era lo único que tenía. Actualmente estoy trabajando con una base de datos que se encuentra en MySQL pero las consultas ya no las puedo hacer directamente en SQL porque no tengo la práctica que tenía cuando era estudiante, además no tengo el tiempo para ponerme a escribir sentencias SQL, decidí utilizar un manejador de bases de datos para hacer las consultas de forma visual. Después de buscar y descargar algunos programas me di cuenta que ninguno cumplía mis expectativas porque yo estaba esperando que fueran igual que Access al cual más o menos recordaba.

Debo decir que mi licencia de Office incluye  Access 2007 y para dejar de buscar pues mejor comienzo a utilizarlo, pero ahora el reto era ¿cómo pasar mis tablas a Access para poder consultarlas? A continuación describo los pasos a seguir para resolver el problema.


Pasar tablas de MySQL a Access para poder realizar consultas de forma gráfica

Fue necesario descargar un driver para hacer la conexión entre MySQL y Access, este driver es para ODBC y se encuentra en la siguiente dirección:


Se debe seleccionar ODBC Driver for MySQL (conector/ODBC), después de descargar hay que instalar.

Después de instalado debemos abrir el panel de control y dirigirnos a Herramientas administrativas, ahí existe la opción “Orígenes de datos ODBC” el cual debemos abrir.



En la pestaña de DSN de usuario agregamos un Origen de datos (suena feo, pero así es la traducción literal que le dio Microsoft). Seleccionamos el driver o controlador MySQL que está casi al final de la lista y le decimos finalizar.

En la ventana de configuración debemos llenar los siguientes campos:
Data Source Name: Debemos poner el nombre como conoceremos el conector a la base de datos.
Descripción: Colocamos un breve texto que describa la base de datos.
TCCP/IP Server: Aquí va la dirección IP en la cual se aloja la base de datos.
Port: Colocamos un puerto disponible por el cual nos podemos conectar, por default coloca el puerto 3306, pero puedes poner otro.
User: Nombre de usuario de la base de datos.
Password: Contraseña de usuario que escribimos arriba.
Database: El nombre de la base de datos con la que haremos la conexión.


Probamos nuestra conexión con el botón Test, si hubiera un error puedes probar con otro puerto o verificar el nombre de usuario y contraseña de la base de datos.

Hasta aquí está configurado el conector para la base de datos, ahora es necesario abrir Access 2007 para poder consultarla.


Dentro de Access 2007 en la parte superior hay una pestaña con el título Datos externos que contiene un botón con la leyenda Bases de datos ODBC que al presionarlo nos muestra una ventana con 2 opciones:
Importar el origen de datos  en una nueva tabla de la base de datos actual o vincular al origen de datos creando una tabla vinculada. La primer opción crea las tablas en Access en caso de no existir, sin embargo los cambios en la Base de datos origen (en nuestro caso MySQL) no se reflejarán en las tablas creadas en Access, mientras que la segunda opción se crea el vínculo de tal manera que cualquier cambio en Access a las tablas, se reflejará en la base de datos original (en nuestro caso MySQL) y viceversa.

Una vez seleccionada la opción que más nos convenga le decimos Aceptar y nos mostrará una ventana para seleccionar el conector que creamos con anterioridad, le damos clic en Origen de datos de equipo y lo seleccionamos.

Ya para terminar seleccionamos las tablas que deseamos importar a Access y le decimos Aceptar

14/8/11

Diferencia entre Facebook y Twitter

Soy nuevo en Facebook, abrí mi cuenta a principios del 2011, no porque no me haya enterado de la red social, simplemente porque hace años abrí cuentas en Hi5 y MySpace con resultados grises, solo un par de amigos tenían cuenta ahí y no había mucho que ver por lo que perdí el interés.

Cuando lei sobre Facebook pensé que se trataba más de lo mismo e ignoré todos los comentarios y evite pensar más en esa nueva "moda" de los adolescentes.

Sin embargo cuando lei sobre Twitter si me llamó la atención que hubiera personas que les interesara la vida de otros que no conocían, lo entendía de Facebook ya que agregabas amigos, pero en Twitter agregabas a personas que talvez nunca habías visto ni verás en persona. Abrí mi cuenta en Twitter sólo por curiosidad, comencé agregando a los amigos de la universidad que sabía no podian faltar, después cuando no encontré más amigos comencé a buscar a personas con los mismos interesese que yo; busqué gamers, desarrolladores de videojuegos, aficionados de la IA, malhumorados como yo que siempre tienen la palabra Usabilidad en mente y así fuí creando una lista de personas que cualquier comentario era más interesante que el de mis amigos que hablaban de su última visita al cine y su vida en el tráfico de la ciudad.

La primer semana con Twitter únicamente la revisaba cada tercer día, después fui agregando más personas y eliminando otras más, poco a poco mi lista creció al grado de no poder leer todo lo que se escribia. Actualmente tengo una lista de aproximadamente 100 personas, es poco, lo sé, pero alguna vez seguí a tanta gente que no me daba tiempo de leer todo y entraba en crisis de pensar que me había perdido de algo bueno.

Conocí primero Twitter, por lo cual cuando conocí Facebook se me hizo lento, poco dinámico y esa es una de las diferencias entre Facebook y Twitter.

Otra diferencia es que mientras en Facebook intercambias información con familiares y amigos, en Twitter intercambias información con el público en general, por lo tanto la información es diferente, a tus amigos les compartes lo que hiciste el fin de semana, la película que viste, la música que estás escuchando, las fotos que tomaste en la fiesta, es decir, información que le interesa a tus conocidos. En twitter las cosas son diferentes, compartes información para las personas que tienen los mismo intereses que tu, hablas de esas cosas que te gustan y puedes compartir con gente que también le gusta pero no necesariamente la conoces en persona, puedes hablar de videojuegos, de política, de medicina, de cocina, de autos, de lo que es interesante para ti y no tan facil lo encuentras con tus amigos y familiares.

Imagínense llegar un día a la casa de su abuelita y decirle: "-Oye Abue, sabías que acaban de liberar una nueva versión del Kernel de Linux?" o ves a tu sobrino de 13 años y le dices: "-¿Y tu que opinas de la reforma energética?" lo mismo aplica si en la calle le dices a un desconocido: "Mira la foto que me tomé en el espejo del baño" o "Estoy emocionado por una noticia que acabo de recibir, luego les daré detalles."

Es común encontrar amigos del Facebook compartiendo información de su área que sólo el entiende (a veces ni él pero quiere dar una imagen de culto) así como también es común encontrar personas de Twitter que escriben todo lo que hacen en el día como si fuera tan importante para nosotros saber que se está tomando un café y dónde lo está haciendo.

Por lo tanto no le pidas a un desconocido que te agregue al Facebook porque no eres parte de su círculo de amigos o familiares, y tampoco esperes que tu sobrino escriba cosas de tu interés en Twitter.

Google+ espera ser la combinación de ambas redes sociales, pero en este momento sólo tengo a 5 personas en mis círculos, no sé como se va a mover en un futuro.

3/8/11

Ejemplo en AJAX

Ejemplo en AJAX

Realizaremos un primer ejercicio para intentar entender AJAX. Este primer ejercicio contendrá dos combos, un combo que carga los Estados de la República Mexicana y dependiendo del Estado que seleccionemos, nos actualiza un segundo combo que contiene los Municipios de dicho Estado.

Lo primero que debemos hacer es crear en la base de datos 2 tablas, una de Estados y una de Municipios.

La tabla de Estados tendrá el siguiente formato:

Id_estado | nombre_estado
1 Aguascalientes
2 Baja California
3 Baja California Sur
4 Campeche
5 Chiapas
.
.
.
El SQL para la creación de la tabla como su contenido es el siguiente:
CREATE TABLE IF NOT EXISTS `estados` (
  `idestado` int(11) NOT NULL,
  `estado` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`idestado`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `estados` (`idestado`, `estado`) VALUES
(1, 'Aguascalientes'),
(2, 'Baja California'),
(3, 'Baja California Sur'),
(4, 'Campeche'),
(5, 'Chiapas'),
(6, 'Chihuahua'),
(7, 'Coahuila'),
(8, 'Colima'),
(9, 'Distrito Federal'),
(10, 'Durango'),
(11, 'Estado de México'),
(12, 'Guanajuato'),
(13, 'Guerrero'),
(14, 'Hidalgo'),
(15, 'Jalisco'),
(16, 'Michoacán'),
(17, 'Morelos'),
(18, 'Nayarit'),
(19, 'Nuevo León'),
(20, 'Oaxaca'),
(21, 'Puebla'),
(22, 'Querétaro'),
(23, 'Quintana Roo'),
(24, 'San Luis Potosí'),
(25, 'Sinaloa'),
(26, 'Sonora'),
(27, 'Tabasco'),
(28, 'Tamaulipas'),
(29, 'Tlaxcala'),
(30, 'Veracruz'),
(31, 'Yucatán'),
(32, 'Zacatecas');
CREATE TABLE IF NOT EXISTS `municipios` (
  `id_municipio` int(11) NOT NULL AUTO_INCREMENT,
  `nombre_municipio` varchar(100) NOT NULL,
  `estado` int(11) NOT NULL COMMENT 'Id de tabla estados',
  PRIMARY KEY (`id_municipio`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=2578 ;

Falta agregar la lista de municipios lo cual es una lista tan larga que será mejor subirla en un archivo y la pongo al final del post.

Lo siguiente será crear la página que contendrá los combos donde se muestren los datos para lo cual creamos un archivo con el nombre comboBox.php y copiamos el siguiente texto:
";
	$listaEdos = devuelveEdos();
	if (count($listaEdos) > 0) {
		for ($i=0;$i".$renglon['estado']."";
		}
	}else{
		echo "";
	}
	echo "
";
}
?>




Ejemplo de combo



		

		

		 
		 



Estoy dando por hecho que sabemos lo básico de PHP, para no entrar en detalles.

La instrucción
include_once 'edosYMun.php';
Nos indica que utilizaremos el archivo edosYMun.php y que se incluirá solamente una vez, más adelante detallaré su contenido.
function cargaEstados()
Indica que crearemos una función que permite cargar los Estados de la República en un combo.
echo " 
que permite la creación de un combo. La propiedad name y id nos va a permitir identificar el combo de cualquier otro.
El evento onChange manda a llamar a una rutina en caso de que el combo cambie de valor, es decir después de seleccionar algún Estado se lanza el evento y ejecuta una función en javascript que tiene por nombre
muestraMunicipios() 
y recibe como parámetro el evento seleccionado.

Aquí es donde entra JavaScript a escena, ya que una vez seleccionado o modificado alguna opción del combo (en este caso un Estado) manda a llamar un evento en JavaScript pasándole el id de la opción seleccionada.
$listaEdos = devuelveEdos();
Manda a llamar a una function declarada en edosYMun.php que devuelve un array con todos los Estados contenido en la tabla Estados.
if (count($listaEdos) > 0) {
En caso de que haya regresado un array con datos, entonces los muestra, si el array está vacío devuelve como el mensaje de que no fue posible conectarse con la Base de datos.
for ($i=0;$i".$renglon['estado']."";
		}
Recorre el arreglo y por cada estado crea una opción del combo, en este caso asigna como id de cada opción el idestado y como el texto de la opción el valor de la columna que tiene el nombre del Estado.

Esta línea es importante para definir el conjunto de caracteres que se van a utilizar en la página, en este caso decimos que dentro del conjunto de caracteres se incluyen acentos y por lo tanto los nombres de los Estados se van a mostrar correctamente.


Le indica a la página que utilizaremos funciones contenidas en el archivo cargaMunicipios.js
		

Carga el combo creado en la función cargaEstados(), por lo tanto no es necesario escribir aquí el código para su creación.

Crea un combo con el nombre municipios y pone como opción un solo valor con el texto: Selecciona una opción.

Este último combo se actualizará dependiendo del Estado seleccionado, es importante el nombre del combo porque con este podremos indicarle al archivo cargaMunicipios.js que cargue contenido en el combo “municipios”.

Ahora el siguiente paso es crear el archivo edosYMun.php que nos servirá para obtener los nombres de los Estados de la Base de datos, así como también obtener los municipios de un Estado en particular.

Para la la creación del archivo edosYMun.php debemos copiar el siguiente código:

".$renglon['nombre_municipio'];
	}
}

  function Conectar()
  {
    if (!($link=mysql_connect("localhost","root",""))){
      echo "Error conectando a la base de datos.";
      exit();
    }
    if (!mysql_select_db("concursos",$link))
    {
      echo "Error seleccionando la base de datos.";
      exit();
    }
    return $link;
  }

	function devuelveEdos()
	{
	 $link=Conectar();
     $arreglo = mysql_query("SELECT * FROM estados",$link);
	 $todo = array();
		while ($fila = mysql_fetch_array($arreglo, MYSQL_ASSOC)){
			$todo[] = $fila;
		}
		return $todo;
	}
Para analizar este archivo vamos a ir ahora de abajo hacia arriba porque es la forma como están declaradas las funciones y seguramente quedará mas claro.
	
function devuelveEdos()
	{
	 $link=Conectar();
     $arreglo = mysql_query("SELECT * FROM estados",$link);
	 $todo = array();
		while ($fila = mysql_fetch_array($arreglo, MYSQL_ASSOC)){
			$todo[] = $fila;
		}
		return $todo;
	}

Como el nombre lo indica, hace una conexión con la base de datos y ejecuta la consulta que selecciona todos los campos o todas las columnas de la tabla ‘estados’. El resultado lo devuelve en un array.

while ($fila = mysql_fetch_array($arreglo, MYSQL_ASSOC)){
Va obteniendo de la table cada uno de los registros para ponerlos en un array pero (MYSQL_ASSOC) conservando los índices asociativos, es decir, con los nombres de los campos.
function Conectar()
  {
    if (!($link=mysql_connect("localhost","root",""))){
      echo "Error conectando a la base de datos.";
      exit();
    }
    if (!mysql_select_db("concursos",$link))
    {
      echo "Error seleccionando la base de datos.";
      exit();
    }
    return $link;
  }
Al función típica para conectarnos a una base de datos usando PHP y MySql, basta con pasarle la dirección a donde nos deseamos conectar, el usuario y contraseña y crear una conexión que podrá servirnos para hacer las consultas a la base.

if (isset($_GET['estado'])){
	$estado = $_GET['estado'];
	$link=Conectar();
    $arreglo = mysql_query("SELECT * FROM municipios WHERE estado = $estado",$link);
	$todo = array();
	  while ($fila = mysql_fetch_array($arreglo, MYSQL_ASSOC)){
		$todo[] = $fila;
	  }
    for ($i=0;$i".$renglon['nombre_municipio'];
	}
}
Si la variable $_GET[‘estado’] tiene algún parámetro entonces se refiere que alguien hizo referencia al archivo pasándole el id de algún Estado, por lo tanto debemos hacer una consulta para obtener los municipios de dicho Estado.

Por lo tanto hacemos la consulta seleccionando todos los campos de la tabla municipios donde el campo Estado sea igual al idEstado que nos pasaron.

Una vez hecha la consulta tendremos un array con todos los elementos, por lo que será necesario crear un Option por cada municipio y que servirá para llenar el Combo de municipios que tenemos en la página principal.

NOTA: Una primera versión colocaba el TAG < option > < / option > y sus propiedades eran el id_municipio y el nombre del municipio, sin embargo esto sólo funcionaba con Firefox y Chrome, pero no jaló con IExplorer por lo que tuve que modificar el código para que funcionara en los 3 Browsers

Esta función me va a regresar
nombre_municipionombre_municipio


header("Content-Type: text/html; charset=iso-8859-1");
Esta línea es importante ya que varios municipios tienen acentos y pueden no mostrarse de forma correcta, cuando se envía a javascript el array con la lista de municipios, se envía con caracteres que no reconoce y por lo tanto aparecen símbolos en lugar de vocales acentuadas, como experimento sería bueno borrar la línea y ver el resultado.

Hasta aquí tenemos una pantalla de presentación con los combos y un archivo php que devuelve lista de Estados o devuelve lista de municipios si le pasamos como parámetro el id del Estado. Necesitamos uno que conecte ambos archivos y ese está en código JavaScript y es el encargado de solicitar información y pasarla a un objeto en particular del archivo de presentación.

Veamos ahora el archivo cargaMunicipios.js
function getHTTPObject(){
  if (window.ActiveXObject) 
	  return new ActiveXObject("Microsoft.XMLHTTP");
  else if (window.XMLHttpRequest) 
	  return new XMLHttpRequest();
  else {
      alert("Tu navegador no soporta AJAX, te recomendamos actualizar tu sistema.");
      return null;
  }
}
 
function muestraMunicipios(idSelectOrigen){
	var selectOrigen=document.getElementById(idSelectOrigen);
	var opcionSeleccionada = selectOrigen.options[selectOrigen.selectedIndex].value;
	var selectDestino=document.getElementById('municipios');
  httpObject = getHTTPObject();
  if (httpObject != null) 
  {
    httpObject.open("GET", "EdosYMun.php?estado="+opcionSeleccionada, true);
    httpObject.onreadystatechange=function() 
	{ 
		if (httpObject.readyState==1)
		{
			selectDestino.length=0;
			var nuevaOpcion=document.createElement("option"); 
			nuevaOpcion.value=0; 
			nuevaOpcion.innerHTML="Cargando...";
			selectDestino.appendChild(nuevaOpcion);
		}
		if (httpObject.readyState==4)
		{
			var cadena = httpObject.responseText;						var pares = cadena.split("<");        
			selectDestino.length=0;               			for (i=1; i");                   				nuevaOpcion.value=muni[0];                        				nuevaOpcion.innerHTML=muni[1];                    				selectDestino.appendChild(nuevaOpcion);           			}
		} 
	}
    httpObject.send(null);    
  }
}
var httpObject = null;
function getHTTPObject(){

Se declara una función que devuelve un objeto XMLHTTP.

XMLHTTP es una clase que puede hacer llamadas o mejor dicho, peticiones al servidor. Una de las ventajas es que estas peticiones las hace y no tiene que esperar a que le contesten, sino que define eventos que se dispararán en el momento en que el servidor tenga los datos solicitados.

La primera versión de la clase XMLHTTP fue desarrollada por Microsoft para el IE 5 por lo que era necesario crearla como un objeto Activex. Por lo tanto para los que tengan el navegador IE 5 o IE 6 deben crear un objeto Activex para poder crear el XMLHTTP.

Los navegadores o browsers recientes pueden crear un objeto XMLHttpRequest incluyendo el IE después de la versión 7

if (window.ActiveXObject) 
	  return new ActiveXObject("Microsoft.XMLHTTP");
  else if (window.XMLHttpRequest) 
	  return new XMLHttpRequest();
  else {
      alert("Tu navegador no soporta AJAX, te recomendamos actualizar tu sistema.");
      return null;
Por lo tanto la función anterior devuelve el objeto XMLHttpRequest si el navegador lo soporta.
function muestraMunicipios(idSelectOrigen){
Esta es la función que mandamos llamar desde el archivo comboBox.php en la parte donde decía onChange=’javaScript:muestraMunicipios(this.id)’
Por lo tanto cuando cambiaba de opción el combo de los Estados se manda a llamar a esta función, ahora veamos que hace.

var selectOrigen=document.getElementById(idSelectOrigen);
Obtiene el componente que sufrió el cambio o dicho de otra manera, obtiene el elemento que mandó llamar a la función.
var opcionSeleccionada=selectOrigen.options[selectOrigen.selectedIndex].value;
Devuelve al opción del combo que el usuario seleccionó, con esto obtenemos el id_estado.
	var selectDestino=document.getElementById('municipios');
Aquí se define el componente que recibirá la información que le vamos a proporcionar más adelante, en este caso el combo que lleva por nombre ‘municipios’.
httpObject = getHTTPObject();
Asignamos a la variable httpObject el objeto que va a servir de enlace con el servidor, ya sea el XMLHTTP o el XMLHttpRequest.

if (httpObject != null) 
  {
    httpObject.open("GET", "edosYMun.php?estado="+opcionSeleccionada, true);
Si el objeto si se pudo crear entonces seguimos con la comunicación con el servidor, en caso contrario pues no hacemos nada más que informar que su browser es un poco antiguo y necesita actualizarlo.

Le indicamos que método vamos a usar, puede ser GET o POST, en este caso es mediante GET.

Le indidamos la ruta del archivo dentro del servidor y le pasamos los parámetros que en este caso es el id del Estado.

Luego le indicamos si va a ser de forma síncrona o asíncrona, con TRUE le decimos que es asíncrona, es decir, no esperamos a que nos conteste, mas bien continuamos con la ejecución del programa.

if (httpObject.readyState==1)
		{
			selectDestino.length=0;
			var nuevaOpcion=document.createElement("option"); 
			nuevaOpcion.value=0; 
			nuevaOpcion.innerHTML="Cargando...";
			selectDestino.appendChild(nuevaOpcion);
		}
El objeto XMLHttpRequest tiene un atributo readyState que puede contener 4 valores:
0 = sin inicializar, 1 = abierto, 2 = cabeceras recibidas, 3 = cargando y 4 = completado

Cuando me dice que el estado del readyState es igual a 1, entonces ya existe comunicación aunque no ha terminado de recibir datos, por lo tanto lo que hago es crear una opción en el combo y ponerle de texto “cargando…”. Al crear un elemento con la cadena “option” JavaScript ya sabe que nos referimos a la etiqueta < option >< / option > y la crea.

Con la instrucción nuevaOpcion.innerHTML="Cargando..."; agrega el texto dentro del tag o del elemento option.

Una vez creado será necesario insertarlo al combo para lo cual se utiliza la instrucción: selectDestino.appendChild(nuevaOpcion);

if (httpObject.readyState==4)
		{
			var cadena = httpObject.responseText;			
var pares = cadena.split("<");        
			selectDestino.length=0;               			
for (i=1; i");                   
				nuevaOpcion.value=muni[0];                        
				nuevaOpcion.innerHTML=muni[1];                    
				selectDestino.appendChild(nuevaOpcion);           
			}
		} 

Cuando el estado del readyState es igual a 4 quiere decir que ha terminado la comunicación con el servidor y puedo revisar que me ha entregado.

var cadena = httpObject.responseText;
Me devuelve el texto o toda la página que consulté para que pueda manipularla, si recordamos la página visitada me devolvía una cadena como la siguiente:
nombre_municipionombre_municipio
Por lo tanto va a ser necesario recorrer todo el texto y buscar los caracteres <> para separar los municipios.
var pares = cadena.split("<");
Con esta instrucción nos devuelve cadenas que están partidas por el carácter < como ese carácter se encuentra antes de cada id_municipio, sabemos que las cadenas van a comenzar con el id_municipio y luego va a tener un carácter > para separar el id_municipio del nombre del municipio por lo tanto tendremos que hacer otro Split.
for (i=1; i");                   
				nuevaOpcion.value=muni[0];                        
				nuevaOpcion.innerHTML=muni[1];                    
				selectDestino.appendChild(nuevaOpcion);           
			}
Recorremos la lista de pares (id_municipio, nombre_municipio) y por cada par que encontremos creamos, un elemento option, partimos el par tomando el primer valor como el valor del elemento option y la cadena como su contenido. Finalmente lo agregamos al combo.
httpObject.send(null);    
Finalmente con esta instrucción envía la petición a la página comboBox.php Finalmente queda listo para visitar la página comboBox.php y seleccionar un Estado y automáticamente se cargará el listado de los municipios sin cargar de nuevo toda la página. Aquí podrás descargar el código de todo lo mostrado: http://www.mediafire.com/?gh43p9icl823gz1