Autenticacion de usuarios en PHP y MySql

Hola, mi cuenta de gmail ha sido vulnerada, por lo que las imágenes no se ven, pero esta entrada ya la he replicado en http://www.notas-programacion.com/2014/10/autenticacion-de-usuarios-en-php-y-mysql/, el contenido de este blog se estará migrando progresivamente allá, disculpa las molestias.

Como he visto que es muy solicitado el codigo que publique sobre como autenticar usuarios en java y MySql, decidi publicar esta nueva entrada que esta muy relacionada con dicho tema, pero ahora en PHP y un poquito mas completo; encriptacion del password en MD5.

Como decía anteriormente, en algunos sistemas a veces un requerimiento es que se manejen privilegios y por lo tanto usuarios, esto con el fin de controlar lo que cada usuario puede hacer/ver una vez dentro del sistema. En esta entrada únicamente se muestra como autenticar a los usuarios para entrar al sistema, es decir, cada usuario tendrá los mismos privilegios; aunque la tabla de usuarios de MySql (que mostrare mas adelante) ya incluye un campo que determina el tipo de usuario este campo no sera utilizado por ahora. Sin mas preámbulos muestro el ejemplo…

La base de datos

Como siempre que voi a hacer uso de una BD, empezare mostrando el script para recrear las tablas que usare en el ejemplo:

/* Crear la base de datos */
create database prueba;

/*Crear Catalogo de tipos de usuario */
create table ctg_tiposusuario
(
id_TipoUsuario	int not null auto_increment,
tx_TipoUsuario	varchar(100),
primary key(id_TipoUsuario)
);


/* Catalogo de usuarios */
create table tbl_users(
id_usuario int not null auto_increment,
tx_nombre varchar(50) not null,
tx_apellidoPaterno varchar(50),
tx_apellidoMaterno varchar(50),
tx_correo varchar(100),
tx_username varchar(50),
tx_password varchar(250),
id_TipoUsuario int,
dt_registro datetime,
primary key(id_usuario),
foreign key(id_TipoUsuario) references ctg_TiposUsuario(id_TipoUsuario)
);

/*Insertar tipos de usuarios de prueba*/
INSERT INTO `ctg_tiposusuario`( `tx_TipoUsuario`) VALUES ('Administrador');
INSERT INTO `ctg_tiposusuario`( `tx_TipoUsuario`) VALUES ('Usuario Normal');

/*passwrd: 12345*/
/*Insertar usuario de prueba*/
INSERT INTO tbl_users (tx_Nombre,tx_apellidoPaterno,tx_apellidoMaterno,tx_correo,
tx_username,tx_password,id_TipoUsuario,dt_registro) 
VALUES('Gonzalo','Silverio','Silverio','gonzasilve@gmail.com',
'gonzasilve','827ccb0eea8a706c4c34a16891f84e7b',1,'2012-11-09 17:35:40');

La base de datos que usare se llama prueba. Como se observa unicamente son dos tablas, ademas, he creado un catalogo con los diferentes tipos de usuario que pudiera haber, solo he añadido dos tipos de usuario (Administrador y Usuario normal) a modo de ejemplo, pero se pueden añadir mas. Si observas, inserto un usuario de prueba. Si quieres asignar otro password al usuario de prueba puedes utilizar esta sencilla herramienta que te permite generar un MD5 a partir de una cadena cualquiera: http://shalo.site50.net/obtener_md5.php

Herramientas necesarias

Supongo que para el momento de estar leyendo este articulo ya tienes el software necesario (ho al menos piensas instalarlo). Como he visto que los visitantes muchas veces son estudiantes de carrera ho aficionados a la programacion; pero con poca experiencia (me incluyo), voi a listar las herramientas de sw necesarias que debes tener yá en tu maquina si quieres probar este exquisito codigo :), puedes usar otro servidor y otro dbms, pero yo use estas:
Como ves son pocos requisitos, si no tienes alguno este es el momento para que lo instales. El servidor de correo de hecho es opcional, solo lo instale para hacer pruebas en mi computadora local (una laptop), si tienes dudas sobre hMailServer en la misma pagina viene mucha documentación acerca de como instalarlo y configurarlo. Si tienes más dudas puedes preguntarle al oraculo (google) escribiendo esto ‘hmailserver y php’.

Bueno vamos a lo interesante…

El código fuente

index.php

Este archivo permite mostrar la ventana de Login, en esta como es de suponerse el usuario introduce su nombre de usuario, su password y le da click al boton enviar, bueno muestro el codigo:
<!--     
	Instituto Tecnologico de Zacatepec, Morelos 
Descripcion:   Archivo para mostrar una pantalla de login con los campos;
				de usuario y password, los 2 datos se envian al archivo validarUsuario.php 
				por el metodo POST. 
Author:     Gonzalo Silverio  gonzasilve@gmail.com 
Archivo:    index.php 
-->

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>.:: Login ::. Ejemplo autenticar usuarios</title>
	
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<link rel="stylesheet" href="estilos.css" type="text/css">
	<script src="jquery171.js" type="text/javascript"></script> 
	<script src="jquery.validate.js" type="text/javascript"></script>
	<script type="text/javascript" src="jquery.alerts.js"></script>
	<link href="jquery.alerts.css" rel="stylesheet" type="text/css" />
	
	<script type="text/javascript">
	<!--
		$().ready(function() {
			$("#frmlogin").validate();
			$("#usuario").focus();
		});
	// -->
	</script>
	
</head>
<body>
<br /><br />
<form id="frmlogin" name="frmlogin"  method="POST" action="validarUsuario.php">
<table align="center" width="200px">
<tr>
	<td colspan="2" align="center"><h3>Iniciar sesi&oacute;n</h3></td>
</tr>
<tr>
	<td>Usuario</td>
	<td>
		<input type="text" name="usuario" id="usuario" class="required" maxlength="50">
	</td>
</tr>

<tr>
	<td>Password</td>
	<td>
		<input type="password" name="password" id="password" class="required"  maxlength="50">
	</td>
</tr>
<tr >
	<td colspan="2" >
		<a href="recuperarPassword.php">
			Olvide mi contrase&ntilde;a
		</a>
	</td>
</tr>

<tr>
	<td colspan="2" align="right">
		<input type="submit" name="enviar" value="Enviar" >
	</td>

</tr>
	
<tr>
	<td colspan="2" align="right" >
		<br/><a href="registro.php">Deseo registrarme</a>
	</td>
</tr>	
	<?php
	
	//Mostrar errores de validacion de usuario, en caso de que lleguen
	
		if( isset( $_POST['msg_error'] ) )
		{
			switch( $_POST['msg_error'] )
			{
				case 1:
			?>
			<script type="text/javascript"> 
				jAlert("El usuario o password son incorrectos.", "Seguridad");
				$("#password").focus();
			</script>
			<?php
				break;			
				case 2:
			?>
			<script type="text/javascript"> 
				jAlert("La seccion a la que intentaste entrar esta restringida.\n Solo permitida para usuarios registrados.", "Seguridad");
			</script>
			<?php		
				break;
			}		//Fin switch
		}

		//Mostrar mensajes del estado del registro
		
		if( isset( $_POST['status_registro'] ) )
		{
			switch( $_POST['status_registro'] )
			{
				case 1:
				if( $_POST['i_EmailEnviado'] ==1) {
				?>
					<script type="text/javascript"> 
						jAlert("Gracias, ha sido registrado exitosamente.\n Se le ha enviado un correo electronico de bienvenida, \npor favor, NO LO CONTESTE pues solo es informativo.", 'Registro');
					</script>
					<?php
				} else {
					?>
					<script type="text/javascript"> 
						jAlert("Gracias, ha sido registrado exitosamente.\n No se le ha podido enviar correo electronico de bienvenida, \nsin embargo, ya puede utilizar sus datos de acceso para iniciar sesion..", 'Registro');
					</script>
				<?php
				}

					break;			
				
				default:
			?>
				<script type="text/javascript"> 
					jAlert("Temporalmente NO se ha podido registrar, intente de nuevo mas tarde.", "Registro");
				</script>
			<?php		
			}		//Fin switch
		}
	?>
	
</table>
</form>
</body>
</html>

Como se puede ver para mostrar los mensajes de error utilizo la libreria JQuery, ya que me parecio que usar un alert() de javascript es algo feito, jajajaj. Como se ve el archivo en si solamente crea un formulario en el cual se dibujan dos cajas de texto; una para el usuario y otra para el password, un link para ir a la pantalla de recuperacion del password en caso de que al usuario se le haya olvidado y por ultimo se crea un boton tipo submit para enviar la informacion. Para validar campos vacios tambien utilizo JQuery. Ademas se puede ver que envio los dos datos de las cajitas a un archivo llamado validarUsuario.php por el metodo POST; el cual se encargara de accesar a la BD y verificar que los datos sean correctos.

Otra cosa interesante que se puede observar es que este archivo verifica si le llega un parametro llamado msg_error (con la funcion isset() de php) y en base a ese parametro (en realidad es un codigo de error) muestra un mensaje de error. A continuacion muestro un pantallazo como se ve el formulario en el navegador Chrome:

Pantalla de Login
En caso de que el usuario introduzca un nombre de usuario incorrecto se mostrara esta pantalla:
Pantalla Login, error usuario

Como se observa se ven mas atractivas las alertas con JQuery y ademas es sumamente facil utilizarlas.

validarUsuario.php

Este archivo es el que se encarga de recibir los datos del archivo index.php y los compara contra los que estan en la BD. Si el usuario y el password son correctos (existen en la BD) guarda el id del usuario en un formulario (el dato se envia oculto, hidden), inicializa una sesion , guarda algunas variables en dicha sesión y redirecciona hacia el archivo principal.php el cual es la pagina web que se supone debe mostrarse para usuarios registrados. En caso de que el usuario y/o password sean incorrectos entonces este archivo guarda igualmente un codigo de error en un formulario y redirecciona a la pagina de login, es decir, al archivo index.php. A continuacion se muestra su codigo fuente:
<?php
	/*
		Instituto Tecnologico de Zacatepec, Morelos 
	Descripcion:   Archivo que recibe los valores de 2 campos;
			un usuario y un password, los 2 datos se buscan si estan en la
			base de datos y redicciona al login o la pagina principal. 
	Author:     Gonzalo Silverio  gonzasilve@gmail.com 
	Archivo:    validarUsuario.php 
	*/ 

	//conectar BD
	include("conectar_bd.php");  
	conectar_bd();
	
	$usr = $_POST['usuario'];
	$pw = $_POST['password'];
	//Obtengo la version encriptada del password
	$pw_enc = md5($pw);
	
	$sql = "SELECT id_usuario FROM tbl_users
			INNER JOIN ctg_tiposusuario
			ON tbl_users.id_TipoUsuario = ctg_tiposusuario.id_TipoUsuario
			WHERE tx_username = '".$usr."'
			AND tx_password = '".$pw_enc."'	";	
	$result		=mysql_query($sql,$conexio); 

	$uid = "";
	
	//Si existe al menos una fila
	if( $fila=mysql_fetch_array($result) )
	{		
		//Obtener el Id del usuario en la BD 		
		$uid = $fila['id_usuario'];
		//Iniciar una sesion de PHP
		session_start();
		//Crear una variable para indicar que se ha autenticado
		$_SESSION['autenticado']    = 'SI';
		//Crear una variable para guardar el ID del usuario para tenerlo siempre disponible
		$_SESSION['uid']       		= $uid;
		//CODIGO DE SESION
		
		//Crear un formulario para redireccionar al usuario y enviar oculto su Id 
?>
		<form name="formulario" method="post" action="principal.php">
			<input type="hidden" name="idUsr" value='<?php echo $uid ?>' />
		</form>
<?php
	}
	else {
		//En caso de que no exista una fila...
		//..Crear un formulario para redireccionar al usuario a la pagina de login 
		//enviandole un codigo de error
?>
		<form name="formulario" method="post" action="index.php">
			<input type="hidden" name="msg_error" value="1">
		</form>
<?php
	}
?>
					
<script type="text/javascript"> 
	//Redireccionar con el formulario creado
	document.formulario.submit();
</script>
Como se observa; la mayoria del codigo esta comentado por lo que me ahorrare volver a explicar: Lo que si quiero mencionar es que en la linea 40 he dejado un comentario (CODIGO DE SESION), en esa linea si usted quiere puede generar un identificador de sesion, debido a que el ID de sesion de PHP a veces se pierde; usted puede crear un ID mas seguro; por ejemplo con base a la fecha y hr actual. la funcion session_id () permite leer o asignar el ID de la sesion.

La funcion session_start() permite iniciar una sesion o continuar una ya iniciada. Es por eso que en todas las paginas web que requieran que el usuario este autenticado se llama a esta funcion de PHP, esto lo podras ver en los demas archivos que mostrare mas adelante.

En la linea 37 y 39 se observa que es muy facil crear una variable de sesion con ayuda del array global $_SESSION[], basta con agregar un nuevo item y asignarle un valor, asi de facil. Posteriormente se pueden utilizar en cualquier pagina php por ejemplo para mostrar el Id del usuario y su Status en el navegador:
	echo "Id del usuario:".$_SESSION['uid'];
	echo "Ha iniciado sesion:".$_SESSION['autenticado'];

Facil ¿No?. Continuemos…

En la linea 12 del archivo validarUsuario.php se inserta un archivo llamado conectar_bd.php el cual se encarga de conectar con el DBMS, este archivo es el que muestro a continuacion…

conectar_bd.php

<?php
/*     
	Instituto Tecnologico de Zacatepec, Morelos 
Descripcion:   Conecta con el Manejador de Base de Datos (DBMS) y deja disponible una variable global (conexio)
		para ser utilizada posteriormente. 
Author:     Gonzalo Silverio  gonzasilve@gmail.com 
Archivo:    conectar_bd.php 
*/

$conexio;
function conectar_bd()
{
	global $conexio;
	//Definir datos de conexion con el servidor MySQL
	$elUsr = "root";
	$elPw  = "12345";
	$elServer ="localhost";
	$laBd = "prueba";
	
	//Conectar
	$conexio = mysql_connect($elServer, $elUsr , $elPw) or die (mysql_error());
	
	//Seleccionar la BD a utilizar
	mysql_select_db($laBd, $conexio ) or die (mysql_error());
}	
?>
Como se observa primero se definen los datos de conexion en variables locales a la funcion conectar_bd(). y posteriormente estas variables se usan como parametros para llamar a la funcion mysql_connect(), la cual es la que hace la peticion al dbms para conectarse. la funcion mysql_connect() devuelve un link que representa la conexion establecida al dbms, con este link guardado en la variable $conexio se selecciona la BD a utilizar (linea 24).

principal.php

Este archivo es la pantalla que el usuario ve si se logueo correctamente, nada mas como ejemplo he creado una muy sencilla. Cuando el usuario accede a esta pagina web se supone que ya paso por la pantalla de login y sus datos fueron verificados en la BD. Pero por seguridad antes de mostrarla verifico que efectivamente este logueado a travez de las variables de sesion que fueron creadas en el archivo validarUsuario.php. A continuacion muestro el codigo fuente:
<?php
/*     
	Instituto Tecnologico de Zacatepec, Morelos 
Descripcion:   Pantalla inicial que se muestra al usuario una vez que ha sido logueado correctamente. 
Author:     Gonzalo Silverio  gonzasilve@gmail.com 
Archivo:    principal.php 
*/

//Inicializar una sesion de PHP
session_start();

//Validar que el usuario este logueado y exista un UID
if ( ! ($_SESSION['autenticado'] == 'SI' && isset($_SESSION['uid'])) )
{
	//En caso de que el usuario no este autenticado, crear un formulario y redireccionar a la 
	//pantalla de login, enviando un codigo de error
?>
		<form name="formulario" method="post" action="index.php">
			<input type="hidden" name="msg_error" value="2">
		</form>
		<script type="text/javascript"> 
			document.formulario.submit();
		</script>
<?php
}

	//Conectar BD
	include("conectar_bd.php");  
	conectar_bd();

	//Sacar datos del usuario que ha iniciado sesion
	$sql = "SELECT  tx_nombre,tx_apellidoPaterno,tx_TipoUsuario,id_usuario
			FROM tbl_users
			LEFT JOIN ctg_tiposusuario
			ON tbl_users.id_TipoUsuario = ctg_tiposusuario.id_TipoUsuario
			WHERE id_usuario = '".$_SESSION['uid']."'";			
	$result		=mysql_query($sql); 

	$nombreUsuario = "";

	//Formar el nombre completo del usuario
	if( $fila = mysql_fetch_array($result) )
		$nombreUsuario = $fila['tx_nombre']." ".$fila['tx_apellidoPaterno'];
	
//Cerrrar conexion a la BD
mysql_close($conexio);
?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>.:: Inicio ::. Ejemplo autenticar usuarios</title>
	<link rel="stylesheet" href="estilos.css" type="text/css">
</head>
<body topmargin="0" >
<table align="right" width="350px" border="0">
<tr>												<!-- Dar Bienvenida al usuario -->
	<td  width="100px" align="right">Bienvenido <b><?php echo $nombreUsuario ?></b></td>
	<td  width="15px" align="center">
		<!-- Proporcionar Link para cerrar sesion -->
		<a href="cerrarSesion.php">Cerrar sesi&oacute;n</a>	
	</td>
</tr>
</table>
<br /><br />
<h2 align="center">Pantalla Principal</h2>

		<!-- Contenido inicial del sitio web -->
		
<body>
</html>
Como decia en la lineas anteriores, cuando una pagina esta restringida lo primero que se debe hacer es verificar que el usuario esta logueado y tiene permisos para ver dicha pagina. Como dije que no mostraria como dar permisos a los usuarios, en este ejemplo solo se comprueba que haya una sesion iniciada y que exista entre las variables de sesion un UID (User Id); Id del usuario en la Base de datos.

Si se verifica que esas condiciones se cumplen entonces se obtienen los datos del usuario, tal como su nombre , correo electronico, etc. Yo solo saque su nombre completo y lo mostre en la esquina superior derecha para que el usuario tenga la sensacion (jajajajj “sienta”) que a entrado al portal. A continuacion muestro un pantallazo de este archivo en el navegador:

Pantalla de inicio del usuario logueado

Como se observa tambien se ha puesto al usuario un link para que cierre su sesion.

Seguridad

Imaginemos que un usuario malintencionado escribe directamente la URL de este archivo en su navegador (escribe http://localhost/autenticar_usuarios/principal.php) pensando que con esto puede entrar y ver el contenido del sitio. Perdera su tiempo pues para eso presisamente se hace la validacion al inicio y solamente vera un mensaje de error como el que se ve a continuacion:

Mensaje de error al entrar a pagina principal sin login

cerrarSesion.php

Este archivo es al que apunta el enlace “Cerrar sesión ” que esta a un lado del nombre de usuario (una vez que ha iniciado su sesión). Este archivo se encarga de destruir todas las variables de sesión y terminar la sesion; todo esto se hace con las funciones que PHP ya trae incluidas.
<?php
/*     
	Instituto Tecnologico de Zacatepec, Morelos 
Descripcion:   Archivo para destruir las variables de sesion de un usuario logueado y terminar la sesion,
				 	ademas redirecciona nuevamente a la pagina de login. 
Author:     Gonzalo Silverio  gonzasilve@gmail.com 
Archivo:    cerrarSesion.php 
*/

session_start();
// Destruye todas las variables de la sesion
session_unset();
// Finalmente, destruye la sesion
session_destroy();

//Redireccionar a la pagina de login
header ("Location: index.php");

?>
Como se ve es muy corto el archivo. No doy mas explicacion ya que cada instruccion esta comentada.

recuperarPassword.php

En la pagina de login, si observas hay un link que dice Olvide mi contraseña, este link nos manda al archivo recuperarPassword.php. Este archivo permite enviar un nuevo password al usuario, el usuario solo debe escribir su correo electronico y automaticamente se generara un nuevo password de nueve caracteres y se le enviara a dicho email. Obviamente que el correo proporcionado se valida que exista en la BD; Como se observa en la BD el password esta encriptado en MD5 por lo que es necesario proporcionarle otro; no hay forma descifrar el password anterior.
<?php
	/*
		Instituto Tecnologico de Zacatepec, Morelos 
	Descripcion:   Este archivo permite preguntar al usuario su correo electronico para enviarle un nuevo
						password. 
	Author:     Gonzalo Silverio  gonzasilve@gmail.com 
	Archivo:    recuperarPassword.php 
	*/ 
?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>.:: Recuperar Password ::. </title>
	
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
	<link rel="stylesheet" href="estilos.css" type="text/css">
	<script src="jquery171.js" type="text/javascript"></script> 
	<script src="jquery.validate.js" type="text/javascript"></script>
	<script type="text/javascript" src="jquery.alerts.js"></script>
	<link href="jquery.alerts.css" rel="stylesheet" type="text/css" />
	
	<script type="text/javascript">
	<!--
		$().ready(function() {
		$("#recPassword").validate({
		rules: {
		/*A continuacion los nombres de los campos y sus reglas a cumplir */
			correo2: {
			required: true,
			email: true,
			equalTo: "#correo"
			},
			correo: {
			required: true,
			email: true
			}


		}
		});
		$("#correo").focus();
		});
	// -->
	</script>
	
</head>
<body>
<br /><br />


<form id="recPassword" name="recPassword"  method="POST" action="recuperarPassword.php">

<table align="center" width="400px">

<tr>
	<td colspan="2" align="center"><h3><b>Recuperar Password</b></h3></td>
</tr>

<?php
//Si llega el parametro correo y no viene vacio
if( isset( $_POST['correo'] ) && $_POST['correo'] != '' )
{
	//Conectar la BD
	include("conectar_bd.php");  
	conectar_bd();

	//Recuperar la direccion de email que llega
	$elcorreo   = $_POST['correo'];
	
	//Verificar si existe el correo en la BD
	$sql = "SELECT  id_usuario,tx_username,tx_nombre,tx_apellidoPaterno
			FROM tbl_users
			WHERE tx_correo = '".$elcorreo."'";			
	$rs_sql	= mysql_query($sql);

	//Si no existe el correo... 
	if ( !( $fila 	= mysql_fetch_object($rs_sql) )  )
	{
	//Mostrar msg de error al usuario (en esta misma pagina)
?>
	<input type="hidden" id="error" value="1">			
	<script type="text/javascript"> 
	location.href="recuperarPassword.php?error="+document.getElementById('error').value;
	</script>
<?php
	}
	
	//En caso de que si exista un email como el k llega, leer de la BD los datos del usuario
	$idusr 	= $fila->id_usuario;		//Servira para actualizar el pw
	$nombre = $fila->tx_nombre." ".$fila->tx_apellidoPaterno;
	$nick 	= $fila->tx_username;
	
	// Generacion de un nuevo Password
	$pasw = "";
	$abecedario = array("A","B","C","D","E","F","G","H","J","K","L","M","N","O","P","Q","R","S","T",
"U","V","W","a","b","c","d","e","f","g","h","j","k","l","m","n","o","p","q","r","s","t","u","v","w");
	$simbolos 	= array(",","}","{","-","|","!","#","$","%","&","/","(",")","=","?","¡",
"*","]","[","_",":",";","+");
	for($i=0;$i<3; $i++)
	{
		$md 	= rand(1,2);
		$pasw 	.=  (($md%2)==0) ? $abecedario[rand(0,43)] : rand(0,9);  
		$md 	= rand(1,2);
		$pasw 	.=  (($md%2)==0) ? rand(0,9) :  $simbolos[rand(0,23)];  
		$md 	= rand(1,2);
		$pasw 	.=  (($md%2)==0) ?   $simbolos[rand(0,23)] : $abecedario[rand(0,43)] ;		
	}		
	
	// Le  Envio  por correo electronico  su nuevo password 
     $seEnvio;			//Para determinar si se envio o no el correo
     $destinatario = $elcorreo;				//A quien se envia
     $nomAdmin 			= 'Gonzalo Silverio';		//Quien envia
	 $mailAdmin 		= 'gonzasilve@gmail.com';	//Mail de quien envia
	 $urlAccessLogin = 'http://localhost/autenticar_usuarios/';	//Url de la pantalla de login

     $elmensaje = "";     
     $asunto = "Nueva contraseña para ".$nick;

     $cuerpomsg ='
		<h3>.::Recuperar Password::.</h3>
		<p>A peticion de usted; se le ha asignado un nuevo password, utilice los siguientes datos para acceder al sistema</p>
		  <table border="0" >
			<tr>
			  <td colspan="2" align="center" ><br> Nuevos datos de acceso para <a href="'.$urlAccessLogin.'">'.$urlAccessLogin.'</a><br></td>
			</tr>
			<tr>
			  <td> Nombre </td>
			  <td> '.$nombre.' </td>
			</tr>
			<tr>
			  <td> Username </td>
			  <td> '.$nick.' </td>
			</tr>
			<tr>
			  <td> Password </td>
			  <td> '.$pasw.' </td>
			</tr>
		  </table> ';
		  
	date_default_timezone_set('America/Mexico_City');
		  
	//Establecer cabeceras para la funcion mail()
	//version MIME
	$cabeceras = "MIME-Version: 1.0\r\n";
	//Tipo de info
	$cabeceras .= "Content-type: text/html; charset=iso-8859-1\r\n";
	//direccion del remitente
	$cabeceras .= "From: ".$nomAdmin." <".$mailAdmin.">";
	$resEnvio = 0;
	//Si se envio el email
	if(mail($destinatario,$asunto,$cuerpomsg,$cabeceras))
	{
		//Actualizar el pwd en la BD
		$sql_updt = "UPDATE tbl_users SET tx_password = '".md5($pasw)."' 
		WHERE (id_usuario = ".$idusr.")
		AND (tx_correo = '".$elcorreo."')";
		$res_updt = mysql_query($sql_updt);
		$resEnvio = 1;
	}

	//Cerrrar conexion a la BD
	mysql_close($conexio);
		
	// Mostrar resultado de envio (en esta misma pagina)
	?>
		<input type="hidden" id="enviado" value="<?php echo $resEnvio ?>">
		<input type="hidden" id="elcorreo" value="<?php echo $elcorreo ?>">
		<script type="text/javascript">
			location.href="recuperarPassword.php?enviado="+document.getElementById('enviado').value+"&elcorreo="+document.getElementById('elcorreo').value;
		</script>
	<?php	
}
else
{
?>

<tr>
	<td colspan="2">Escriba su correo electronico con el que se ha registrado, 
		se le enviara un nuevo password a su correo electronico:<br /><br /> 
	</td>
</tr>

<tr>
	<td>Correo electronico:</td>
	<td>
		<input type="text" name="correo" id="correo"  maxlength="50" />
	</td>
</tr>
<tr>
	<td>Confirme Correo electronico:</td>
	<td>
		<input type="text" name="correo2" id="correo2" maxlength="50" />
	</td>
</tr>

<?php
	//Si llega un codigo de error
	if( isset($_GET['error']) && $_GET['error']==1 )
	{
		echo "<tr><td colspan='2'><br><font color='red'>El correo electronico no pertenece a ningun usuario registrado.</font><br></td></tr>";
	}
	else if( isset($_GET['enviado']) && isset($_GET['elcorreo'])  )
	{
		//Si se envio correctamente el nuevo password
		if( $_GET['enviado']==1 ) 
			echo "<tr><td colspan='2'><br><font color='green'>Su nueva contrase&ntilde;a ha sido enviada a <strong>".$_GET['elcorreo']."</strong>.</font><br></td></tr>";
		else if( $_GET['enviado']==0 ) 
			echo "<tr><td colspan='2'><br><font color='red'>Por el momento la nueva contrase&ntilde;a no pudo ser enviada a <strong>".$_GET['elcorreo']."</strong>.<br>
			Intente de nuevo mas tarde.</font></td></tr>";
	}
?>

<tr>
	<td align="center" colspan="2">
		<br /><br /> 
		<input type="button" onClick="javascript: location.href='index.php'" name="cancelar" value="Cancelar" >
		&nbsp;&nbsp;&nbsp;&nbsp;
		<input type="submit" name="enviar" value="Enviar" >
	</td>
</tr>

<?php
}
?>

</table>
</form>
</body>
</html>

Para mas seguridad el password nunca se muestra al usuario, por el contrario; se le asigna otro (formado aleatoriamente) y se le envia por correo electronico. Como se observa en la linea 60 se comienza comprobando si llega un parametro llamado ‘correo’; si llega esto quiere decir que el formulario de recuperacion de password ya fue enviado y el correo que esta llegando es de un usuario al que se le debe asignar un nuevo password. Por el contrario; sino llega, se dibujan dos cajas de texto para permitir al usuario escribir su correo electronico y se le pueda enviar su password.

Bueno, supongamos que a este archivo le llega un el parametro correo, entonces de la linea 62 a la linea 85 se comprueba si ese email existe en la BD. sino existe, entonces se redirecciona al usuario a este mismo archivo pero con un codigo de error, el cual servira para mostrar un texto al usuario avisando que su correo electronico no existe. En caso de que si exista el email en la BD (no se cumple la condicion de la linea 76) entonces se recuperan los datos del usuario (linea 88 a la 90) y posteriormente se le genera un nuevo password (linea 93 a la 104), observe la forma como he generado el nuevo password del usuario; cada ciclo agrega 3 caracteres: el primero puede ser una letra ho un numero, el segundo puede ser un numero o un simbolo del array con el mismo nombre, el tercero puede ser un simbolo o una letra (Como son tres ciclos entonces el password tendra nueve caracteres).

Y ya por ultimo se le envia el password a su correo electronico del usuario (linea 106 a la linea 165). Algo que me gustaria resaltar es que el nuevo password debe ser actualizado en la BD para que la proxima vez el usuario intente iniciar sesion pues este password sea valido, ademas, solo se debe de actualizar despues de notificar al usuario (envio de email correcto), tal como se hace en este ejemplo.

A continuacion pongo una imagen del error que aparece en caso de que el email escrito no exista:

El email no existe en la Base de datos

Mensaje en caso de que el email haya sido enviado correctamente:

Nuevo password asignado correctamente

Ya no pongo el mensaje del error en caso de que NO se envie el email (falle la funcion mail() de php), porque es muy obvia, pero, a continuación dejo una imagen del eMail que le llega al usuario, con sus nuevos datos de acceso:

Email con nuevo password del usuario

registro.php

A peticion de muchos de los visitantes que preguntan (ya sea en privado o en comentarios de esta entrada) como registrar usuarios en php decidi exponer un ejemplo. En la pantalla de Login si observas aparece un enlace (hipervinculo) con la leyenda Deseo registrarme; el codigo que muestro a continuacion es del archivo que se muestra en el navegador al dar click en dicho enlace. Este archivo, en resumen, muestra un formulario creado con HTML para que el usuario capture sus datos personales y datos de acceso (username y password) envie dichos datos al script guardarRegistro.php que guarda los datos en la base de datos. El codigo es este…
<?php
	/*
		Instituto Tecnologico de Zacatepec, Morelos
	Descripcion:   Este archivo muestra un formulario que permite al usuario
		capturar sus datos y personales y de acceso.
	Author:     Gonzalo Silverio  gonzasilve@gmail.com
	Archivo:    registro.php
	*/

$str_nombre 		= "";
$str_apPaterno 	= "";
$str_apMaterno 	= "";
$str_correo 		= "";
$str_username 	= "";
$str_password 	= "";
$str_password2 	= "";

if( isset($_POST['str_nombre']) ) 		
	$str_nombre 		= trim($_POST['str_nombre']);
if( isset($_POST['str_apPaterno']) ) 
	$str_apPaterno 	= trim($_POST['str_apPaterno']);
if( isset($_POST['str_apMaterno']) ) 
	$str_apMaterno 		= trim($_POST['str_apMaterno']);
if( isset($_POST['str_correo']) ) 
	$str_correo 	= trim($_POST['str_correo']);
if( isset($_POST['str_username']) ) 
	$str_username 	= trim($_POST['str_username']);
if( isset($_POST['str_password']) ) 
	$str_password 	= trim($_POST['str_password']);
if( isset($_POST['str_password2']) ) 
	$str_password2 	= trim($_POST['str_password2']);


?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>.:: Registrar Usuario ::. </title>

	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
	<link rel="stylesheet" href="estilos.css" type="text/css">
	<script src="jquery171.js" type="text/javascript"></script>
	<script src="jquery.validate.js" type="text/javascript"></script>
	<script type="text/javascript" src="jquery.alerts.js"></script>
	<link href="jquery.alerts.css" rel="stylesheet" type="text/css" />

	<script type="text/javascript">
	<!--
		$().ready(function() {
		$("#registrar_usuario").validate({
		rules: {
		/*A continuacion los nombres de los campos y sus reglas a cumplir */
			tx_nombre: {
				required: true,	minlength: 3
			},
			tx_apPaterno: {
				required: true, minlength: 3
			},
			tx_apMaterno: {
				required: true,	minlength: 3
			},
			tx_correo: {
				required: true,	minlength: 5, email: true
			},
			tx_username: {
				required: true,	minlength: 5
			},
			tx_password: {
				required: true,	minlength: 5
			},
			tx_password2: {
				required: true,	minlength: 5,	equalTo: "#tx_password"
			}

		},
		/*A continuacion los campos y los mensajes en caso de que no se cumplan las reglas */
		messages: {
			tx_nombre: {
				required: "Por favor, escriba su Nombre.",
				minlength: jQuery.format("Su Nombre como minimo debe tener {0} caracteres.")
			},
			tx_apPaterno: {
				required: "Por favor, escriba su Apellido Paterno.",
				minlength: jQuery.format("Su Apellido Paterno como minimo debe tener {0} caracteres.")
			},
			tx_apMaterno: {
				required: "Por favor, escriba su Apellido Materno.",
				minlength: jQuery.format("Su Apellido Materno como minimo debe tener {0} caracteres.")
			},
			tx_correo: {
				required: "Por favor, escriba una direccion de correo electronico valida.",
				minlength: jQuery.format("Por favor, escriba una direccion de correo electronico valida.")
			},
			tx_username: {
				required: "Por favor, escriba un nombre de usuario. Este dato le servira para iniciar sesion y ver el contenido.",
				minlength: jQuery.format("Su nombre de usuario como minimo debe tener {0} caracteres.")
			},
			tx_password: {
				required: "Por favor, escriba una contraseña.",
				minlength: jQuery.format("Su contraseña como minimo debe tener {0} caracteres.")
			},
			tx_password2: {
				required: "Por favor, repita la contraseña anterior.",
				minlength: jQuery.format("Su contraseña como minimo debe tener {0} caracteres."),
				equalTo: "Por favor, repita la contraseña anterior.",
			}

		}

		});
		$("#tx_nombre").focus();
		});
	// -->
	</script>

</head>
<body>
<br />


<form id="registrar_usuario" name="registrar_usuario"  method="POST" action="guardarRegistro.php">

<table align="center" width="600px">

<tr>
	<td colspan="2" align="center"><h3><b>Registrar usuario</b></h3></td>
</tr>

<tr>
	<td colspan="2">Gracias por tu interes en registrarte. Para hacerlo, solo debes llenar
	los siguientes campos y pulsar el boton <b>Registrarme</b>. Para hacer mas rapido el registro y
	asi tu puedas acceder al contenido, tu cuenta se activa inmediatamente.<br /><br />
	</td>
</tr>
	
	<?php
		//Si llega el parametro error y no viene vacio
		if( isset( $_POST['error'] ) && $_POST['error'] != '' ) {
	?>
		<tr>
			<td colspan="2" >
				<font color="red">
				<ul>
					<?php
						echo $_POST['msgs_error'];
					?>
				</ul>
				</font>
			</td>
		</tr>
	<?php
		}
	?>

	
	<tr>
		<td><label for="tx_nombre">Nombre(s)</label></td>
		<td>
			<input type="text" name="tx_nombre" id="tx_nombre" value='<?php echo $str_nombre ?>' size="30"  maxlength="30" />
		</td>
	</tr>
	<tr>
		<td><label for="tx_apPaterno">Apellido paterno</label></td>
		<td>
			<input type="text" name="tx_apPaterno" id="tx_apPaterno" value='<?php echo $str_apPaterno ?>' size="30"  maxlength="30" />
		</td>
	</tr>
	<tr>
		<td><label for="tx_apMaterno">Apellido materno</label></td>
		<td>
			<input type="text" name="tx_apMaterno" id="tx_apMaterno"  value='<?php echo $str_apMaterno ?>' size="30"  maxlength="30" />
		</td>
	</tr>
	<tr>
		<td><label for="tx_correo">Correo electronico</label></td>
		<td>
			<input type="text" name="tx_correo" id="tx_correo"  value='<?php echo $str_correo ?>' size="30"  maxlength="30" />
		</td>
	</tr>
	<tr>
		<td><label for="tx_username">Nombre de usuario</label></td>
		<td>
			<input type="text" name="tx_username" id="tx_username"  value='<?php echo $str_username ?>' size="25"  maxlength="25"  />
		</td>
	</tr>
	<tr>
		<td><label for="tx_password">Contrase&ntilde;a</label></td>
		<td>
			<input type="password" name="tx_password" id="tx_password"  value='<?php echo $str_password ?>'  size="25"  maxlength="25" />
		</td>
	</tr>
	<tr>
		<td><label for="tx_password2">Confirme la contrase&ntilde;a</label></td>
		<td>
			<input type="password" name="tx_password2" id="tx_password2"  value='<?php echo $str_password2 ?>'  size="25"  maxlength="25" />
		</td>
	</tr>
	<tr>
		<td>Tipo de usuario</td>
		<td>
			<input type="hidden" name="i_tipoUsuario" id="i_tipoUsuario" value="2"   />
			<input type="radio" name="rad_TipoUsuario" id="rad_TipoUsuario" disabled value="2" checked="checked"  /> Usuario normal &nbsp;&nbsp;&nbsp;
			<input type="radio" name="rad_TipoUsuario" id="rad_TipoUsuario" disabled value="1"  /> Administrador
		</td>
	</tr>

<tr>

	<td align="center" colspan="2">
		<br /><br />
		<input type="button" onClick="javascript: location.href='index.php'" name="cancelar" value="Cancelar" >
		&nbsp;&nbsp;&nbsp;&nbsp;
		<input type="submit" name="registrarme" value="Registrarme" >
	</td>
</tr>

</table>
</form>
</body>
</html>
Como puedes observar esta un poco extenso (como 200 lineas sin lineas en blanco); ese es el precio de validar de una manera rigurosa los datos que el usuario introduce en los cuadros de texto. Tratare de explicar un poco este archivo, pero antes te muestro una imagen de la pagina web que se genera a partir del codigo fuente anterior:

Pagina web para registrar usuarios

De la linea 10 a 16 se declaran y limpian variables, una para cada dato del usuario que se va a registrar, enseguida en la linea 18 se verifica si esta llegando (si exite, con isset()) la variable de str_nombre, si se cumple que si existe dicha variable; hay una variable con el mismo nombre que se declaro antes (linea 10), entonces se le asigna el valor que llega. Cuando llegan datos significa que ya se habian enviado los datos al archivo guardarRegistro.php y éste los esta regresando si no los pudo guardar. Esta operacion la realiza para cada dato del usuario.

Si continuamos viendo el codigo se observa que de la linea 50 a la 100 es codigo javascript donde ajustamos parametros del plugin de validacion de JQuery. A este tipo de validacion se le conoce como validacion del lado cliente, en este caso el cliente es el navegador.

En la linea 121 se observa que esta escrito el encabezado del formulario y en su parametro action estamos diciendole que envie los datos de dicho formulario al archivo guardarRegistro.php el cual se encargara de guardarlos en la base de datos (no sin antes validarlos en el lado servidor).

En la linea 138 estamos verificando si existe/llega una variable llamada error y en caso de que si, mostramos la lista de errores que ocurrieron al guardar. La lista de errores vienen en otra variables llamada msg_error. Observa como en la linea 143 y 147 se abre y cierra, respectivamente una lista desordenada de HTML, la variable msg_error trae los <li> </li> correspondientes, cada <li> es un error que ocurrio al intentar guardar en el archivo guardarRegistro.php. En caso de que hayan ocurrido errores se mostrara una pantalla similar a esta:

Horrores al registrar un usuario

guardarRegistro.php

Este archivo recibe los datos del archivo registro.php y los guarda en la base de datos. Antes de guardar realiza varias validaciones, mas abajo esta la explicacion pero, veamos el codigo…
<?php
	/*
		Instituto Tecnologico de Zacatepec, Morelos
	Descripcion:   Este archivo permite guardar un nuevo usuario.
	Author:     Gonzalo Silverio  gonzasilve@gmail.com
	Archivo:    guardarRegistro.php
	*/
	//Recuperar los datos del formulario de registro
	$str_nombre			=trim($_POST['tx_nombre']);
	$str_apPaterno	=trim($_POST['tx_apPaterno']);
	$str_apMaterno	=trim($_POST['tx_apMaterno']);
	$str_correo			=trim($_POST['tx_correo']);
	$str_username		=trim($_POST['tx_username']);
	$str_password		=trim($_POST['tx_password']);
	$str_password2	=trim($_POST['tx_password2']);
	$i_TipoUsuario	=trim($_POST['i_tipoUsuario']);

	//Devuelve true si la cadena que llega esta VACIA
	function estaEnBlanco($cadena) {
		if(strlen( trim($cadena) ) == 0 )
			return true;
		return false;
	}

	//Devuelve true si la longitud de la cadena (primer parametro)
	// que llega  es menor que el numero (segundo parametro)
	function validaTamanio($cadena,$longitud) {
		if(strlen( trim($cadena) ) < $longitud )
			return true;
		return false;
	}

	// devuelve true SI ha escrito, un email NO VALIDO
	function esCorreoInvalido($str_email) {
		if(!filter_var(trim($str_email), FILTER_SANITIZE_EMAIL))
			return true;
		return false;
	}

	// devuelve una cadena escapada de algunos caracteres que
	// pudieran servir para un ataque de sql injection
	function escaparQuery($cadena) {
		$str_KeywordsSQL 			= array("select ","insert ","delete ","update ","union ");
		$str_OperadoresSQL 		= array("like ","and ","or ","not ","<",">","<>","=","<");
		$str_DelimitadoresSQL = array(";","(",")","'");

		//Quitar palabras reservadas y operadores
		for($i=0; $i<count($str_KeywordsSQL); $i++) {
			$cadena = str_replace($str_KeywordsSQL[$i], "",strtolower($cadena) );
		}
		for($i=0; $i<count($str_OperadoresSQL); $i++) {
			$cadena = str_replace($str_OperadoresSQL[$i], "",strtolower($cadena) );
		}
		for($i=0; $i<count($str_DelimitadoresSQL); $i++) {
			$cadena = str_replace($str_DelimitadoresSQL[$i], "",strtolower($cadena) );
		}

		return $cadena;
	}


	$mensajesAll= "";

	//Mensajes para el nombre
	if( estaEnBlanco($str_nombre) )
		$mensajesAll = "<li>Por favor, escriba su Nombre.</li>";
	if( validaTamanio($str_nombre,3) )
		$mensajesAll .= "<li>Su Nombre como minimo debe tener 3 caracteres.</li>";
	//Mensajes para el Apellido Paterno
	if( estaEnBlanco($str_apPaterno) )
		$mensajesAll .= "<li>Por favor, escriba su Apellido Paterno.</li>";
	if( validaTamanio($str_apPaterno,3) )
		$mensajesAll .= "<li>Su Apellido Paterno como minimo debe tener 3 caracteres.</li>";
	//Mensajes para el Apellido Materno
	if( estaEnBlanco($str_apMaterno) )
		$mensajesAll .= "<li>Por favor, escriba su Apellido Materno.</li>";
	if( validaTamanio($str_apMaterno,3) )
		$mensajesAll .= "<li>Su Apellido Materno como minimo debe tener 3 caracteres.</li>";
	//Mensajes para el Correo electronico
	if( estaEnBlanco($str_correo) || validaTamanio($str_correo,5) || esCorreoInvalido($str_correo) )
		$mensajesAll .= "<li>Por favor, escriba una direccion de correo electronico valida.</li>";
	//Mensajes para el nombre de usuario
	if( estaEnBlanco($str_username) )
		$mensajesAll .= "<li>Por favor, escriba un nombre de usuario. Este dato le servira para iniciar sesion y ver el contenido.</li>";
	if( validaTamanio($str_username,5) )
		$mensajesAll .= "<li>Su nombre de usuario como minimo debe tener 5 caracteres.</li>";
	//Mensajes para el password
	if( estaEnBlanco($str_password) )
		$mensajesAll .= "<li>Por favor, escriba una contrase&ntilde;a.</li>";
	if( validaTamanio($str_password,5) )
		$mensajesAll .= "<li>Su contrase&ntilde;a como minimo debe tener 5 caracteres.</li>";
	//Mensajes para la confirmacion del password
	if( estaEnBlanco($str_password2) || validaTamanio($str_password2,5) )
		$mensajesAll .= "<li>Por favor, confirme la contrase&ntilde;a anterior.</li>";
	if( trim($str_password) != trim($str_password2) )
		$mensajesAll .= "<li>Por favor, repita la contrase&ntilde;a anterior.</li>";	
	//Mensajes para el tipo de usuario
	if( estaEnBlanco($i_TipoUsuario) )
		$mensajesAll .= "<li>Por favor, indique el tipo de usuaurio.</li>";

	$log = $mensajesAll."<br>";

	//Si se generaron mensajes de error al validar...
	if ( trim($mensajesAll) != "" )	{
		//..Redireccion a la pagina de registro para mostrar msg de error al usuario
		//Enviar los datos que habia escrito antes de enviar
	?>
	<form id="frm_error"   name="frm_error" method="post" action="registro.php">
		<input type="hidden" name="error" value="1" />
		<input type="hidden" name="msgs_error" value='<?php echo $mensajesAll ?>' />
		<input type="hidden" name="str_nombre" value='<?php echo $str_nombre ?>' />
		<input type="hidden" name="str_apPaterno" value='<?php echo $str_apPaterno ?>' />
		<input type="hidden" name="str_apMaterno" value='<?php echo $str_apMaterno ?>' />
		<input type="hidden" name="str_correo" value='<?php echo $str_correo ?>' />
		<input type="hidden" name="str_username" value='<?php echo $str_username ?>' />
		<input type="hidden" name="str_password" value='<?php echo $str_password ?>' />
		<input type="hidden" name="str_password2" value='<?php echo $str_password2 ?>' />
	</form>
	<script type="text/javascript">
		//Redireccionar con el formulario creado
		document.frm_error.submit();
	</script>
<?php
		exit;
	}
?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>.:: Registrar Usuario ::. </title>

	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<link rel="stylesheet" href="estilos.css" type="text/css">
	<script src="jquery171.js" type="text/javascript"></script>
	<script src="jquery.validate.js" type="text/javascript"></script>
	<script type="text/javascript" src="jquery.alerts.js"></script>
	<link href="jquery.alerts.css" rel="stylesheet" type="text/css" />

	<script type="text/javascript">
	<!--
		$().ready(function() {

		});
	// -->
	</script>

</head>
<body>

<?php
	$mensajesAll				= "";
	$username_duplicado = false;
	$email_duplicado 		= false;
	//Escapar las cadenas para avitar SQL Injection
	$str_username = escaparQuery($str_username);
	$str_correo 	= escaparQuery($str_correo);

	//Conectar la BD
	include("conectar_bd.php");
	conectar_bd();

	
	//Validar que el nombre de usuario no exista en la BD
	$sql = "SELECT  id_usuario	FROM tbl_users
	WHERE tx_username = '".trim($str_username)."';";
	$rs_sql	= mysql_query($sql);
	$log .=  $sql."<br>";
		
	//Si ya existe el usuario en la BD...
	if ( $fila 	= mysql_fetch_object($rs_sql) )	{
		$mensajesAll = "<li>El nombre de usuario <b>".$str_username."</b> ya fue registrado 
		por otra persona. Por favor, escriba otro.</li>";
		$username_duplicado = true;
	}

	//Validar que el email no exista en la BD
	$sql = "SELECT  id_usuario	FROM tbl_users
	WHERE tx_correo='".$str_correo."';";
	$rs_sql	= mysql_query($sql);
	$log .=  $sql."<br>";

	
	//Si ya existe el email en la BD...
	if ( $fila 	= mysql_fetch_object($rs_sql) )	{
		$mensajesAll = "<li>El correo electronico <b>".$str_correo."</b> ya fue registrado 
		por otra persona. Por favor, escriba otro.</li>";
		$email_duplicado 		= true;
	}
	//Si ambos datos ya estan en la Base de datos mostrar un solo msg
	if( $username_duplicado && $email_duplicado)
		$mensajesAll = "<li>Ambos, nombre de usuario <b>".$str_username."</b> 
		y correo electronico <b>".$str_correo."</b> ya fueron registrados por otra persona.
		Por favor, cambie esos datos.</li>";
	//..Redireccion a la pagina de registro para mostrar msg de error al usuario
	//Enviar los datos que habia escrito antes de enviar
	
	$log .=  $mensajesAll."<br>";

	
	if ( trim($mensajesAll) != "" )	{
		//..Redireccion a la pagina de registro para mostrar msg de error al usuario
		//Enviar los datos que habia escrito antes de enviar
		?>
		<form id="frm_error"   name="frm_error" method="post" action="registro.php">
			<input type="hidden" name="error" value="2" />
			<input type="hidden" name="msgs_error" value='<?php echo $mensajesAll ?>' />
			<input type="hidden" name="str_nombre" value='<?php echo $str_nombre ?>' />
			<input type="hidden" name="str_apPaterno" value='<?php echo $str_apPaterno ?>' />
			<input type="hidden" name="str_apMaterno" value='<?php echo $str_apMaterno ?>' />
			<input type="hidden" name="str_correo" value='<?php echo $str_correo ?>' />
			<input type="hidden" name="str_username" value='<?php echo $str_username ?>' />
			<input type="hidden" name="str_password" value='<?php echo $str_password ?>' />
			<input type="hidden" name="str_password2" value='<?php echo $str_password2 ?>' />
		</form>
		<script type="text/javascript">
			//Redireccionar con el formulario creado
			document.frm_error.submit();
		</script>
			<?php
		exit;
	}
	
	
	//..Si llega asta aqui es que todos los datos son validos, procedemos a darlo de alta en BD
	$str_elNombre 				= $str_nombre." ".$str_apPaterno;
	$str_elNombreCompleto = $str_nombre." ".$str_apPaterno." ".$str_apMaterno;

	
	//Formar el query para el insert del nuevo usuario
	$queryInsert="INSERT INTO tbl_users (
	tx_nombre,
	tx_apellidoPaterno,
	tx_apellidoMaterno,
	tx_correo,
	tx_username,
	tx_password,
	id_TipoUsuario,
	dt_registro	) 
	VALUES(
	'".$str_nombre."',
	'".$str_apPaterno."',
	'".$str_apMaterno."',
	'".$str_correo."',
	'".$str_username."',
	'".md5($str_password)."',
	".$i_TipoUsuario.",
'".date("Y-m-d H:i:s")."');";
	
	$log .=  $queryInsert."<br>";

	//echo $log;
	//exit;
	
	mysql_query($queryInsert);

	// Le  Envio  un correo electronico  de bienvenida
	$destinatario = $str_correo;					//A quien se envia
	$nomAdmin 			= 'Gonzalo Silverio';			//Quien envia
	$mailAdmin 		= 'gonzasilve@gmail.com';		//Mail de quien envia
	$urlAccessLogin = 'http://localhost/autenticar_usuarios';		//Url de la pantalla de login

	$elmensaje = "";
	$asunto = $str_elNombre.", Gracias por registrarte!";

	$cuerpomsg ='
	<h2>.::Registrar usuarios::.</h2>
	<p>Le damos la mas cordial bienvenida, desde ahora usted podra gozar de los beneficios de 
	haberse identificado y acceder a contenido exclusivo de esta comunidad.</p>
		<table border="0" >
		<tr>
			<td colspan="2" align="center" >Sus datos de acceso para <a href="'.$urlAccessLogin.'">'.$urlAccessLogin.'</a><br></td>
		</tr>
		<tr>
			<td> Nombre </td>
			<td> <b>'.$str_elNombreCompleto.'</b> </td>
		</tr>
		<tr>
			<td> Nombre de usuario </td>
			<td> <b>'.$str_username.'</b> </td>
		</tr>
		<tr>
			<td> Password </td>
			<td> <b>'.$str_password.'</b> </td>
		</tr>
		</table> <br/><br/>
	<p><b>Gracias por su preferencia, hasta pronto.</b></p> <br><br>';

	date_default_timezone_set('America/Mexico_City');

	//Establecer cabeceras para la funcion mail()
	//version MIME
	$cabeceras = "MIME-Version: 1.0\r\n";
	//Tipo de info
	$cabeceras .= "Content-type: text/html; charset=iso-8859-1\r\n";
	//direccion del remitente
	$cabeceras .= "From: ".$nomAdmin." <".$mailAdmin.">";
	$i_EmailEnviado = 0;
	
	//Si se envio el email
	if( mail($destinatario,$asunto,$cuerpomsg,$cabeceras) )	
		$i_EmailEnviado = 1;
	
	//Cerrrar conexion a la BD
	mysql_close($conexio);

	// Mostrar resultado del registro
	?>
	<form id="frm_registro_status"   name="frm_registro_status" method="post" action="index.php">
		<input type="hidden" name="status_registro" value="1" />
		<input type="hidden" name="i_EmailEnviado" value='<?php echo $i_EmailEnviado ?>' />
	</form>
	<script type="text/javascript">
		//Redireccionar con el formulario creado
		document.frm_registro_status.submit();
	</script>
</body>
</html>

Empezamos recogiendo en varibles locales a este archivo los datos que nos llegan del archivo registro.php, esto se hace de la linea 8 a l6. Despues definimos 4 funciones, las cuales mas adelante nos serviran para hacer validaciones con los datos que acabamos de recibir. Cada una tiene un breve explicación asi que me ahorrare volver a hacerlo.

De la linea 64 a 99 validamos que los datos que llegan no vengan vacios (en blanco), ademas para algunos campos como el username y password validamos su tamaño. Observa como para cada campo que pudiera venir vacio o no cumplir el tamaño se siguen revisando los demas pero se agrega un item <li> con la descripcion del error. En la linea 104 se revisa si la lista NO esta vacia, sino esta vacia entonces regresamos todos los datos al archivo registro.php, para que el usuario no tenga que volver a escribirlos y solo corrija los que tienen error, y ademas mandamos una variable llamada error y la lista de errores que ocurrieron (con su descripcion). Ademas de mandar los errores debemos detener la ejecucion de este archivo, esto se hace en la linea 124.

Supongamos que no hubo errores de campos en blanco ni tamaños, entonces no se cumplira la condicion de la linea 104, entonces, el interprete de PHP se saltara hasta la linea 126 y continuara su ejecucion…

Lo que haremos ahora sera validar que el nombre de usuario e email escrito no existan en la BD, si algunos de los dos ya fue registrado volveremos a direccionar la ejecucion al archivo registro.php para que escriba otro username/pasword. Esto se hace de la linea 151 a 231, el codigo esta comentado por lo tanto evitare redundar en la explicacion.

Tal y como dice la linea 224, si la ejecucion llega asta dicha linea es que todos los datos son validos (han pasado las validaciones), entonces procedemos a darlo de alta en la base de datos. Despues de formar la sentencia SQL (insert) de la linea 230 a 247, se ejecuta (linea 254) y con lo cual el usuario ha sido dado de alta. Observa como en varios puntos del script voi guardando un log de la ejecucion (errores, querys, etc) en una variable llamada $log puedes imprimirla y detener la ejecucion en cualquier momento para ver que pasa detras del telon, observa como lo hago yo en la linea 251 y 252.

Como un plus e puesto el codigo como se le pueden enviar sus datos de acceso en un email, si recuerdas ya vimos como enviar un email en PHP en otra entrada de blog. A continuación un pantallazo del email que le llega al usuario que se acaba de registrar:
Email con sus datos de acceso
 
 
Despues de enviarle el email con sus datos direccionamos al usuario al archivo index.php (recuerda que ahi dio click en el enlace Deseo registrarme) junto con una bandera; $status_registro si esta bandera llega con valor 1 significa que el registro fue exitoso. el archivo index.php ya esta preparado para revisar si le llega esta bandera (fijate en linea 99). Pantalla de aviso que ha sido registrado:

Aviso de registro exitoso

Por ultimo no hay que olvidarse de cerrar la conexion a la base de datos, esto lo hago en la linea 304 del archivo guardarRegistro.php.

Demo

Si deseas ver el ejemplo funcionando Da click aqui. usa estos datos para probar el ejemplo, Usuario: visitante_wp, Contraseña: 12345. Si te registras no olvides revisar el SPAM!.
 
 
Bueno, eso es todo. Como siempre, si quieres el codigo deja tu email y te lo envio a la brevedad.  Si te gusto el articulo ¿me regalas un like?. Saludos.

 
 

Clase java para recorrer y buscar registros de tabla (de Sql Server, Mysql o Postgres) con botones primero, anterior, siguiente y ultimo.

Clase java para recorrer y buscar registros de tabla de base de datos con botones primero, anterior, siguiente y ultimo. El objetivo de esta entrada de blog es mostrar una clase diseñada por mi para facilitar la navegacion por los registros de una tabla. Se me ocurrio esto debido a que en muchas ocasiones en los programas necesitamos recorrer los registros de una tabla con los tipicos botones:
Primero Permite ir al primer registro de la tabla.
Anterior Permite ir al anterior registro.
Siguiente Permite ir al siguiente registro.
Ultimo Permite ir al ultimo registro.

La siguiente imagen muestra un ejemplo clasico donde se requieren estos botones (los botones con flechas verdes):

Ventana con botones de navegacion de registros.
Ventana con botones de navegacion de registros.

Como se puede imaginar con ayuda de estos botones nos podemos colocar en cualquier registro de la tabla y una vez posicionados en el registro deseado se pueden usar otros botones para modificar o eliminar el registro. Bueno sin mas preambulos muestro el codigo de la clase:

GonzaBD.java
El truco de esta clase es almacenar en un array todos los campos llave de la tabla que se desee manipular (por cada tabla se debe crear un nuevo objeto de esta clase). Al llamar al metodo primero() con ayuda de una variable se accede al primer elemento del arreglo de llaves primarias. Al llamar al metodo ultimo() con ayuda de una variable se accede al ultimo elemento del arreglo de llaves primarias. Al llamar al metodo siguiente() con ayuda de una variable; si por ejemplo estamos en la fila 5, se accede al elemento 5 +1, del arreglo de llaves primarias. Despues se realiza un Select hacia la tabla y los datos quedan en un Objeto Resultset (llamado rs) que es local a esta clase, bueno a continuacion muestro el codigo:

/*
 *   Instituto Tecnologico de Zacatepec
 * Descripcion:  Clase que contiene metodos para recorrer los registros de una tabla 
 *						hacia el primer, anterior, siguiente o ultimo registro
 * Archivo: GonzaBD.java
 * author Gonzalo Silverio       gonzasilve@hotmail.com
 * fuente:  https://gonzasilve.wordpress.com
 */
import java.sql.*;


public class GonzaBD 
{
	String strSentenciaSQL = "";
	String strCadenaConexion = "";
	String strOrdenarPor = "";
	String strCampoLLave = "";
	String strTabla = "";
	String strArrayCamposLlave[];
	int intArrayCamposLlave[];
	
	//Los posibles tipos del campo llave son cadena y entero
	//Por defecto el campo llave es de tipo cadena
	String strTipoCampoLlave = "cadena";
	
	int intTotalRegistros = 0,intFilaActual = 0;	
	
	String strDriverMySQL 		="com.mysql.jdbc.Driver";
	String strDriverPostgres 	="org.postgresql.Driver";
	String strDriverSqlServer 	="net.sourceforge.jtds.jdbc.Driver";	
	
	String strManejador 		= "mysql";
	String strBaseDatos 		= "BD";
	String strServidor 		= "localhost";
	String strUsuario 		= "usuario";
	String strPassword		= "password";
	String strControlador 	= strDriverMySQL;
	String strPuerto			= "3306";
	
	private static Connection con = null;
	Statement st;
	ResultSet rs;
	
    public GonzaBD()
    {
    	
    }
    
    //se mueve a la primera fila y devuelve true si se pudo, false sino se pudo ir a la primera fila
    public  boolean  primero()
    {
      try
		{
			intFilaActual = 0;
			if( strTipoCampoLlave.equals("cadena") )
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"='"+strArrayCamposLlave[intFilaActual]+"'");
			else
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"="+intArrayCamposLlave[intFilaActual]);
				
			if( rs.next() )
				return true;
			
			return false;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }
    
    //se mueve a la anterior fila y devuelve true si se pudo, false sino se pudo ir a la anterior fila
    public  boolean  anterior()
    {
      try
		{
			intFilaActual--;
			if(intFilaActual<0)
				intFilaActual=0;
				
			if( strTipoCampoLlave.equals("cadena") )
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"='"+strArrayCamposLlave[intFilaActual]+"'");
			else
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"="+intArrayCamposLlave[intFilaActual]);
				
			if( rs.next() )
				return true;
			
			return false;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }
    
    //se mueve a la siguiente fila y devuelve true si se pudo, false sino se pudo ir a la siguiente fila
    public  boolean  siguiente()
    {
      try
		{
			intFilaActual++;
			if(intFilaActual>intTotalRegistros-1)
				intFilaActual=intTotalRegistros-1;

			if( strTipoCampoLlave.equals("cadena") )
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"='"+strArrayCamposLlave[intFilaActual]+"'");
			else
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"="+intArrayCamposLlave[intFilaActual]);
				
			if( rs.next() )
				return true;
			
			return false;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }
    
    //se mueve a la ultima fila y devuelve true si se pudo, false sino se pudo ir a la ultima fila
    public  boolean  ultimo()
    {
      try
		{
			intFilaActual = intTotalRegistros-1;

			if( strTipoCampoLlave.equals("cadena") )
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"='"+strArrayCamposLlave[intFilaActual]+"'");
			else
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"="+intArrayCamposLlave[intFilaActual]);
				
			if( rs.next() )
				return true;
			
			return false;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }
	 
	//Obtiene el controlador del manejador mysql o postgres
    public  String obtenerDriverManejador(String manejador)
    {
		if(manejador.equals("sqlserver"))							//Si el manejador es sql server
			return strDriverSqlServer;
		else if(manejador.equals("mysql"))							//Si el manejador es mysql
			return strDriverMySQL;
		else if(manejador.equals("postgres"))							//Si el manejador es postgres
			return strDriverPostgres;

			//en caso d k no sea ninguno devuelve el de MySQL			
			return strDriverMySQL;
    }
  	
	//Conecta a la BD con los datos por default
    public boolean conectarBD() throws SQLException
    {    
      try
		{
			return conectarServidor(strManejador,strServidor,strUsuario,strPassword,strBaseDatos,strControlador);
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }
    

	//Conecta a la BD con los datos del usuario, bd y password especificados, para los demas toma los k estan por default
    public boolean conectarBD(String usuario, String password, String BD )// throws SQLException
    {
    	boolean ress;
      try
		{
			strUsuario 		= usuario;
			strPassword 	= password;
			strBaseDatos 	= BD;
			ress = conectarServidor(strManejador,strServidor,usuario,password,BD,strControlador);
			return ress;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }
    
    //permite especificar el campo por el que se van a ordenar los registros
    public  void ordenarPor(String campo)
    {
    	strOrdenarPor = campo;
    }
    
	//Conecta a la BD con los datos especificados, para los demas toma los k estan por default
    public boolean conectarBD(String usuario, String password, String BD, String manejador) //throws SQLException
    {
    	boolean ress;
      try
		{
			strControlador = obtenerDriverManejador(manejador);			
			strUsuario 		= usuario;
			strPassword 	= password;
			strBaseDatos 	= BD;
			strManejador 	= manejador;
			ress = conectarServidor(manejador,strServidor,usuario,password,BD,strControlador);
			return ress;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }
    
	//Realiza una conexion a sqlserver, mysql o postgres con los datos especificados
    public boolean conectarServidor(String manejador,String servidor,String usuario,String pw,String bd, String driver) throws SQLException
    {
		if(manejador.equals("sqlserver"))							//Si el manejador es sql server
		{
		    try
		    {
		        Class.forName(driver);
		        strCadenaConexion = "jdbc:jtds:sqlserver://"+servidor+"/"+bd+";instance=SQLSERVEREXPRESS;";
		        con = DriverManager.getConnection(strCadenaConexion,usuario,pw);
		        if (con == null )
		    			return false;
		        return true;
		    }
		    catch(SQLException sqlex)
		    {
		    		sqlex.printStackTrace();
		        	return false;
		    }
		    catch(Exception e)
		    {
		    		e.printStackTrace();
		        	return false;
		    }
		}            
    	else if(manejador.equals("mysql"))									//Si el manejador es mysql
    	{
           try
           {
		          Class.forName(driver);
		          strCadenaConexion = "jdbc:mysql://"+servidor+"/"+bd;
		          con = DriverManager.getConnection(strCadenaConexion,usuario,pw);
		          if (con == null )		          	
		          	return false;
		          
		          return true;
            }
            catch(SQLException sqlex)
            {
            	sqlex.printStackTrace();
                return false;
            }
            catch(Exception e)
            {
            	e.printStackTrace();
            	return false;
            }
    	}
    	else if(manejador.equals("postgres"))							//Si el manejador es postgress
      {
          try
          {
              Class.forName(driver);
              strCadenaConexion = "jdbc:postgresql://"+servidor+":5432/"+bd;
              con = DriverManager.getConnection(strCadenaConexion,usuario,pw);
              if (con == null )
          			return false;

              return true;
          }
          catch(SQLException sqlex)
          {

          		sqlex.printStackTrace();
              	return false;
          }
          catch(Exception e)
          {
          	e.printStackTrace();
              return false;
          }
      }

	    	return false;
    }
    
	//Ejecuta un SELECT y devuelve el Resultset con los resultados
	public ResultSet ejecutarConsulta(String cadSQ) throws SQLException
	{
		rs = null;
		if( ! strOrdenarPor.equals("") )
			cadSQ += " ORDER BY " +strOrdenarPor;
			
		try
		{
			rs = st.executeQuery(cadSQ);
			return rs;
       }
       catch(SQLException sqlex)
       {
       		sqlex.printStackTrace();
       		return rs;
       }

	}

	public  void obtenerCamposLlave()
	{
		obtenerCamposLlave(strTabla);
	}
	

	//Si el campo llave es de tipo entero guarda las llaves primarias en un arreglo de enteros
	//Si el campo llave es de tipo cadena guarda las llaves primarias en un arreglo de Strings
	public  void obtenerCamposLlave(String tabla)
	{
		int c=0;
		try
		{
			rs = ejecutarConsulta("SELECT * FROM " + tabla);
			while(rs.next())
				c++;
			intTotalRegistros = c;
			strArrayCamposLlave = new String[intTotalRegistros];
			intArrayCamposLlave = new int[intTotalRegistros];
			
			cerrar(rs);		//Cerrar consulta anterior
			//Ejecutar nuevamente la consulta
			rs = ejecutarConsulta("SELECT * FROM " + tabla);
			rs.next();		//Moverse al primer registro
			
			c=0;
			do
			{			//determina el tipo del campo llave y en base a eso guarda en el array correspondiente
				if( strTipoCampoLlave.equals("cadena") )				
					strArrayCamposLlave[c] = rs.getString(strCampoLLave);
				else
					intArrayCamposLlave[c] = rs.getInt(strCampoLLave);
					
				c++;
			}while( rs.next() );
			
		}
		catch(SQLException sqlex)
		{
       	sqlex.printStackTrace();
		}
		
	}

	
	// Cierra un objeto Resultset
	public static void cerrar(ResultSet rs)
	{	
		try
		{
			rs.close();
		} 
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}
	
	// cierra un objeto Statemet
	public static void cerrar(Statement st)
	{
		try
		{
			st.close();
		} 
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}

	// Cierra un objeto Connection
	public static void cerrar(Connection con)
	{	
		try
		{
			con.close();
		} 
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}
	
	//Permite especificar cual es el campo llave de la tabla
	public  void setCampoLlave(String campo)
	{
		strCampoLLave = campo;
	}
	
	//Permite especificar cual es el campo llave y su tipo, de la tabla
	public  void setCampoLlave(String campo, String tipo)
	{
		strCampoLLave = campo;
		strTipoCampoLlave = tipo;
	}
	
	public void setTipoCampoLlave(String tipo)
	{
		strTipoCampoLlave = tipo;
	}
	
	//Especifica la tabla sobre la k se va a trabajar
	public  void setTabla(String tabla)
	{
		try
		{
			strTabla = tabla;
			st=con.createStatement();
		}
		catch(SQLException ex)
		{
			ex.printStackTrace();
		}

	}	
}	//Fin de la clase

Lo interesante de esta clase es que esta preparada para recorrrer los registros de tablas que esten creadas en cualquera de los manejadores SQL Server, MySQL o de Postgres, obviamente que los .jar de los JConnector de dichos DBMS deben estar copiados en C:\Program Files\Java\jdk1.6.0_23\jre\lib\ext, Lo que esta en negrita lo e resaltado debido a que la version del JVM puede cambiar segun la que tengas instalada. Los JConnector que e usado para probar esta clase son los siguientes (puedes dar click en el enlace para descargarlo sino lo tienes).
JConnector de SQL Server: jtds-1.2.5.jar
JConnector de Postgres: postgresql-9.1-901.jdbc4.jar
JConnector de MySQL: mysql-connector-java-5.1.18-bin.jar

Para ejemplificar el uso de la clase anterior e usado una tabla que esta en SQL Server. Los parametros de conexion son:
Manejador de Base de datos (DBMS): SQL Server 2005 Express
Base de datos: prueba
Tabla: tbl_alumnos
Usuario: sa
Password: 123456
El Script para crear la tabla alumnos en SQL Server es el siguiente (generado con el Microsoft SQL Server Management Studio):

USE [prueba]
GO
/****** Object:  Table [dbo].[tbl_alumnos]    Script Date: 12/28/2011 17:59:51 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[tbl_alumnos](
	[matricula] [int] NOT NULL,
	[nombre] [varchar](50) NULL,
	[apellidos] [varchar](100) NULL,
	[edad] [int] NULL,
	[peso] [decimal](10, 2) NULL,
	[sexo] [char](1) NULL,
 CONSTRAINT [PK__tbl_alumnos__6FBF826D] PRIMARY KEY CLUSTERED
(
	[matricula] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF

La imagen de la tabla ya creada en SQL Server se ve asi:

Tabla Alumnos en SQL Server

DIAGRAMA UML DE LA CLASE gonzaBD

Diagrama UML de la clase gonzaBD

Diagrama UML de la clase gonzaBD

BREVE EXPLICACION DE LOS ATRIBUTOS DE LA CLASE gonzaBD:

Atributo Descripcion
intfilaActual Contiene un número que se usa como índice para acceder a una llave primaria dentro del arreglo strArrayCamposLlave o el arreglo strArrayCamposLlave (dependiendo de si la llave primaria es de tipo cadena o tipo entero, respectivamente). Este atributo contiene el número actual de fila-1.
strArrayCamposLlave[] Arreglo que contiene las llaves primarias de la tabla en caso de que el tipo de dato del campo llave sea Cadena.
intArrayCamposLlave[] Arreglo que contiene las llaves primarias de la tabla en caso de que el tipo de dato del campo llave sea Entero.
rs Contiene los datos de la fila actual mostrandose. Cada vez que se manda a llamar al método primero(), anterior(), siguiente() o ultimo() se realiza una consulta y este atributo (tipo Resultset) se actualiza con los campos de la nueva fila.

COMO SE USA LA CLASE gonzaBD
A continuacion voi a poner un fragmento de codigo con la intencion mostrar los pasos a realizar para usar correctamente la clase.

//Crear un objeto de esta clase
GonzaBD a = new GonzaBD();
//AHORA SE DEBE REALIZAR LO SIGUIENTE EN EL MISMO ORDEN…
//Primeramente se debe indicar especificar cual es la llave primaria de la tabla y su tipo
a.setCampoLlave("matricula","entero");
//Se de desea se puede indicar que si se desean ordenar los registros de la tabla por un campo, //este paso es opcional en todo caso sino se realiza, no se ordenan por ningún campo
a.ordenarPor("nombre");
//A continuación usamos un metodo sobrecargado para conectarse al DBMS, aquí es donde //indicamos a que manejador se debe accesar
a.conectarBD("sa","12345","pruebas","sqlserver");
//Una vez que ya estamos conectados se debe especificar la tabla que se va a manipular
a.setTabla("tbl_alumnos");
//Ahora se manda a llamar al método que rellena el arreglo de llaves primarias dentro de la clase; //dependiendo del tipo de dato del campo llave se rellena el arreglo de Strings o el arreglo de //enteros.
a.obtenerCamposLlave();
//Ahora ya se puede llamar a cualquiera de los métodos primero(), anterior(), siguiente() o ultimo()...

Despues de realizar lo anterior, para que el objeto rs se rellene con los datos de la primera fila se invoca al metodo:
a.primero();
Después de que se invoco ese metodo, el atributo rs de la clase gonzaBD se quedara con los datos de la fila 1. Supongamos que la tabla “alumnos”contiene las siguientes filas, rs apuntara a la fila:

El atributo rs esta en la posicion de la primera fila.

El atributo rs esta en la posicion de la primera fila.

Si inmediatamente despues se llama al método siguiente()
a.siguiente();
El atributo rs apuntara al siguiente registro despues del primero, es decir rs apuntara a la fila:

El atributo rs apunta a los datos de la segunda fila

El atributo rs apunta a los datos de la segunda fila

Y asi sucesivamente, una observación: si te fijas en el codigo de los metodos (siguiente() y anterior()) cuando se ha llegado a la ultima fila, es decir, si rs apunta al registro 4 y se ejecuta una llamada al método siguiente() (se intenta accesar una fila después de la ultima); dicho método contiene un ‘candado’ para detectar eso y siempre dejara a rs apuntando al ultimo registro. El método anterior() igualmente tiene esa precaucion y siempre que se intente accesar a un registro antes del primero automáticamente moverá a rs para que apunte a la primera fila. De esta manera no es posible sobrepasar los limites (inferior ni superior) de filas de la tabla que se este manipulando.

Finalmente Para ilustrar el uso de la clase gonzaBD anterior he creado una ventana muy basica.

JfrPrincipal.java
Esta clase crea una ventana de formulario con 6 campos y los 4 botones; primero, anterior, siguiente y ultimo en la parte inferior de dicha ventana. Es la misma clase que utilice para ilustrar como usar ventanas de formulario en Java, pero la he modificado con algunos campos mas. Bueno ahora muestro el codigo:

/*
 *   Instituto Tecnologico de Zacatepec
 * Descripcion:  Clase que crea una GUI para ilustrar el uso de la clase GonzaBD
 * Archivo: JfrPrincipal.java
 * author: Gonzalo Silverio       gonzasilve@hotmail.com
 * fuente:  https://gonzasilve.wordpress.com
 */

import javax.swing.*;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

//Se usara para cambiar los Margenes de los botones
import java.awt.Insets;

//Para Manejo de BD
import java.sql.*;

public class JfrPrincipal extends JFrame
{
	//Campos de texto y sus etiquetas 
	JLabel jlbMatricula;    JTextField  jtfMatricula;
	JLabel jlbNombre;       JTextField  jtfNombre;
	JLabel jlbApellidos;    JTextField  jtfApellidos;
	JLabel jlbEdad;         JTextField  jtfEdad;
	JLabel jlbPeso;         JTextField  jtfPeso;
	JLabel jlbSexo;         JComboBox   jcbSexo;
	
	//Botones de navegacion de los registros
	JButton btnPrimero;
	JButton btnAnterior;
	JButton btnSiguiente;
	JButton btnUltimo;
	
	Box boxVCamposVentana;   //Contiene todo los campos de texto (con su respectiva etiqueta)
	JPanel panBotones;      //Contiene los botones Guardar y Cancelar
	
	//Objeto de la clase que nos ayuda a navegar por los registros de la tabla
	GonzaBD bd = new GonzaBD();
	
	JfrPrincipal(String strTitulo, int intAncho, int intAlto)
	{
		super(strTitulo);
		this.setSize(intAncho, intAlto);
		this.setResizable(false);		//Ventana no redimensionable
		this.setLocationRelativeTo(null);       //Centrar ventana en pantalla
		
		//Box vertical por que los botones van a estar abajo
		Box boxVContenidoVerticalVentana = Box.createVerticalBox();
		crearCamposVentana();
		crearBotones();
		//Espacio del borde superior de la ventana al primer Campo
		boxVContenidoVerticalVentana.add(Box.createVerticalStrut(30));
		boxVContenidoVerticalVentana.add(boxVCamposVentana);
		//Espacio entre el ultimo campo (sexo) y los botones Guardar y Cancelar
		boxVContenidoVerticalVentana.add(Box.createVerticalStrut(20));
		boxVContenidoVerticalVentana.add(panBotones);
		
		this.add(boxVContenidoVerticalVentana);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	  
	  //Conecta la Base de datos
		conectarBD();
		bd.primero();		//Posicionarse en el primer registro
		rellenarCampos();		//Rellenar los campos con los datos del primer registro
		
		//ASIGNAR UN ESCUCHADOR PARA CADA BOTON DE NAVEGACION
		//Boton Primero
		btnPrimero.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent evt) 
			{
				bd.primero();
				rellenarCampos();
			}
		});
		//Boton Anterior
		btnAnterior.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent evt) 
			{
				bd.anterior();
				rellenarCampos();
			}
		});
		//Boton Siguiente
		btnSiguiente.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent evt) 
			{
				bd.siguiente();
				rellenarCampos();
			}
		});
		//Boton Ultimo
		btnUltimo.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent evt) 
			{
				bd.ultimo();
				rellenarCampos();
			}
		});
		  	
        	
	}		//Fin del constructor

	//Crea los campos de la ventana (cada caja tiene su correspondiente etiqueta)
    private void crearCamposVentana()
    {
        Box boxHMatricula =  Box.createHorizontalBox();        
        jlbMatricula = new JLabel("Matricula ");   jtfMatricula = new JTextField(15);
        boxHMatricula.add(Box.createHorizontalStrut(20));
        boxHMatricula.add(jlbMatricula);
        boxHMatricula.add(Box.createHorizontalStrut(14));
        boxHMatricula.add(jtfMatricula);
        JPanel panMatricula =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panMatricula.add(boxHMatricula);

        Box boxHNombre =  Box.createHorizontalBox();
        jlbNombre = new JLabel("Nombre ");   jtfNombre = new JTextField(15);
        boxHNombre.add(Box.createHorizontalStrut(20));
        boxHNombre.add(jlbNombre);
        boxHNombre.add(Box.createHorizontalStrut(20));
        boxHNombre.add(jtfNombre);
        JPanel panNombre =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panNombre.add(boxHNombre);

        Box boxHApellidos =  Box.createHorizontalBox();
        jlbApellidos = new JLabel("Apellidos ");   jtfApellidos = new JTextField(15);
        boxHApellidos.add(Box.createHorizontalStrut(20));
        boxHApellidos.add(jlbApellidos);
        boxHApellidos.add(Box.createHorizontalStrut(11));
        boxHApellidos.add(jtfApellidos);
        JPanel panApellidos =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panApellidos.add(boxHApellidos);

        Box boxHEdad =  Box.createHorizontalBox();
        jlbEdad = new JLabel("Edad ");   jtfEdad = new JTextField(15);
        boxHEdad.add(Box.createHorizontalStrut(20));
        boxHEdad.add(jlbEdad);
        boxHEdad.add(Box.createHorizontalStrut(40));
        boxHEdad.add(jtfEdad);
        JPanel panEdad =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panEdad.add(boxHEdad);
        
        Box boxHPeso =  Box.createHorizontalBox();
        jlbPeso = new JLabel("Peso ");   jtfPeso = new JTextField(15);
        boxHPeso.add(Box.createHorizontalStrut(20));
        boxHPeso.add(jlbPeso);
        boxHPeso.add(Box.createHorizontalStrut(40));
        boxHPeso.add(jtfPeso);
        JPanel panPeso =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panPeso.add(boxHPeso);

        Box boxHSexo =  Box.createHorizontalBox();
        jlbSexo = new JLabel("Sexo ");   jcbSexo = new JComboBox();
        jcbSexo.addItem("Masculino");
        jcbSexo.addItem("Femenino");
        boxHSexo.add(Box.createHorizontalStrut(20));
        boxHSexo.add(jlbSexo);
        boxHSexo.add(Box.createHorizontalStrut(40));
        boxHSexo.add(jcbSexo);
        JPanel panSexo =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panSexo.add(boxHSexo);

        boxVCamposVentana = Box.createVerticalBox();
        boxVCamposVentana.add(panMatricula);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panNombre);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panApellidos);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panEdad);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panPeso);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panSexo);
    }

    private void crearBotones()
    {
        Box boxHBotones = Box.createHorizontalBox();
        
        btnPrimero = new JButton("|< Primero");
        btnAnterior = new JButton("< Anterior");
        btnSiguiente = new JButton("Siguiente >");
        btnUltimo = new JButton("Ultimo >|");
        //Cambiar los margenes de los botones
        			//Insets(margen_sup, margen_izq, margen_inf, margen_der)
        btnPrimero.setMargin(new Insets(0, 2, 0, 2));
        btnAnterior.setMargin(new Insets(0, 2, 0, 2));
        btnSiguiente.setMargin(new Insets(0, 2, 0, 2));
        btnUltimo.setMargin(new Insets(0, 2, 0, 2));
        
        boxHBotones.add(btnPrimero);
        boxHBotones.add(Box.createHorizontalStrut(20));
        boxHBotones.add(btnAnterior);
        boxHBotones.add(Box.createHorizontalStrut(20));
        boxHBotones.add(btnSiguiente);
        boxHBotones.add(Box.createHorizontalStrut(20));
        boxHBotones.add(btnUltimo);
        
        panBotones =  new JPanel(new FlowLayout(FlowLayout.CENTER) );
        panBotones.add(boxHBotones);
    }
	//Conecta con la BD y devuelve true si se conecto correctamente
	//false en cualquiero otro caso
	public boolean conectarBD()
	{
		// Especificar cual es la llave primaria de la tabla y su tipo
		bd.setCampoLlave("matricula","entero");
    	bd.ordenarPor("nombre");	//Ordena los registros de la tabla por este campo
		
		//Conecta con el usuario, pass, BD y dbms (manejador) especificados
		bd.conectarBD("sa","12345","pruebas","sqlserver");
		
    	//especifica la tabla sobre la que se va a manipular
    	bd.setTabla("tbl_alumnos");
    	//Dentro del objeto bd rellena un arreglo con las llaves 
    	//primarias de la tabla que se esta manipulando
		bd.obtenerCamposLlave();
		
		return true;
	}
	
	//Rellena los campos de texto con los datos del registro actual
    public void rellenarCampos()
    {
		try
		{
    		jtfMatricula.setText(aCadena(bd.rs.getInt("matricula")));
    		jtfNombre.setText(bd.rs.getString("nombre").trim ());
    		jtfApellidos.setText(bd.rs.getString("apellidos").trim ());
    		jtfEdad.setText(aCadena(bd.rs.getInt("edad")));
    		jtfPeso.setText(aCadena(bd.rs.getFloat("peso")));
    		jcbSexo.setSelectedItem( bd.rs.getString("sexo").equals("f") ? "Femenino" : "Masculino" );
    		
    		this.setTitle("Alumno "+(bd.intFilaActual+1)+" de "+bd.intTotalRegistros);
		}
		catch( SQLException ex )
		{
			ex.printStackTrace();
		}
    }
    
    //Recibe un numero entero y lo devuelve como Cadena (String)
    private String aCadena(int num)
    {
    	return String.valueOf(num);
    }
    
    //Recibe un numero decimal y lo devuelve como Cadena (String)
    private String aCadena(float num)
    {
    	return String.valueOf(num);
    }
    
    private void mostrar()
    {
        this.setVisible(true);
    }

    public static void main(String args[])
    {
        JfrPrincipal prueba1 = new JfrPrincipal("Recorrer registros de SQL Server en Java",400,400);
        prueba1.mostrar();
    }
}

Y aqui una imagen de la ejecucion:

Ejecucion del ejemplo: Mostrando la tabla alumnos

Ejecucion del ejemplo: Mostrando la tabla alumnos

A diferencia de la otra entrada de blog anterior a esta, ahora se pueden realizar busquedas e igualmente se pueden recorrer los resultados con ayuda de la misma clase. La busqueda se puede realizar por matricula, nombre o por genero (sexo). Por ejemplo en caso de que decidamos buscar en los nombres de los alumnos la cadena ‘ar’, debemos marcar el radio nombre, escribir en la cajita ‘ar’ y dar clic en el boton Buscar en este caso se encontraron 4 resultados, como se muestra en la siguiente imagen:

Buscando por nombre a un alumno

Buscando por nombre a un alumno

Observa como automaticamente se desactivan los controles de busqueda y se muestran los resultados; los cuales tambien se pueden recorrer con los mismos botones de Primero, Anterior, Siguiente y Ultimo. Ademas el texto del boton Buscar cambia y ahora ese boton permite terminar la Busqueda. Al dar click en el boton Fin Busqueda se muestran nuevamente todos los alumnos de la tabla y se despliega el que estaba mostrandose antes de hacer la busqueda. Por ultimo muestro otro pantallazo de una busqueda por Sexo:

Buscando alumnos por sexo

Buscando alumnos por sexo

Como decia anteriormente lo interesante es que si ahora deseamos que la tabla alumnos este creada en MySQL o Postgres, entonces la creamos en dicho manejador (con ayuda del script que puse mas arriba; estan los nombres de los campos y su tipo) y en la linea 402 de la clase JfrPrincipal.java, cambiamos los parametros de Conexion (usuario,pass,bd, manejador) de dicho manejador, la clase automaticamente usara el Driver adecuado y se conectara a dicho DBMS sin problemas.

Sin querer se hizo un poco largo este ejemplo, pero no era para mas, espero haber sido lo suficiente explicito y no haber dejado muchas dudas, los ya avanzados en Java supongo que mi codigo lo habran digerido sin problemas y los que empiezan de todas maneras pregunten sin compromiso, les aseguro que yo tambien soy un novato y seguro hay alguna manera mas fina y elegante de hacer esto del recorrido de registros, solo es una idea. . Y es que a la clase GonzaBD.java la simplifique y le quite mucho codigo para que quedara simple y sencilla de entender ya que mi version original tiene muchos mas metodos para realizar las cuatro Operaciones SQL de manera mas simple (INSERT, DELETE, UPDATE, SELECT), pero me reservo el codigo y posiblemente mas adelante lo libere en este mismo blog, por ahora creo que seria demasiado y requeria mas tiempo para explicarlo y estoy muy ocupado estod dias.

Bueno no me queda mas que decir hasta pronto y si a alguien le interesan los fuentes basta con pedirlos y se los envio, hasta pronto y gracias x visitar.

Como generar un PDF con datos de una tabla MySQL con ayuda de iText

Ejemplo muy sencillo donde se ilustra como generar un documento PDF con datos provenientes de una tabla creada en MySQL con la libreria iText. Bueno creo que el titulo de la entrada lo dice todo asi que no quiero ser redundante en el objetivo de esta practica de programacion.

El ejemplo consta de 3 archivos: CrearConexion.java, GenerarPDFEmpleados.java JfrPrincipal.java (a decir verdad tambien se usa una imagen (logo de mysql), pero puedes cambiarla por otra que quieras). Como en casi todos mis ejemplos, no voi a dar mucha explicacion debido a que mi objetivo es tener disponible el ejemplo de codigo. Primero que nada te muestro un diagrama para que veas en forma grafica y rapida la estructura del ejemplo:

Diagrama que muestra en forma grafica el ejemplo

Diagrama que muestra en forma grafica el ejemplo

A continuacion se explican brevemente los tres archivos de codigo a grandes rasgos:

JfrPrincipal
Clase que crea una interfaz grafica de usuario muy sencilla; la cual es una ventana con 2 JLabels, un JTextField y un JButton. Desde esta clase se hace una instancia de la clase GenerarPDFEmpleados.java, la cual es la que realmente genera el PDF con ayuda de la libreria iText. En el codigo se muestran los comentarios correspondiente explicando casi todo…

/*
		Instituto Tecnologico de Zacatepec, Mor.
Descripcion:  Clase que crea una ventana con un boton que al darle clic
					genera el PDF de una tabla de MySQL.
Autor:  			Gonzalo Silverio   gonzasilve@gmail.com
Archivo: 		JfrPrincipal.java
*/

import javax.swing.*;
import java.awt.FlowLayout;
import java.awt.event.*;

public class JfrPrincipal extends JFrame
{
	String strTituloPDF = "INSTItuTO TEcnologico de zacatepec";
	String strNombrePDF = "pdf_tabla_Empleados.pdf";
	JTextField jtfNombrePDF;
	
	//Constructor
	JfrPrincipal(String titulo, int ancho, int alto)
	{
		//Establecer titulo, tamanio y posicion en la pantalla
		super(titulo);
		setSize(ancho,alto);
		setLocationRelativeTo(null);	//centrado
		//Rotulo principal de la ventana
		JLabel lblTitulo = new JLabel("Generar un PDF desde Java");
		JPanel panTitulo = new JPanel(new FlowLayout(FlowLayout.CENTER));
		panTitulo.add(lblTitulo);
		
		//Crea campo de texto para especificar el nombre del PDF
		JLabel lblNombrePDF = new JLabel("Nombre del documento PDF");
		jtfNombrePDF = new JTextField(30);
		jtfNombrePDF.setText(strNombrePDF);
		jtfNombrePDF.setHorizontalAlignment (JTextField.CENTER);
		JPanel panNombrePDF = new JPanel(new FlowLayout(FlowLayout.CENTER));
      panNombrePDF.add(Box.createHorizontalStrut(15));
		panNombrePDF.add(lblNombrePDF);
		panNombrePDF.add(jtfNombrePDF);
		
		//Crear el boton nuevo
		JButton btnGenerarPDF = new JButton("Generar PDF");
		JPanel panGenerarPDF = new JPanel(new FlowLayout(FlowLayout.CENTER));
		panGenerarPDF.add(btnGenerarPDF);

		//Todos los componentes estan en un Box Vertical
		//la clase Box se usa para alinear los controles
		Box boxVertical = Box.createVerticalBox();
		boxVertical.add(Box.createVerticalStrut(50));
		boxVertical.add(panTitulo);
		boxVertical.add(panNombrePDF);
		boxVertical.add(Box.createVerticalStrut(10));
		boxVertical.add(panGenerarPDF);

		//Agregar el Box a la ventana
		add(boxVertical);
		setResizable(false);	//No maximizar ni cambiar tamanio
		//Al dar en la X terminar todo el programa
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    	// ########### ESCUCHADOR BOTON NUEVO   ##########
    	ActionListener escuchadorGenerarPDF = new ActionListener()
    	{
        	public void actionPerformed(ActionEvent evt)
        	{
        		strNombrePDF = jtfNombrePDF.getText();
            GenerarPDFEmpleados ejemplo = new GenerarPDFEmpleados(strTituloPDF,strNombrePDF);
       		//Preguntar al usuario si desea abrir el documento PDF
       		int respuesta = JOptionPane.showConfirmDialog(null,"Se ha generado el documento "+strNombrePDF+", ¿Desea abrirlo?","Pregunta",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE);
       		//Si la respuesta es SI, abrirlo
				if(respuesta == JOptionPane.YES_OPTION)
					ejemplo.abrirPDF ();
          
        	}
   	};
    	btnGenerarPDF.addActionListener(escuchadorGenerarPDF);

    	
	}	//Fin del constructor

	//hace visible la ventana	
	public void mostrar()
	{
		setVisible(true);
	}

	public static void main(String[] args) 
   {
		JfrPrincipal ejemplo = new JfrPrincipal("Ventana principal de Usuario",400,400);
		ejemplo.mostrar();
   }
}

Y a continuacion una imagen de la GUI que se genera:

GUI para el ejemplo

GUI para el ejemplo

El primer Jlabel es un rotulo para la ventana, el segundo Jlabel es una etiqueta para el JTextField con la cual se le indica al usuario que debe escribir el nombre del documento PDF (con extension), el JTextField es el campo donde el uuario debe escribir el nombre del PDF. El JButton al darle click; el usuario generara el documento PDF de una tabla llamada Empleados e inmediatamente se le preguntara si desea abrirlo, aca una imagen:

Pregunta al usuario si desea abrir el PDF

Pregunta al usuario si desea abrir el PDF


Si el usuario da click en el boton Si del mensaje llama al metodo abrirPDF() de un objeto de la clase GenerarPDFEmpleados.java el cual abrira en una nueva ventana el documento PDF dentro del cual se muestra el contenido de la tabla empleados, aca una imagen del PDF:
PDF generado con datos de tabla empleados creada en MySQL

PDF generado con datos de tabla empleados creada en MySQL

GenerarPDFEmpleados.java
En esta clase es donde se hace uso de la libreria iText para generar un documento PDF. El codigo de esta clase es el siguiente:


//		Instituto Tecnologico de Zacatepec
//  	Descripcion:  Programa que genera un archivo PDF con datos de una base de datos
//		en mySQL y con ayuda de la libreria iText
//  	Author: Gonzalo Silverio   gonzasilve@hotmail.com
//		Archivo: GenerarPDFEmpleados.java

import java.awt.Color;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;

import com.lowagie.text.Anchor;
import com.lowagie.text.BadElementException;
import com.lowagie.text.Cell;
import com.lowagie.text.Chapter;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.List;
import com.lowagie.text.ListItem;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Section;
import com.lowagie.text.Table;
import com.lowagie.text.Element;
import com.lowagie.text.PageSize;

import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfWriter;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfPTable;

import com.lowagie.text.Image;

import java.sql.*;

public class GenerarPDFEmpleados
{
	private String strNombreDelPDF;

	private  Font fuenteNegra10 = new Font(Font.TIMES_ROMAN, 10, Font.BOLD, Color.BLACK);
	private  Font fuente8 = new Font(Font.TIMES_ROMAN, 8, Font.NORMAL, Color.BLACK);
	private  Font fuenteAzul25 = new Font(Font.TIMES_ROMAN, 25, Font.BOLD, Color.BLUE);

	Color grisClaro = new Color( 230,230,230);	
	Color azulClaro = new Color( 124,195,255 );

	//############# VARIABLES PARA MANEJO DE BASE DE DATOS ########################
	//Guarda la consulta operacion a realizar
	String strConsultaSQL;
	//Apuntador a la conexion
	Connection conn = null;	
	//Para ejecutar operaciones SQL
	Statement estSQL1;
	//Para guardar los resultados de una operacion SELECT
	ResultSet rs;
	Document document;
	PdfWriter writer;
	String strRotuloPDF;
	
	//Metodo principal del ejemplo
	public GenerarPDFEmpleados(String titulo, String nomPDF)
	{
		strRotuloPDF = titulo;
		strNombreDelPDF = nomPDF;
		try 
		{		//Hoja tamanio carta, rotarla (cambiar a horizontal)
			document = new Document( PageSize.LETTER.rotate() );
			
			writer = PdfWriter.getInstance(
			// that listens to the document
					document,
					// direccionar el PDF-stream a un archivo
					new FileOutputStream(strNombreDelPDF));
			document.open();

			agregarMetaDatos(document);
			agregarContenido(document);
			
			document.close();
			
			System.out.println("Se ha generado el PDF: "+ strNombreDelPDF);
				
		} catch (Exception e) 
		{
			e.printStackTrace();
		}
	}
	
	//agrega el contenido del documento; para este ejemplo agrega una tabla con datos y una imagen
	//Espera como entrada el documento donde agregara el contenido
	private void agregarContenido(Document document) throws DocumentException
	{
		Paragraph ParrafoHoja = new Paragraph();
				
		// Agregamos una linea en blanco al principio del documento
		agregarLineasEnBlanco(ParrafoHoja, 1);
		// Colocar un encabezado (en mayusculas)
		ParrafoHoja.add(new Paragraph(strRotuloPDF.toUpperCase (), fuenteAzul25) );
		agregarLineasEnBlanco(ParrafoHoja, 1);
		// 1.- AGREGAMOS LA TABLA
		agregarTabla(ParrafoHoja);
		//Agregar 2 lineas en blanco
		agregarLineasEnBlanco(ParrafoHoja, 2);
		// 2.- AGREGAMOS LA IMAGEN
		try
		{
			Image im = Image.getInstance("logo_mysql.gif");
			im.setAlignment(Image.ALIGN_CENTER | Image.TEXTWRAP );
			im.setWidthPercentage (50);
	      ParrafoHoja.add(im);
		}
		catch(Exception e)
		{
			e.printStackTrace ();
		}
		
		document.add(ParrafoHoja);

	}

	//Se conecta al DBMS MySQL , obtiene los datos de la tabla (SELECT) y los acomoda en una tabla JTable de iText.
	// Espera como entrada el parrafo donde agregara la tabla
	private void agregarTabla(Paragraph parrafo) throws BadElementException 
	{
		//Anchos de las columnas
		float anchosFilas[] = { 0.2f,1f,1f,0.5f,0.5f,0.3f,1f,1.5f,0.7f };
		PdfPTable tabla = new PdfPTable(anchosFilas);
		String rotulosColumnas[] = {"id","Nombre","Apellidos","Sexo","Telefono","Edad","Correo","Direccion","Fecha\nContratacion"};
		// Porcentaje que ocupa a lo ancho de la pagina del PDF
		tabla.setWidthPercentage(100);
		//Alineacion horizontal centrada
		tabla.setHorizontalAlignment(Element.ALIGN_CENTER);
		//agregar celda que ocupa las 9 columnas de los rotulos
		PdfPCell cell = new PdfPCell(new Paragraph("Tabla: Empleados"));
		cell.setColspan(9);
		//Centrar contenido de celda
		cell.setHorizontalAlignment(Element.ALIGN_CENTER);
		//Color de fondo de la celda
		cell.setBackgroundColor (azulClaro);		
		tabla.addCell(cell);

    	try
    	{
			if ( ConectarBD() )
			{
				// Mostrar los rotulos de las columnas
				for(int i=0; i<rotulosColumnas.length; i++)
				{
					cell = new PdfPCell(new Paragraph(rotulosColumnas[i],fuenteNegra10));
					cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
					cell.setHorizontalAlignment(Element.ALIGN_CENTER);
					cell.setBackgroundColor (grisClaro);
					tabla.addCell(cell);
				}
				
				//Consultar la tabla empleados
				strConsultaSQL = "SELECT * FROM empleados";
				//ejecutar consulta
				rs = estSQL1.executeQuery(strConsultaSQL);

				//Iterar Mientras haya una fila siguiente
	   		while (rs.next())
	   		{			//Agregar 9 celdas
					cell = new PdfPCell(new Paragraph(String.valueOf(rs.getInt ("idEmpleado")),fuente8 ));
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(rs.getString("nombre"),fuente8));
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(rs.getString("apellidos"),fuente8));
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(rs.getString("sexo"),fuente8));
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(rs.getString("telefono"),fuente8));
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(String.valueOf(rs.getInt("edad")),fuente8) );
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(rs.getString("correo"),fuente8));
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(rs.getString("direccion"),fuente8));
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(rs.getDate("fechaContratacion").toString (),fuente8 ) );
					tabla.addCell(cell);
   			}
   			
	        	//Cerrar los objetos de manejo de BD
	        	CrearConexion.cerrar(rs);			//ResultSet
	        	CrearConexion.cerrar(estSQL1);	//Statement
	        	CrearConexion.cerrar(conn);		//Connection
			}		//Fin de if que comprueba si se pudo conectar
			
		}
		catch(Exception e) 
		{
	    	System.out.println("Excepcion al ejecutar CONSULTA!!!");
	    	//Mostrar la traza de la pila
	    	e.printStackTrace();
		}
		//Agregar la tabla con los datos al parrafo que nos llego como entrada
		parrafo.add(tabla);
	}  //Fin del metodo que crea la tabla

	//Agrega las lineas en blanco  especificadas a un parrafo especificado
	private static void agregarLineasEnBlanco(Paragraph parrafo, int nLineas) 
	{
		for (int i = 0; i < nLineas; i++) 
			parrafo.add(new Paragraph(" "));
	}
	
	//Agrega los metadatos del documento, los metadatos a asignar son
	//Titulo, Asunto, Palabras clave, Autor y el sw o org con el cual fue generado
	private static void agregarMetaDatos(Document document)
	{
		document.addTitle("Documento con datos de tabla MySQL");
		document.addSubject("Usando iText y MySQL");
		document.addKeywords("Java, PDF, iText");
		document.addAuthor("Gonzalo Silverio");
		document.addCreator("https://gonzasilve.wordpress.com");
	}

	//devuelve true en caso de que si se pudo conectar
	//devuelve false sino se logro conectar
	public boolean ConectarBD() throws Exception
	{
	    try
	    {		
	    		//Aqui se instancia a la otra clase --> CrearConexion.java	    		
	    		//y se le mandan en el constructor los datos de conexion
	     		CrearConexion con  = new CrearConexion("root","root","prueba");
	     		//Obtiene una referencia a la conexion abierta
	     		conn = con.getConnection();
	      	
	      	//Comprobar si hay una refencia valida
	      	if(conn!=null)
	      	{
					//Mostrar MSG al usuario de la conexion se ha establecido
					System.out.println("Conexion establecida");
	     			//Se prepara para ejecutar sentencias en la conexion recien abierta
	      		estSQL1 = conn.createStatement();
					return true;
	      	}
	      	else
	      		return false;
	      		
	  	 }
	    catch (SQLException e)
	    {
	    	
	      // the above drop statements will throw exceptions
	      // if the types and tables did not exist before. Just ingore it.
	      System.out.println("Error en la conexion!!!");
	      e.printStackTrace();
	      return false;
	    }
	    		
	}
	
	//Abre el documento PDF
	public void abrirPDF()
	{
  		/* Abrir el archivo PDF */
		try 
		{
			Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + strNombreDelPDF);
		}
		catch (IOException e) 
		{
			e.printStackTrace();
		}	
	}	
}

Como se observa en el metodo conectarBD() se hace una instancia de la clase CrearConexion.java y se le mandan en el constructor los datos con los que se conectara a MySQL.

Los datos que se usan para conectarse al DBMS son:
Usuario: root
Password: root
Base de datos: prueba
Tabla: empleados
Host: localhost

Y la estructura de la tabla empleados es:

Estructura de la tabla empleados usada en este ejemplo

Estructura de la tabla empleados usada en este ejemplo

CrearConexion.java
Este archivo tiene como funcion la apertura de una conexion al DBMS MySQL y devuelve la referencia a traves de su metodo getConnection(). En el constructor recibe los datos que seran usados por el JConnector, el codigo de este archivo es:

// 		Instituto Tecnologico de Zacatepec
 // Descripcion: Clase para manejo de base de datos de MySQL
 // Author Gonzalo Silverio    gonzasilve@hotmail.com
 // Archivo: CrearConexion.java


import java.sql.*;

public class CrearConexion 
{
	//Datos por default de la conexion
	static String strUsuario = "usr";
	static String strPassword = "pw";
	static String strBaseDatos ="bd";
	static String strHost = "localhost";
	
	//Constructor, le llegan los datos con los que se conectara al DBMS
	public CrearConexion(String usr,String pw, String bd)
	{
		strUsuario = usr;
		strPassword = pw;
		strBaseDatos =bd;
		try
		{
			Class.forName("com.mysql.jdbc.Driver");		
		} catch ( ClassNotFoundException e )
		{
			System.out.println("ERROR: Error al cargar la clase del Driver");		
		}
	}
	
	//Constructor, le llegan los datos con los que se conectara al DBMS
	// a dif. del otro constructor le llega tbn el host (servidor)
	public CrearConexion(String usr,String pw, String bd,String srvr)
	{
		strUsuario = usr;
		strPassword = pw;
		strBaseDatos =bd;
		strHost = srvr;
		try
		{
			//Cargar el driver
			Class.forName("com.mysql.jdbc.Driver");		
		} catch ( ClassNotFoundException e )
		{
			System.out.println("ERROR: Error al cargar la clase del Driver\n");
			e.printStackTrace();
		}
	}
	
	public static Connection getConnection() throws SQLException 
	{
		//a continuacion vamos a formar la cadena de conexion, pero...
		//OJO aca debes poner el nombre de la instancia de SQL Server que vas a usar
		String url = "jdbc:mysql://"+strHost+"/"+strBaseDatos;
		return DriverManager.getConnection(url,strUsuario,strPassword);
	}

	//Cierra objeto Resultset
	public static void cerrar(ResultSet rs)
	{	
		try
		{
			rs.close();
		} 
		catch(Exception ex)
		{}
	}
	
	//Cierra objeto Statement
	public static void cerrar(Statement st)
	{
		try
		{
			st.close();
		} 
		catch(Exception ex)
		{}
	}
	
	//Cierra objeto Connection
	public static void cerrar(Connection con)
	{	
		try
		{
			con.close();
		} 
		catch(Exception ex)
		{}
	}
}	//Fin de la clase

Como se puede ver esta clase es la misma que use en el ejemplo Acceso a Base de datos de SQL Server desde java (Jconnector).

Eso es todo, hasta pronto y espero comentarios al respecto. ya sabes si quieres los fuentes, basta con pedirlos dejando tu mail. Suerte, bye.

Como guardar la ruta de un archivo en tabla MySQL y java

A veces en algun programa necesitamos guardar la ruta de un archivo. Por ejemplo si es un programa para llevar el control de empleados tal vez sera necesario guardar las fotografias de los empleados o una imagen de un producto, o la ruta de un archivo de documento, etc. Es por eso que se me ocurrio mostrar como se puede guardar la ruta de un archivo en una tabla de MySQL y recuperarla.

Parece facil, pero tiene su chiste, bueno para mostrar voi a diseñar una sencilla BD con una sola tabla que se llame productos con 3 unicos campos: el Id, el nombre del producto y su imagen (imagen muestra del producto). Los comandos SQL para crear la BD y la tabla son los siguientes:

CREATE DATABASE pruebaRuta;
USE pruebaRuta;
CREATE TABLE productos(id int auto_increment not null,nombre varchar(100), imagen varchar(2000), primary key(id) );

Observe que el id es auto_increment y por lo tanto el DBMS lo genera automaticamente, el campo imagen guarda una cadena que sera la ruta donde esta la imagen del producto.

Ahora imaginemos que las imagenes las tenemos almacenadas en la siguiente ruta del disco duro: c:\imagenes\productos. Podria pensarse que para realizar una insercion para registrar un nuevo producto en la tabla se haria con el comando:

INSERT INTO productos(nombre, imagen) VALUES('Chiles chipotles','c:\imagenes\productos\chipoles_100gr.jpg');

y de hecho si ese comando lo ejecutamos en la consola de MySQL nos dice que se inserto con exito:

 

insercion mal

insercion mal

bien, ahora hagamos un SELECT de la tabla para mostrar si se inserto…

 

select mal

select mal

…pero hooo! sorpresaa faltan las diagonales (slash). al parecer el DBMS las toma como secuencias de escape y las omite, no las guarda pues, desconozco sinceramente por que no guarda las diagonales pero e ideado una clase java que agrega doble diagonal o cualquier otro caracter para reemplazar los separadores de carpetas por unos que si son validos. La forma correcta de registrar un nuevo producto es esta:

INSERT INTO productos(nombre, imagen) VALUES('Chiles chipotles','c:\\imagenes\\productos\\chipoles_100gr.jpg');

ahora muestro como MySQL no manda error:

insert bien

insert bien

y ahora otra vez el SELECT y vemos como ahora si se guardo correctamente

 

select bien

select bien

aahh esta vez si se inserto bien la ruta del producto. Obviamente que las inserciones aqui hechas se han hecho desde la linea comandos del cliente de MySQL pero esta operaciones de INSERT se hacen mediante un programa java con una interfaz de usuario y esas cosas.
Para ilustrar todo esto con un ejemplo practico he creado 3 clases: JfrPrincipal.java, JfrAltaProductos.java, JfrVisorProductos.java, los cuales voi a ir explicando poco a poco a continuacion. No olvidar que el objetivo de este ejemplo es la de mostrar como mandar correctamente la ruta de un archivo a una tabla de MySQL y como recuperarla para mostrar el archivo (p. ej. imagenes, .txt) o abrirlo. A continuacion muestro el diagrama de clases del ejemplo:

Clases del ejemplo Corregir Ruta Archivo

Clases UML del ejemplo Corregir Ruta Archivo

Como se puede observar la clase que nos interesa la e resaltado en otro color, esta clase se instancia desde la clase JfrAltaProductos.java que es la que nos permite dar de alta a un nuevo producto, se llama desde aqui por que antes de dar de alta un producto (INSERT) se debe correguir la ruta.

JfrPrincipal.java
Este archivo es la clase principal y unicamente tiene la funcion de mostrar una GUI con dos botones para que el usuario elija abrir el visor de imagenes o agregue un nuevo producto. En el codigo hay algunos comentarios para describir brevemente que es lo que se hace:

/*
		Instituto Tecnologico de Zacatepec, Mor.
Descripcion:  Ventana principal del ejemplo, desde esta interfaz el usuario puede
					elegir entre ver las imagenes o dar de alta un nuevo producto.
Autor:  Gonzalo Silverio   gonzasilve@gmail.com
Archivo JfrPrincipal.java
*/

import javax.swing.*;
import java.awt.FlowLayout;
import java.awt.event.*;

public class JfrPrincipal extends JFrame
{
	//Constructor
	JfrPrincipal(String titulo, int ancho, int alto)
	{
		//Establecer titulo, tamanio y posicion en la pantalla
		super(titulo);
		setSize(ancho,alto);
		setLocationRelativeTo(null);	//centrado
		//Rotulo principal de la ventana
		JLabel lblTitulo = new JLabel("Ventana principal");
		JPanel panTitulo = new JPanel(new FlowLayout(FlowLayout.CENTER));
		panTitulo.add(lblTitulo);
		//Crear el boton nuevo
		JButton btnNuevo = new JButton("Nuevo");
		JPanel panNuevo = new JPanel(new FlowLayout(FlowLayout.CENTER));
		panNuevo.add(btnNuevo);
		//Crear el boton para abrir el visor de imagenes
		JButton btnVisorImagenes = new JButton("Visor de imagenes");
		JPanel panVisor = new JPanel(new FlowLayout(FlowLayout.CENTER));
		panVisor.add(btnVisorImagenes);
		
		//Todos los componentes estan en un Box Vertical
		//para alinear los controles
		Box boxVertical = Box.createVerticalBox();
		boxVertical.add(Box.createVerticalStrut(50));
		boxVertical.add(panTitulo);
		boxVertical.add(panNuevo);
		boxVertical.add(panVisor);
		//Agregar el Box a la ventana
		add(boxVertical);
		setResizable(false);	//No maximizar ni cambiar tamanio
		//Al dar en la X terminar todo el programa
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    	// ########### ESCUCHADOR BOTON NUEVO   ##########
    	ActionListener escuchadorAlta = new ActionListener()
    	{
        	public void actionPerformed(ActionEvent evt)
        	{
            JfrAltaProductos ejemplo = new JfrAltaProductos("Alta de un nuevo producto",400,400);
            ejemplo.mostrar();
            //Ocultar la ventana principal
            setVisible(false);
        	}
   		};
    	btnNuevo.addActionListener(escuchadorAlta);

    	// ########### ESCUCHADOR PARA BOTON VISOR DE IMAGENES   ##########
    	ActionListener escuchadorVisor = new ActionListener()
    	{
        	public void actionPerformed(ActionEvent evt)
        	{
            JfrVisorProductos ejemplo = new JfrVisorProductos("Visor de imagenes de productos",400,400);
            ejemplo.mostrar();
            //Ocultar la ventana principal
            setVisible(false);
        	}
   		};
    	btnVisorImagenes.addActionListener(escuchadorVisor);
    	
	}	//Fin del constructor

	//hace visible la ventana	
	public void mostrar()
	{
		setVisible(true);
	}

	public static void main(String[] args) 
   {
		JfrPrincipal ejemplo = new JfrPrincipal("Visor de Imagenes de productos",400,400);
		ejemplo.mostrar();
   }
}

Ahora muestro imagen de la ventana que genera el codigo anterior:

Ventana principal del ejemplo.

Ventana principal del ejemplo.

Como se puede ver es una interfaz muy sencilla y es el punto de entrada del programa.

JfrAltaProductos.java
Esta clase permite dar de alta un nuevo producto, es decir permite hacer un INSERT en la tabla de productos con el nombre del producto y la ruta que corresponde a una imagen previa de dicho producto. En el codigo se muestra los comentario correspondientes explicando el codigo:

/*
		Instituto Tecnologico de Zacatepec, Mor.
Descripcion:  Ventana para dar de alta a un nuevo producto, antes de dar de alta
			un producto se debe corregir la ruta del archivo de imagen del producto.
Autor:  	Gonzalo Silverio   gonzasilve@gmail.com
Archivo: JfrAltaProductos.java
*/

import javax.swing.*;
import java.awt.FlowLayout;
import java.awt.Color;
import java.awt.event.*;
//Para usar la clase File con el FilesChooser
import java.io.*;
//Para usar operacion con BD (JDBC)
import java.sql.*;

public class JfrAltaProductos extends JFrame
{
	
	 //Script SQL para crear la tabla productos:
	 //CREATE TABLE productos(id int auto_increment not null,nombre varchar(100), imagen varchar(2000), primary key(id) );

   JTextArea jtaRutaImagen;
   JTextField jtfNombre;

	private static Connection con = null;
	Statement st;

	//Constructor
	JfrAltaProductos(String titulo, int ancho, int alto)
	{
		super(titulo);
		setSize(ancho,alto);
		setLocationRelativeTo(null);
		JLabel lblTitulo = new JLabel("Datos del producto");
		JPanel panTitulo = new JPanel(new FlowLayout(FlowLayout.CENTER));
		panTitulo.add(lblTitulo);
		
		//Crear una etiqueta y su campo de texto correspondiente para capturar el
		//nombre del producto
		JLabel lblNombre = new JLabel("Nombre: ");
		jtfNombre = new JTextField(20);
		JPanel panNombre = new JPanel(new FlowLayout(FlowLayout.LEFT));
      panNombre.add(Box.createHorizontalStrut(15));
		panNombre.add(lblNombre);
		panNombre.add(jtfNombre);
		//Crear el boton examinar
		JButton btnExaminar = new JButton("Examinar...");
      btnExaminar.addActionListener(new seleccionarImagen());
		
		//Crear el area de texto para mostrar la ruta absoluta del archivo
      JPanel panRutaImagen = new JPanel(new FlowLayout(FlowLayout.LEFT));
         jtaRutaImagen = new JTextArea(4,20);
         jtaRutaImagen.setDisabledTextColor(Color.BLUE);
         jtaRutaImagen.setLineWrap(true);
         jtaRutaImagen.setEnabled(false);
         JScrollPane scrollRutaImagen = new JScrollPane(jtaRutaImagen);
         scrollRutaImagen.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
         scrollRutaImagen.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
      panRutaImagen.add(Box.createHorizontalStrut(15));
      panRutaImagen.add(scrollRutaImagen);
      panRutaImagen.add(btnExaminar);
		//Crear el boton Guardar
		JButton btnGuardar = new JButton("Guardar");
		JPanel panGuardar = new JPanel(new FlowLayout(FlowLayout.CENTER));
		panGuardar.add(btnGuardar);
		//Crear el boton Cancelar
		JButton btnCancelar = new JButton("Cancelar");
		JPanel panCancelar = new JPanel(new FlowLayout(FlowLayout.CENTER));
		panCancelar.add(btnCancelar);
		//Alinear los botones Guardar y Cancelar en forma horizontal
      Box boxGuardarCancelar = Box.createHorizontalBox();
      boxGuardarCancelar.add(btnGuardar);
      boxGuardarCancelar.add(Box.createHorizontalStrut(30));
      boxGuardarCancelar.add(btnCancelar);

		//Agregar todos los controles de usuario al Box Horizontal principal
		Box boxVertical = Box.createVerticalBox();
		boxVertical.add(Box.createVerticalStrut(50));
		boxVertical.add(panTitulo);
      boxVertical.add(Box.createVerticalStrut(50));
      boxVertical.add(panNombre);
      JPanel panEtiquetaRuta = new JPanel(new FlowLayout(FlowLayout.LEFT));
      panEtiquetaRuta.add(Box.createHorizontalStrut(15));
      panEtiquetaRuta.add(new JLabel("Imagen previa del producto"));
      boxVertical.add(panEtiquetaRuta);      
		boxVertical.add(panRutaImagen);
      boxVertical.add(Box.createVerticalStrut(10));
      boxVertical.add(boxGuardarCancelar);
      boxVertical.add(Box.createVerticalStrut(100));
		//Agregar el Box principal a este JFrame
		add(boxVertical);
		//No permitir maximizar ni redimensionar este JFrame
		setResizable(false);

// ##################### ESCUCHADOR DE VENTANA #############################################
    	//Para que al dar clic en la x de la esquina de este JFrame
      //se muestre por default la ventana principal
		this.addWindowListener(new WindowAdapter() 
		{
			public void windowClosing(WindowEvent e)
			{
            JfrPrincipal ejemplo = new JfrPrincipal("Visor de Imagenes de productos",400,400);
            ejemplo.mostrar();

				setVisible(false);
			}

			public void windowClosed(WindowEvent e)
			{
            JfrPrincipal ejemplo = new JfrPrincipal("Visor de Imagenes de productos",400,400);
            ejemplo.mostrar();
				setVisible(false);
			}
		});

    	// ########### ESCUCHADOR BOTON CANCELAR   ##########
    	ActionListener escuchadorCancelar = new ActionListener()
    	{
        	public void actionPerformed(ActionEvent evt)
        	{
            JfrPrincipal ejemplo = new JfrPrincipal("Visor de Imagenes de productos",400,400);
            ejemplo.mostrar();
            setVisible(false);
        	}
   	};
    	btnCancelar.addActionListener(escuchadorCancelar);

    	// ########### ESCUCHADOR BOTON GUARDAR   ##########
    	ActionListener escuchadorGuardar = new ActionListener()
    	{
        	public void actionPerformed(ActionEvent evt)
        	{
        		//Validar que NO haya campos vacios
            if(hayCamposVacios())
            {
            	JOptionPane.showMessageDialog(null,"Debes escribir el nombre y elegir la ruta de la imagen, hay campos vacios");
            	return;
            }

            if( conectarBaseDatos() )
            {
               if( altaProducto() )
               {
               	JOptionPane.showMessageDialog(null,"Producto guardado con exito");
               	jtfNombre.setText("");
               	jtaRutaImagen.setText("");
               }                  
               else
                  JOptionPane.showMessageDialog(null,"No se pudo guardar");
            }
            else
               JOptionPane.showMessageDialog(null,"No se pudo Conectar la BD");

        	}
   	};
    	btnGuardar.addActionListener(escuchadorGuardar);
    	
	}  	//Fin del costructor

	//Conecta la base de datos y se prepara para un sentencia SQL
	//Devuelve true solo si la conexion tuvo exito
   public boolean conectarBaseDatos()
   {
      try
      {
         Class.forName("com.mysql.jdbc.Driver");
         String strCadenaConexion = "jdbc:mysql://localhost/pruebaRuta";
         con = DriverManager.getConnection(strCadenaConexion,"root","12345");
         if (con == null )
            return false;
         
         //Preparar conexion para ejecutar una sentencia SQL
         st = con.createStatement();
         return true;
      }
      catch(SQLException sqlex)
      {
         sqlex.printStackTrace();
          return false;
      }
      catch(Exception e)
      {
         e.printStackTrace();
         return false;
      }
   }

	//Realiza un ALTA en la tabla de productos
   //devuelve true solo si se pudo realizar con exito el INSERT en la tabla
   public boolean altaProducto()
   {
      try
      {
         String strRutaImagen;
         //Instanciamos la clase que corrige la ruta del archivo
         CorregirRuta ruta1 = new CorregirRuta(jtaRutaImagen.getText(),"\\", "\\\\");
         //CORREGIR LA RUTA
         strRutaImagen = ruta1.obtenerRutaCorregidaWindows();
         //Hacer el insert con la ruta corregida
         int res = st.executeUpdate("INSERT INTO productos(nombre,imagen) VALUES('"+jtfNombre.getText()+"','"+strRutaImagen+"')");
         
         if(res==1)
            return true;
         else
            return false;

      }
      catch(SQLException sqlex)
      {
         sqlex.printStackTrace();
          return false;
      }
      catch(Exception e)
      {
         e.printStackTrace();
         return false;
      }
   }

   //Comprueba true si alguno de los 2 campos esta vacios
   public boolean hayCamposVacios()
   {
      if( jtfNombre.getText().isEmpty() || jtaRutaImagen.getText().isEmpty() )
         return true;
      return false;
   }

   //hace visible la ventana
	public void mostrar()
	{
		setVisible(true);
	}

	//Clase interna
	class seleccionarImagen implements ActionListener
	{
	  public void actionPerformed(ActionEvent ae)
	  {
	   String strSeleccionado;
	   JFileChooser jfcSeleccionarArchivo = new JFileChooser();
	   //Asignar el filtro para que solo se vean imagenes en la ventana abrir
	   jfcSeleccionarArchivo.addChoosableFileFilter(new FiltroImagenes());
	   //Filtro a usarse por defecto
	   jfcSeleccionarArchivo.setFileFilter(jfcSeleccionarArchivo.getChoosableFileFilters()[1]);
	
	      // Abre el cuadro de dialogo Abrir
	      int retval = jfcSeleccionarArchivo.showOpenDialog(JfrAltaProductos.this);
	      if (retval == JFileChooser.APPROVE_OPTION)
	      {
	          //... Si el usuario selecciono un archivo, entonces usarlo
	          File filSeleccionado = jfcSeleccionarArchivo.getSelectedFile();
	          //Obtener ruta absoluta del archivo seleccionado
	          strSeleccionado = filSeleccionado.getAbsolutePath();
	          //Mostrar la ruta al usuario en el area de texto correspondiente
	          jtaRutaImagen.setText(strSeleccionado);
	      }
	  }
	}		//fin de clase interna


}		//Fin de la clase

A continuacion muestro una imagen de la ventana que se genera:

Ventana para dar de Alta un producto.

Ventana para dar de Alta un producto.


Dejando campos vacios…
Mensaje de error al dejar Campos vacios en alta de producto.

Mensaje de error al dejar Campos vacios en alta de producto.

Como se observa e insertado un producto de ejemplo para ilustrar como funciona la ventana. El usuario una vez que escribe el nombre y elije un archivo de imagen (con el Boton Examinar…) debe dar clic en el Boton Guardar; al hacer esto el programa realiza una pequeña validacion de campos vacios y si se logra satisfacer se hace el INSERT. Una vez que se realizo el INSERT el programa limpia los campos para que el usuario siga dando de alta mas productos. Si el usuario ya termino debe dar click en el Boton Cancelar para volver a la ventana principal del ejemplo.

Como se puede observar en el metodo altaProducto() se instancia a la clase CorregirRuta.java (pasandole la ruta sin corregir) y se ejecuta su metodo obtenerRutaCorregidaWindows() para obtener la ruta corregida, tambien en la clase interna seleccionarImagen se hace una instancia de la clase FiltroImagenes.java, a continuacion muestro el codigo de dichas clases:

CorregirRuta.java
Permite corregir al ruta de carpetas de un archivo para poder almacenarla correctamente en una tabla de MySQL. Creo que no necesita mucha explicacion pues en el cabezado del archivo se describe, sin tanto rodeo, el codigo es…

/*
 *		Instituto Tecnologico de Zacatepec, Mor.
 * Descripcion:
 *	Clase que eecibe una ruta de archivo y una cadena que es con la que vienen separadas los nombres de las carpetas
 *  y otra cadena mas que es el nuevo separador con el que se van a separar ahora las carpetas.
 *  Devuelve la ruta ya corregida con el nuevo separador
 * @author: Gonzalo Silverio gonzasilve@gmail.com
 * Archivo: CorregirRuta.java
 * 
 */
import java.util.StringTokenizer;

public class CorregirRuta 
{
    String ruta, separador, nuevoSeparador;	

    public CorregirRuta(String laruta, String sep, String nuevoSep)
    {
    	ruta=laruta;
    	separador=sep;
    	nuevoSeparador=nuevoSep;
    }

    public String obtenerRutaCorregidaWindows()
    {
         StringTokenizer tokens=new StringTokenizer(ruta, separador);
         //Para guardar la ruta corregida
         String rutaCorregida = new String();
         //Contar los tokens (en este caso las carpetas, contado tambien
         // el nombre del archivo seleccionado).
         int noTokens = tokens.countTokens();
         int i = 1;
         do
         {		//Agregar el nuevo separador
            rutaCorregida += tokens.nextToken()+nuevoSeparador;
            i++;
         }while(i<noTokens);
         //Agregar a la ruta corregida el ultimo token, (nombre del archivo)
         rutaCorregida += tokens.nextToken();		
         //Mostrar la ruta corregida en la consola
         System.out.println(rutaCorregida+"\n"+noTokens+ " tokens");
         return rutaCorregida;
    }
}

FiltroImagenes.java
Clase para filtrar unicamente los archivos de imagenes con extension .jpeg , .jpg , .png , .gif en la ventana de dialogo estandar Abrir.

/*
		Instituto Tecnologico de Zacatepec, Mor.
Descripcion:
   Clase que permite mostrar unicamente los ficheros .jpeg,  .jpg,  .gif en los cuadros de dialogo.
   Un filtro es un objeto de la clase FileFilter del paquete javax.swing.filechooser.. FileFilter es una
   clase obstracta con dos metodos abstractos accept y getDescription.
Author:  Gonzalo Silverio   gonzasilve@gmail.com
Archivo FiltroImagenes.java
*/

import javax.swing.filechooser.FileFilter;
import java.io.File;

public class FiltroImagenes extends FileFilter
{
    public boolean accept(File f)
   {
      if( f.isDirectory() )      
         return true;
      
      String nombreArchivo = f.getName().toLowerCase();
      if( nombreArchivo != null )
         if( nombreArchivo.endsWith(".jpeg") ||
            nombreArchivo.endsWith(".jpg")  ||
			nombreArchivo.endsWith(".png")  ||
            nombreArchivo.endsWith(".gif")
           )
            return true;
      
      return false;    
   }
   
   //Descripcion del filtro (se mostrara en la ventana abrir)
   public String getDescription()
   {
      return "Archivos de imagenes ( *.jpg ,  *.png ,  *.gif )";
   }
}        //Fin de la clase

JfrVisorProductos.java
Esta clase crea una ventana muy sencilla para mostrar los datos del producto, principalmente permite leer la ruta almacenada del archivo de imagen muestra del producto. En el codigo he comentado las partes mas importantes…

/*
		Instituto Tecnologico de Zacatepec, Mor.
Descripcion:  Ventana para mostrar las imagenes de los productos.
Autor:  Gonzalo Silverio   gonzasilve@gmail.com
Archivo: JfrVisorProductos.java
*/

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import java.sql.*;

public class JfrVisorProductos extends JFrame
{
   JPanel panelPrincipal, panelSuperior,panelInferior;

	private static Connection con = null;
	Statement st;
	ResultSet rs;
	
	int idsProductos[];    //Contiene los ID de los productos
	//Apunta al registro que se esta mostrando actualmente
	//Po defecto apuntar antes del primero
	int regActual = -1;
	int totalRegistros = 0;         //Contiene el total de registros que hay en la tabla
   JLabel lblNombreProducto = new JLabel("Nombre imagen");
   JPanel panImagen;
   JLabel lblImagen;
	Icon imagenn;
   
	JButton btnAnterior = new JButton("Anterior");
	JButton btnSiguiente  = new JButton("Siguiente");;
      
	Box boxpanSuperior;

   JfrVisorProductos(String tituloVentana, int ancho, int alto)
   {
      //Establecer titulo,tamanio, si es redimensionable y la posicion
      // de la ventana
      setTitle(tituloVentana);
      setSize(ancho,alto);
      this.setResizable(false);
      setLocationRelativeTo(null);
      
      JPanel panNombreProducto = new JPanel(new FlowLayout(FlowLayout.CENTER));
      panNombreProducto.add(lblNombreProducto);
      
      panelPrincipal = new JPanel(new BorderLayout());
      panelSuperior = new JPanel(new BorderLayout());
      panelInferior = new JPanel(new BorderLayout());
      btnAnterior.setMnemonic(KeyEvent.VK_A);
      btnSiguiente.setMnemonic(KeyEvent.VK_S);
      imagenn = new ImageIcon();
      lblImagen = new JLabel(imagenn);

      panImagen = new JPanel(new FlowLayout(FlowLayout.CENTER));
      panImagen.add(new JScrollPane(lblImagen), BorderLayout.CENTER);
      
      panelSuperior.add(panImagen);
      boxpanSuperior = Box.createVerticalBox();      
      boxpanSuperior.add(panNombreProducto);
      boxpanSuperior.add(panelSuperior);
      
      panelInferior.add(btnAnterior, BorderLayout.WEST);
      panelInferior.add(btnSiguiente, BorderLayout.EAST);
      panelPrincipal.add(boxpanSuperior, BorderLayout.CENTER);
      panelPrincipal.add(panelInferior, BorderLayout.SOUTH);

      add(panelPrincipal);
      inicializar();		//Cargar los IDs
      siguiente();		//Moverse al primer registro (estabamos uno antes del primero)
      
// ##################### ESCUCHADOR DE VENTANA #############################################
    	//Para que al dar clic en la x de la esquina de este JFrame
      //se muestre por default la ventana principal
	this.addWindowListener(new WindowAdapter() {

			public void windowClosing(WindowEvent e)
			{
            JfrPrincipal ejemplo = new JfrPrincipal("Visor de Imagenes de productos",400,400);
            ejemplo.mostrar();

				setVisible(false);
			}

			public void windowClosed(WindowEvent e)
			{
            JfrPrincipal ejemplo = new JfrPrincipal("Visor de Imagenes de productos",400,400);
            ejemplo.mostrar();
				setVisible(false);
			}
		});

    	// ########### ESCUCHADOR BOTON ANTERIOR   ##########
    	ActionListener escuchadorAnterior = new ActionListener()
    	{
        	public void actionPerformed(ActionEvent evt)
        	{
				anterior();				//Va al anterior registro de la tabla
        	}
   		};
    	btnAnterior.addActionListener(escuchadorAnterior);

    	// ########### ESCUCHADOR BOTON SIGUIENTE   ##########
    	ActionListener escuchadorSiguiente = new ActionListener()
    	{
        	public void actionPerformed(ActionEvent evt)
        	{
				siguiente();				//Va al siguiente registro de la tabla
        	}
   		};
    	btnSiguiente.addActionListener(escuchadorSiguiente);
    	
   }		//Fin del constructor

    //Inicializa el arreglo de IDs para que se puedan recorrer los registros 
    //y actualiza la variable que contiene el total de registros que hay en la tabla
    public void inicializar()
    {
        try
        {
            conectarBaseDatos();		//Nos conectamos con la BD
            rs = st.executeQuery("SELECT * FROM productos"); //seleccionamos todos los de la tabla productos

            //A continuacion se van a guardar en un arreglo los IDs de todos los productos
            if(! rs.first() )             //Nos movemos al primer registro
            	JOptionPane.showMessageDialog(null,"La tabla de productos esta vacia.");
	
            int contador = 0 ;
            do
                contador ++ ;           //Contar cuantos registros hay en la tabla productos
            while(rs.next());
            totalRegistros = contador-1;      //Guarda el numero de registros que hay en la tabla

            idsProductos = new int[contador];            //Crea el arreglo de IDs
            contador = 0;       //Reinicializar el contador
            rs.first();             //Nos movemos al primer registro
            do
                idsProductos[contador++]= rs.getInt("id");
            while(rs.next());

        }
        catch( SQLException sqlex  )
        {
            JOptionPane.showMessageDialog(null,"Error al inicializar el arreglo de IDs");
        }

    }		//Fin del metodo
    
    //permite desplazarse al anterior registro de la tabla
    public void anterior()
    {       
        regActual = regActual - 1;
        if ( regActual < 0 )
            regActual = 0;

        if(!consultarID())
            JOptionPane.showMessageDialog(null,"Error al ir al registro Anterior");
    }
	
	//permite desplazarse al siguiente registro de la tabla
    public void siguiente()
    {
        regActual = regActual + 1;
        if ( regActual > totalRegistros )
            regActual = totalRegistros;

        if(!consultarID())
            JOptionPane.showMessageDialog(null,"Error al ir al siguiente registro");
    }

    
    //Realiza una consulta con el ID seleccionado en regActual en el arreglo idsProductos[], 
    //devuelve true si se realizo la consulta con exito, en caso contrario devuelve false
    private boolean consultarID()
    {
        try
        {
            rs = st.executeQuery("SELECT * FROM productos where id="+idsProductos[regActual] ); //seleccionamos todos los de la tabla productos
            rs.first();                 //moverse al primer registro
            poblarCampos();
            return true;                //Todo se ejecuto con exito
        }
        catch(SQLException sqlex)
        {
            return false;
        }
    }		//Fin del metodo
    
    //rellena los campos con los datos del registro apuntado actualmente
    private void poblarCampos()
    {
        try
        {            
            lblNombreProducto.setText(rs.getString("nombre"));
            panImagen.remove(lblImagen);	//Borrar la imagen anterior
            //Recuperar de la BD la ruta del archivo de imagen
            imagenn = new ImageIcon(rs.getString("imagen"));	
            lblImagen = new JLabel(imagenn); //Cargar nueva imagen
            panImagen.add(lblImagen);	
            validate();
            repaint();	
				//Mostrar en la barra de titulo el reg. actual y el total
				setTitle("Visor de imagenes [producto "+(regActual+1)+" de "+(totalRegistros+1)+"]");

        }
        catch( SQLException sqlex  )
        {
            JOptionPane.showMessageDialog(null,"Error al rellenar los campos");
        }        
    }		//Fin del metodo
    

	//Conecta la base de datos y se prepara para un sentencia SQL
	//Devuelve true solo si la conexion tuvo exito
   public boolean conectarBaseDatos()
   {
      try
      {
         Class.forName("com.mysql.jdbc.Driver");
         String strCadenaConexion = "jdbc:mysql://localhost/pruebaRuta";
         con = DriverManager.getConnection(strCadenaConexion,"root","12345");
         if (con == null )
            return false;
         
         st = con.createStatement();
         return true;
      }
      catch(SQLException sqlex)
      {
         sqlex.printStackTrace();
          return false;
      }
      catch(Exception e)
      {
         e.printStackTrace();
         return false;
      }
   }		//Fin del metodo
   
	//hacer visible la ventana
	public void mostrar()
	{
		setVisible(true);
	}

}	//Fin de la clase

El aspecto de la ventana que se genera es esta:

Visor de imagenes de productos

Visor de imagenes de productos



Como se puede observar en el codigo e ideado una manera de recorrrer los registros de la tabla con dos botones, me parece interesante esto; lo mas probable es que en otra entrada del blog publique algo al respecto pero ya con los 4 botones de navegacion de registros (Primero,Anterior,Siguiente,Ultimo).

Nota: La marca Sabritas, Rufles y Coca-Cola son marcas registradas y solo las e puesto aqui con propositos educativos, si el autor(es) desea que la retire basta con pedirlo.

Bueno esto creo que se alargo demasiado, el objetivo era corregir la ruta y meti varias cosas mas, jajaja pero estoy seguro que aprendi mas y espero que tu tambien. Si estas leyendo esto es por que me imagino que leiste todo lo anterior. Ya sabes si tienes dudas puedes dejar un comentario, o si quieres los .java basta con dejar tu mail… hasta pronto y gracias por pasar por aqui ;).

Como hacer un DELETE en una BD SQL Server desde C Sharp!

Ahora muestro como mandar una sentencia DELETE a una tabla muy sencilla de SQL Server , de la cual muestro su estructura a continuacion:

Estrutura de tabla animales SQL Server

Estrutura de tabla animales SQL Server

como se ve en la imagen, la tabla se llama animales y unicamente tiene 3 campos; el primero entero (smallint), el segundo string (char) y el tercero entero (smallint). Bueno pues no hay mucho que explicar en el codigo se explica todo. El codigo es el siguiente:

/*
                Instituto Tecnologico de Zacatepec, Morelos
Descripcion:    Este programa muestra como acceder a una BD de SQL Server para hacer un DELETE
Author: 	       Gonzalo Silverio  gonzasilve@gmail.com
Fecha:          12/08/2010
Archivo:		Practica10.cs
*/

using System;
using System.Data.SqlClient;

public class Practica10
{
	static void Main()
	{
        //Variable para guardar el ID del animal a eliminar
        string strID;

        //Definicion de la cadena de conexion
        string strCadConexion = "user id=root;" +
                                       "password=12345;server=localhost\\SQLSERVEREXPRESS;" +
                                       "Trusted_Connection=yes;" +
                                       "database=prueba; " +
                                       "connection timeout=15";
        string strCadSQL;
        SqlConnection myConnection = new SqlConnection(strCadConexion);

        //abrir la conexion
        try
        {
            myConnection.Open();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }

        //Solicitud y Lectura de datos
        Console.WriteLine("Escriba el ID del animal que desea borrar: ");
        strID = Console.ReadLine();

        //Formando el comando SQL
        strCadSQL = "DELETE FROM animales WHERE id=" + strID;
        SqlCommand myCommand = new SqlCommand(strCadSQL, myConnection);

        //Ejecucion del comando en el servidor de BD
        myCommand.ExecuteNonQuery();

        Console.WriteLine();
        Console.WriteLine("  ...OK. eliminacion exitosa!");
	}
}

A continuacion muestro pantallazos de la compilacion y ejecucion del codigo…

compilacion:

Compilacion de Practica 10

Compilacion de Practica 10

ejecucion:

Ejecucion de Practica 10

Ejecucion del programa

se aceptan comentarios constructivos .

}

Como hacer un UPDATE en una BD SQL Server desde C Sharp!

Ahora muestro como mandar una sentencia INSERT a una tabla muy sencilla de SQL Server , de la cual muestro su estructura a continuacion:

Estrutura de tabla animales SQL Server

Estrutura de tabla animales SQL Server

como se ve en la imagen, la tabla se llama animales y unicamente tiene 3 campos; el primero entero (smallint), el segundo string (char) y el tercero entero (smallint). Bueno pues no hay mucho que explicar en el codigo se explica todo. El codigo es el siguiente:

/*
                Instituto Tecnologico de Zacatepec, Morelos
Descripcion:    Este programa muestra como acceder a una BD de SQL Server para hacer un UPDATE
Author: 	       Gonzalo Silverio  gonzasilve@gmail.com
Fecha           12/08/2010
Archivo:		Practica9.cs
*/

using System;
using System.Data.SqlClient;

public class Practica9
{
	static void Main()
	{
        //Variables para guardar los datos escritos x el usuario
        string strID;       //ID del registro a actualizar
        string strNuevoID;
        string strNombre;
        string strNoPatas;

        //Definicion de la cadena de conexion
        string strCadConexion = "user id=root;" +
                                       "password=12345;server=localhost\\SQLSERVEREXPRESS;" +
                                       "Trusted_Connection=yes;" +
                                       "database=prueba; " +
                                       "connection timeout=15";
        string strCadSQL;
        SqlConnection myConnection = new SqlConnection(strCadConexion);

        //abrir la conexion
        try
        {
            myConnection.Open();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }

        //Solicitud y Lectura de datos
        Console.WriteLine("Escriba el ID del animal a modificar: ");
        strID = Console.ReadLine();
        Console.WriteLine();

        Console.WriteLine("Escriba el NUEVO ID: ");
        strNuevoID = Console.ReadLine();
        Console.WriteLine("Escriba el Nombre del animal: ");
        strNombre = Console.ReadLine();
        Console.WriteLine("Escriba el No. de patas: ");
        strNoPatas = Console.ReadLine();

        //Formando el comando SQL
        strCadSQL = "UPDATE animales SET id="+strNuevoID+", nombre='"+strNombre+"', no_patas="+strNoPatas+" WHERE id="+strID;
        SqlCommand myCommand = new SqlCommand(strCadSQL, myConnection);

        //Ejecucion del comando en el servidor de BD
        myCommand.ExecuteNonQuery();

        Console.WriteLine();
        Console.WriteLine("  ...OK. Actualizacion exitosa!");
	}
}

A continuacion la compilacion y ejecucion del codigo…

compilacion:

Compilacion de Practica 9

Compilacion de codigo

ejecucion:

Ejecucion de practica 9

Ejecucion del programa

se aceptan comentarios constructivos .

Obtencion de datos con SELECT de una BD SQL Server en C Sharp!

Este ejemplo muestra como conectarse a una base de datos en el DBMS SQL Server y como obtener datos de una tabla muy sencilla, de la cual muestro su estructura a continuacion:

Estrutura de tabla animales SQL Server

Estrutura de tabla animales SQL Server

como se ve en la imagen, la tabla se llama animales y unicamente tiene 3 campos; el primero es entero (smallint), el segundo string (char) y el tercero es entero (smallint). Bueno pues no hay mucho que explicar en el codigo se explica todo. El codigo es el siguiente:

</pre>
 /*
                Instituto Tecnologico de Zacatepec, Morelos
Descripcion:    Este programa muestra como acceder a una BD de SQL Server y obtener
                datos con un SELECT.
Author: 	    Gonzalo Silverio  gonzasilve@gmail.com
Fecha:		    10/08/2010
Archivo:		Practica8.cs
*/

using System;
using System.Data.SqlClient;

public class Practica8
{
	static void Main()
	{

        //Definicion de la cadena de conexion
        string strCadConexion = "user id=root;" +
                                       "password=12345;server=localhost\\SQLSERVEREXPRESS;" +
                                       "Trusted_Connection=yes;" +
                                       "database=prueba; " +
                                       "connection timeout=15";
        string strCadSQL;
        SqlConnection myConnection = new SqlConnection(strCadConexion);
        
        try
        {
            //abrir la conexion
            myConnection.Open();

            //Formar la sentencia SQL, un SELECT en este caso
            SqlDataReader myReader = null;
            strCadSQL = "SELECT * FROM animales";
            SqlCommand myCommand = new SqlCommand(strCadSQL, myConnection);

            //Ejecutar el comando SQL
            myReader = myCommand.ExecuteReader();

            //Imprimir un encabezado para mostrar una tabla de resultados
            Console.WriteLine("ID\tNombre\tNo_patas");
            Console.WriteLine("---------------------------------------------------------");

            //Mostrar los datos de la tabla
            while (myReader.Read())
            {
                Console.WriteLine( myReader["id"].ToString() + "\t" + myReader["nombre"].ToString() + "\t" + myReader["no_patas"].ToString() );
            }

            //Informar del exito de la operacion al usuario
            Console.WriteLine();
            Console.WriteLine("  ...OK. Operacion exitosa!");
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
        
	}
}

A continuacion la compilacion y ejecucion del codigo…

compilacion:

Obtencion de datos con SELECT

ejecucion:

Obtencion de datos con SELECT

Ejecucion del programa

se aceptan dudas y comentarios constructivos.

bye

Operacion INSERT en una BD SQL Server en C Sharp

En esta ocasion muestro como conectarse a una base de datos en el DBMS SQL Server y como mandar una sentencia INSERT de una tabla muy sencilla, de la cual muestro su estructura a continuacion:

Estrutura de tabla animales SQL Server

Estrutura de tabla animales SQL Server

como se ve en la imagen, la tabla se llama animales y unicamente tiene 3 campos; el primero entero (smallint), el segundo string (char) y el tercero entero (smallint). Bueno pues no hay mucho que explicar en el codigo se explica todo. El codigo es el siguiente:

/*
                Instituto Tecnologico de Zacatepec, Morelos
Descripcion:    Este programa muestra como acceder a una BD de SQL Server para hacer un INSERT
Author: 	    Gonzalo Silverio  gonzasilve@gmail.com
Fecha:		    10/08/2010
Archivo:		Practica7.cs
*/

using System;
using System.Data.SqlClient;

public class Practica7
{
	static void Main()
	{
        //Variables para guardar los datos escritos x el usuario
        string strID;
        string strNombre;
        string strNoPatas;

        //Definicion de la cadena de conexion
        string strCadConexion = "user id=root;" +
                                       "password=12345;server=localhost\\SQLSERVEREXPRESS;" +
                                       "Trusted_Connection=yes;" +
                                       "database=prueba; " +
                                       "connection timeout=15";
        string strCadSQL;
        SqlConnection myConnection = new SqlConnection(strCadConexion);

        //abrir la conexion
        try
        {
            myConnection.Open();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }

        //Solicitud y Lectura de datos
        Console.WriteLine("Escriba el ID: ");
        strID = Console.ReadLine();
        Console.WriteLine("Escriba el Nombre del animal: ");
        strNombre = Console.ReadLine();
        Console.WriteLine("Escriba el No. de patas: ");
        strNoPatas = Console.ReadLine();

        //Formando el comando SQL
        strCadSQL = "INSERT INTO animales (id, nombre, no_patas) Values ("+strID+",'"+strNombre+"',"+strNoPatas+")";
        SqlCommand myCommand = new SqlCommand(strCadSQL, myConnection);

        //Ejecucion del comando en el servidor de BD
        myCommand.ExecuteNonQuery();

        Console.WriteLine();
        Console.WriteLine("  ...OK. Operacion exitosa!");
	}
}

A continuacion la compilacion y ejecucion del codigo…

compilacion:

Compilacion de practica7

Compilacion de practica7

ejecucion:

Ejecucion de practica7

Ejecucion de practica7

se aceptan comentarios constructivos y dudas.

A %d blogueros les gusta esto: