You are on page 1of 314

Este libro sigue estando dedicado a ya sabéis quiénes, incluso aunque las personas en cuestión no lo sepan.

A ver si logramos mantener el secreto otro libro más.

Agradecimientos
Son muchas las personas con las que tengo una deuda de gratitud pero poco el espacio disponible para pagarles; toca generalizar. Gracias a todas aquellas personas que me están ayudando a apreciar las cosas sencillas como, por ejemplo, los momentos que puedo compartir con ellas. Y claro, le tengo que dar las gracias a Ignacio Cerro por poner prólogo a esta obra y ponerla en perspectiva, y a Guadalupe Torres por darle un toque de color y de estilo al libro con una portada tan maravillosa. Por cierto, quizá en la dedicatoria no ha quedado del todo claro que este libro va para toda la familia de Guille, que tan bien se está portando con él.

Introducción
¿Revolución? No, realidad. Está usted leyendo la introducción de un libro que contiene las claves para convertir sus páginas Web en aplicaciones Web, cuyo contenido se obtiene a partir de una base de datos, y que permite a sus usuarios almacenar información en esa misma base de datos. Y si tiene usted esta guía en sus manos no hace falta que le convenza (al menos, no mucho) de la formidable pareja que hacen MySQL y PHP. Éste es un mundo de descubrimientos. Y de maravillas. Y está en continuo cambio. Fue en el año 1990 cuando comenzó todo, de mano del investigador Tim Berners-Lee, el padre de la criatura. No ha pasado tanto tiempo desde entonces, ¿verdad? Y sin embargo, han pasado tantas cosas que parece casi increíble. En primer lugar, están las páginas Web, escritas en leguaje HTML. Este lenguaje permite describir la ubicación de diferentes elementos en una página, además de sus propiedades (tamaño, color, etc.). Salvando las distancias, sería una tarea similar a la de un pintor trabajando con un lienzo. No en vano la tarea de crear páginas HTML se deja en manos de los diseñadores, los artistas de la Web. Estas páginas reciben el calificativo de estáticas porque, una vez publicadas, su contenido permanece inalterable. Hasta que decidamos modificarlas, claro está, pero en este caso se trataría de otra página. Y es aquí donde aparece PHP. PHP es un lenguaje, como HTML, pero con una diferencia notable: tanto los elementos de una página como su ubicación dentro de ella pueden variar dependiendo de las condiciones que creamos oportunas. Esto permite crear contenidos totalmente flexibles. Una sencilla aplicación de las posibilidades de PHP consiste en incluir detalles de la fecha y la hora actuales en las páginas aunque, obviamente, esto no se queda ahí. Puede variar el contenido de las páginas dependiendo del cliente Web que se esté utilizando para ver las páginas. Así, si utiliza Firefox, puede mostrar la página de una manera y si utiliza Internet Explorer de otra totalmente diferente. Por otro lado están las bases de datos, presentes en multitud de aspectos de la vida cotidiana: en el móvil, en el banco, en el supermercado. Sin que seamos conscientes de ello, convivimos con estos sistemas. Inicialmente, su alto coste no hacía previsible esta expansión. Pero la situación ha cambiado considerablemente porque hoy en día podemos encontrar sistemas gestores de bases de datos que utilizar libremente. Entre ellos destaca uno, MySQL, el más utilizado de los de su clase. Y por último, está su unión. Para que se haga una idea

del potencial que la combinación de estas tecnologías tiene, suponga que quiere poner a disposición de todo el mundo, en su propio servidor Web, información sobre su colección de películas. Normalmente esto significaría crear una página por cada película. Sin embargo, utilizando MySQL y PHP juntos, podrá crear una única página cuyo contenido variará dependiendo de la película que quiera seleccionar. En esta guía aprenderá a hacerlo. La unión hace la fuerza, nada más cierto. Combinando las tecnologías necesarias para ofrecer páginas Web, para administrar bases de datos y el lenguaje de páginas dinámicas PHP, podrá poner a disposición de todos aquellos que tengan acceso a Internet un catálogo de productos o cualquier otra información que desee mostrar. Y las posibilidades no se limitan a Internet. La red local de su empresa puede ser también el medio de difusión ideal, ya se trate de una aplicación para la gestión de las tareas asignadas a cada departamento o de un boletín de noticias privadas. El límite lo marca su imaginación. Estamos hablando de medios de difusión, equiparando una red de ordenadores con una red de periódicos, de televisión o de radio, porque es así. Las principales cadenas de radio del mundo emiten en Internet desde hace tiempo, los periódicos más importantes tienen su versión digital, e incluso las televisiones se intentan abrir hueco. Muchos asisten perplejos al nacimiento de un nuevo sistema de comunicación de noticias basado en el mismo esquema: un servidor de bases de datos que almacena las noticias y un servidor Web que, gracias al uso de lenguajes como PHP, las ofrece a todos los que quiera leerlas o publicarlas. Muchos de estos sistemas, conocidos como blogs (de Web Logs) utilizan PHP y MySQL para su funcionamiento. Hemos empezado diciéndole que estamos frente a una realidad y hay varios hechos que lo constatan. El más significativo de ellos es la aparición, sin pausa, de versión tras versión de PHP, cada una de ellas incorporando interesantes novedades, haciéndolo aún más potente y capaz de lo que ya era. Si a esto unimos la madurez en la que se encuentra MySQL tras el lanzamiento de su versión 5.1 (que bien podría haber sido llamada la versión 6), no podemos equivocarnos: PHP y MySQL es la pareja ganadora. Decidirse por ellos es unirse a una de las mayores comunidades de desarrolladores de nuestro planeta, una gran ventaja, ya que se cuenta con mucha experiencia acumulada que puede ser de utilidad. Acompáñenos en lo que le prometemos será un viaje de descubrimientos y de maravillas. No le defraudaremos.

Cómo usar este libro
El objetivo de esta guía es que, a su fin, sea capaz de desarrollar aplicaciones para la Web basadas en MySQL y PHP. Tanto si ya ha trabajado con ellos por separado o conjuntamente como si éste es su primer contacto, está en buenas manos. En primer lugar queremos que sepa exactamente qué es lo que logrará si sigue con nosotros durante el resto del viaje. Para ello hemos preparado un primer capítulo equiparable a una terapia de choque. Durante este capítulo configurará un completo sistema de desarrollo y aprenderá qué son un servidor Web, un servidor de bases de datos y dónde encaja PHP dentro de todo esto. Para ilustrar esta explicación nada mejor que un sencillo ejemplo. Al terminar este capítulo debería tener una visión de conjunto de todas las tecnologías que va a utilizar. El segundo capítulo es una introducción al lenguaje PHP para aquellos que aún no lo conozcan: desde la declaración de variables y sus posibles tipos hasta las instrucciones de control. En la misma línea que el anterior, el tercer capítulo se dedica al sistema gestor de bases de datos MySQL. Hablaremos sobre sus características, veremos qué son bases de datos y tablas y los tipos de datos que podemos almacenar. Los capítulos cuarto y quinto están dedicados a ampliar los conocimientos adquiridos en el segundo y el tercero. De nuevo están dedicados a PHP y MySQL, pero a aspectos que aún no se han tratado y cuya importancia es fundamental. En concreto, funciones y programación orientada a objetos en lo que se refiere a PHP y diseño de bases de datos con respecto a MySQL, ya que antes de entrar en el meollo de la cuestión, diseñaremos la base de datos con la que vamos a trabajar. En el sexto capítulo aprenderá a utilizar el lenguaje SQL para obtener la información que desee de una base de datos, así como para modificarla. La verdadera acción comienza en el capítulo séptimo. En él MySQL y PHP unen sus fuerzas. Para acceder a bases de datos de MySQL desde PHP utilizaremos la nueva interfaz entre ambos que PHP presentó en la versión anterior a la actual, la 5. Veremos con detalle el ejemplo expuesto durante el primer capítulo, combinado con la base de datos diseñada en el capítulo anterior, y lo ampliaremos. En el capítulo octavo hablaremos sobre los formularios en HTML y JavaScript. Hasta ahora se habrá limitado a obtener información de una base de datos y mostrarla en una página Web, pero con lo que aprenda en este capítulo será capaz de permitir que el usuario de sus aplicaciones Web también pueda guardar datos. Entre otros usos, JavaScript le ayudará a comprobar que estos datos son

correctos, ahorrándole trabajo en sus páginas PHP y evitando posibles errores. El noveno capítulo está dedicado a uno de los aspectos que más se descuidan durante la creación de un programa en PHP: la gestión de errores. Verá cómo configurar PHP y MySQL en este aspecto, y cómo crear sus propios gestores de error. A estas alturas de la guía ya habrá visto lo complicado que es mantener dos lenguajes como PHP y HTML en un único archivo. Lo ideal es que el trabajo de diseño y el de programación se puedan hacer de forma independiente. Esto es posible gracias al uso de plantillas, que veremos durante el capítulo décimo. Los capítulos decimoprimero, decimosegundo y decimotercero están dedicados a los procedimientos almacenados, los desencadenadores y las vistas, respectivamente. Se trata de características avanzadas de MySQL que le resultarán extremadamente útiles. Esta guía se cierra con un capítulo dedicado a XML, un estándar con el que tanto MySQL como PHP pueden trabajar. En dicho capítulo veremos cómo utilizar sus características de forma conjunta. En un mundo que evoluciona tan rápido como el de la informática, no hay nada peor que un libro que no evoluciona al mismo paso. Por ello hemos puesto a su disposición la página Web: http://enreas.com/amp/ Los productos que utilizamos en este libro dan el nombre a la página: Apache, MySQL y PHP (AMP). En ella podrá encontrar los ejemplos del libro, contactar con el autor de esta guía y mucho más.

soluciones. Algo que nunca me paré a mirar y que forma parte de mi día a día como si de un grifo se tratase. por qué el color del envase coincide con el del contenido. sin Google. Veo pasar todo ante mí fluyendo sin aparente esfuerzo. En apenas 30 segundos. Perspectiva para entender que las cosas no suceden porque sí. un día tras otro: consulto una enciclopedia. dos electrodomésticos le ofrecieron lo que él buscaba. Estaba frío. Pensar en lo que hago cada día. A veces tiendo a imaginarme lo que Internet ofrece como un ente físico. por qué usaron ese plástico para distribuirlo. Devoradores de datos. con el paso del tiempo y con la ayuda de las nuevas tecnologías. En esta dirección he debido hacer un ejercicio de autocrítica. con claridad. Lo abro y allí está la respuesta. Y en esta senda me topo con algo que uso a diario para mi trabajo. Yo solito. carentes de perspectiva para entenderlos. relleno un formulario. . en muchos casos. La velocidad a la que se suceden los acontecimientos en nuestros días nos dejan. No aceptar nada porque exista desde hace tiempo. comento en un blog. se sentó delante de un portátil que suele estar en la cocina y abrió Spotify. Comienza mi jornada delante del ordenador y algunos actos se suceden a lo largo del día. En el día de ayer mi hijo de nueve años se acercó al frigorífico de la casa y sacó un batido. de opciones. publico en otro. sin interrogantes y sin perspectiva. por qué tiene ese tamaño si suelo quedarme con ganas de coger otro. Eligió su lista de canciones favoritas y comenzó a escuchar música. de imágenes. Cuestionarme por qué está frío el batido. No dar nada por supuesto. Me siento como un funcionario del control de aduanas de Andorra. de contactos. Qué difícil es entender que nuestra obligación pasa tanto por respetar lo que hay como por arrasarlo para construir algo nuevo. con estructura y vida propia. La música estaba donde debía y hacía lo que se esperaba que hiciese. que el fruto de muchos años de trabajo puede hacer que algo parezca evidente pero es la consecuencia de horas y horas con muchos interrogantes y pocas respuestas. que es lo que se espera cuando uno saca una bebida del frigorífico. Qué difícil es parar y cargar una dosis de perspectiva. en auténticos devoradores. Nos estamos convirtiendo. Pensar sin muchos datos. herramientas.Prólogo Perspectiva. A continuación. Con naturalidad. Todo ocurrió con la misma coherencia y trasparencia que cuando tomó el batido en sus manos. accedo a un foro. que me ofrece información. con extremidades copadas de conocimientos y ansioso por atravesar el umbral de la puerta de mi casa. Parar y pensar un poquito. Recibir y ofrecer. sin Wikipedias a mi alcance. Todo según lo esperado.

Lo usamos a diario con la misma naturalidad que tenemos al coger el mando a distancia de la televisión. pues durante muchos años me fue muy ajeno. Doy fe de que no es mala compañía. Ignacio Cerro . levantándose cada día para hacer que todo siga funcionando. Creer que está a nuestro alcance el participar de la batalla no es algo insensato. Pero a mí me da igual y. Ahora está pasando las primeras páginas de un libro que pretende mostrar algunas de las cualidades de dos de estos hermanitos que dan de comer a la legión que nombramos anteriormente: PHP y MySQL.Pero ¿qué hay detrás de todo eso? ¿Qué es lo que lo sostiene? No puedo negar que últimamente me siento fuertemente atraído por eso que llaman software libre. aunque hoy lo que pretendo es rendir un pequeño homenaje a aquellos que hacen posible que esto siga creciendo. Por este motivo les invito a que. ¿Quien los puso a todos de acuerdo para que la máquina funcionara? ¿Cuál fue el origen? ¿Qué puerta hay que cruzar para dejar de ser un devorador y formar parte de la legión? ¿Dónde está la clave para dar soporte y ánimo al grupo? El software libre se nos ha metido en casa. Les dejo ahora con uno de esos disciplinados orcos. Entenderlo un poco nos ayudaría a respetarlo. Pero es que no puedo dejar de imaginarme a una legión de programadores. Conocerlo nos permitiría hacerlo crecer. Si he de ser sincero. lo que me dejan es su eficiencia. sigan pasando páginas y que puedan encontrar en lo que viene a partir de este momento al menos una respuesta a tanto interrogante. conmigo. Lo reconozco con cierta vergüenza. para mí no son más que un conjunto de letras reunidas con poca gracia. Su engranaje es sublime. Muchas de las tareas que realizo a diario están soportadas por bases de datos construidas con MySQL y se muestran en páginas programadas con PHP. semejante en número y constancia a un piélago de orcos camino del Abismo de Helm. pero ya advertí que era el momento de parar y pensar.

La primera aplicación ¿Cuál es nuestro objetivo? Construir una aplicación que muestre el contenido de una base de datos en una página Web. Vamos a desarrollar una pequeña aplicación Web que permita gestionar nuestra videoteca. pero juntos forman una de las parejas más formidables del mundo del software libre. Este capítulo está pensado para aquel lector que no está muy seguro de lo que podrá encontrar en este libro. así que iremos por partes: nos limitaremos a crear una aplicación para realizar el mantenimiento de una lista de géneros cinematográficos. Antes de que el lector pueda comenzar a realizar sus propios desarrollos será necesario que pasemos por algunos capítulos que le mostrarán las características principales de MySQL y PHP. hay que tener paciencia para contener los deseos de avanzar capítulos sin prestar la debida atención a los pilares fundamentales del desarrollo de páginas Web de contenido dinámico. MySQL y PHP son grandes productos por sí solos. de las maravillas que podrá construir tras el trabajo que supondrán los capítulos siguientes a éste. Veremos que es posible tener una base de datos. Durante las siguientes páginas crearemos una pequeña aplicación Web que muestre el contenido de una base de datos en una página HTML. Este trabajo formará luego parte de la aplicación que gestionará nuestra videoteca. No se preocupe si muchos de los conceptos que se presenten durante este capítulo le son desconocidos: profundizaremos en todos ellos durante el resto del libro. Las aplicaciones Web que veremos se componen de varias partes: . aprenderá a utilizar de forma conjunta ambas tecnologías. Una vez tenga esos conocimientos básicos. No queremos engañarle. utilizando PHP como unión. de su futuro. el contenido de la página Web cambiará sin que por ello tenga que cambiar ni una sola línea de la página PHP. Pero es mejor concretar un poco más. Y veremos que. si cambia alguno de los datos de una tabla.1 MySQL y PHP Para el impaciente. Plantéese la lectura de este capítulo como la de una novela: le narraremos una historia que habla del futuro. extraer los datos almacenados en ella y mostrarlos en una página Web. Sería muy ambicioso por nuestra parte comenzar esta guía con un trabajo de tales características.

1 muestra las relaciones existentes entre los diferentes elementos que acabamos de enumerar. Puede modificar el contenido de la base de datos y ver cómo el contenido de las páginas Web de su aplicación cambia sin que tenga que alterar una sola línea de código. La figura 1. Aplicaciones Web Por lo tanto. Tras ello. Posteriormente poblaremos dicha base de datos con las tablas y los registros necesarios. debido a su potencia y a que es uno de los más utilizados. Linux o Mac OS X. .1. por lo que todos podemos utilizarlo en Windows.2. Clientes: Los clientes son los usuarios de nuestra aplicación Web. el primer paso será disponer de todos los servicios necesarios: MySQL para las bases de datos y Apache (con PHP) para las páginas Web. Sea un desarrollo hecho para nuestro propio disfrute o para el de los demás. si nadie (persona o máquina) va a utilizarlo quizá su existencia carezca de sentido. PHP: El nexo de unión entre la base de datos y los clientes potenciales de nuestra aplicación Web. podremos comenzar con a trabajar. Entre ellos. Una base de datos: Contiene las tablas y los datos con los que queremos trabajar. Un servidor Web: Aunque podríamos escoger cualquier servidor Web que permita la ejecución de PHP. que se trata del servidor Web más utilizado en el mundo y es libre. Continuaremos con la programación en PHP de la página que mostrará el contenido de una de las tablas de la base de datos. Al terminar podremos contemplar algo parecido a lo que se puede ver en la figura 1. Figura 1.Un servidor de bases de datos: MySQL ha sido la elección lógica. Nuestro desarrollo va a comenzar con la creación de la base de datos. nos decantamos por Apache por varios motivos.

Francamente. Apache.Figura 1. de un plumazo. en cualquiera de los sistemas operativos antes mencionados: XAMPP. para que se pueda poner manos a la obra necesita disponer de un sistema con Apache. XAMPP no es algo único. Existen muchas otras soluciones para instalar Apache. configuración y mantenimiento de cada uno de los componentes de forma individual. existe una forma rápida y sencilla de instalar y configurar todo esto.org/ Not a: XAMPP son las siglas de X. se trata de un trabajo que es necesario dejar en manos de expertos capaces de garantizar la seguridad y el rendimiento del servidor. PHP y Perl. Linux o Mac . en que todo funciona como se espera. aquel en el que se encontrarán las aplicaciones Web una vez concluido su desarrollo) sigue siendo la más compleja: la instalación. PHP y MySQL instalados y en funcionamiento. como en WAMP o LAMP. Puede encontrarlo en la página: http://apachefriends. En segundo lugar. aunque le parezca mentira. PHP y MySQL con facilidad. y concéntrese en el contenido de la misma. Nuestro objetivo Not a: No preste atención al diseño de la página. programación) de la representación (aspecto. Sin embargo. MySQL. XAMPP es ideal para entornos de desarrollo. Se utiliza una X para representar al sistema operativo y no una W (de Windows) o una L (de Linux). la opción recomendada para un servidor de producción (es decir. En el capítulo dedicado a Smarty aprenderemos a separar la lógica (funcionamiento. Obviamente. diseño). haría falta un libro como éste sólo para comenzar a explicar cómo instalar y configurar correctamente estos tres componentes en los tres sistemas operativos más utilizados del mercado (Windows.2. La razón por la que lo utilizaremos en este libro es múltiple: Está a su disposición ya utilice Windows. Un par de aclaraciones. a su aspecto. Pues. Linux y Mac OS X). En primer lugar. En este libro no utilizaremos esa última P. XAMPP Como acabamos de comentar.

. Como podrá comprobar. Figura 1. C:\xampp. El equipo responsable de su desarrollo se preocupa de mantenerlo actualizado para que ofrezca la última versión de cada componente. por ejemplo. se trata de un proceso muy simple. de forma individual. El más complejo de ellos. por ejemplo. la instalación de XAMPP es prácticamente idéntica: tendrá que descargar un archivo. la mejor forma de evitar problemas con los permisos de la carpeta de archivos de programa si se instala en Windows Vista es utilizar una carpeta que se encuentre en la raíz del disco como.org/en/xampp-windows. PHP y MySQL correctamente instalados y configurados.html Cuando termine de descargar el instalador haga doble clic sobre él y siga los pasos del mismo. extraer su contenido y ejecutar una orden para poner en marcha los servicios necesarios. Proporciona una interfaz de usuario muy fácil de utilizar para poner en marcha y detener los servicios. No es obligatorio que use XAMPP. Instalación de XAMPP en Windows Advert encia: ¿Por qué es el paso más complejo? Porque. Puesta en marcha en Windows La forma más sencilla de disponer de la versión para Windows de XAMPP es utilizar el asistente para la instalación disponible en la siguiente dirección: http://apachefriends.3. según se comenta en la página dedicada a la versión para Windows de XAMPP. Puesta en marcha de XAMPP Independientemente del sistema operativo. una aplicación Web para la administración de bases de datos MySQL. consiste en seleccionar la ruta en la que se instalará XAMPP. Incluye multitud de herramientas como. phpMyAdmin.OS X. podrá seguir los ejemplos de este libro siempre y cuando disponga de un equipo con Apache. que puede ver en la figura 1.3.

tar. XAMPP se encontrará en dentro de la carpeta /opt .Las opciones predeterminadas de los pasos del asistente serán las más adecuadas en la mayoría de los casos. El panel de control de XAMPP se encuentra dentro del menú Inicio. Responda que sí: podrá ver un cuadro de diálogo similar al que muestra la figura 1.gz -C /opt 4. Figura 1. Cuando esté en funcionamiento aparecerá una etiqueta a su derecha con el texto Running y el nombre del botón cambiará por Stop.html 2. Haga clic en Start para poner en marcha un servicio. Cuando el proceso de instalación concluya se le ofrecerá la opción de ejecutar el panel de control de XAMPP. Inicie una sesión como administrador del sistema o utilice la orden su para obtener sus privilegios.org/en/xampp-linux. Consejo: Póngase en contacto con el administrador de su sistema Linux si tiene dificultades para seguir las anteriores instrucciones o si el resultado obtenido no . 3. Utilice la siguiente orden para extraer su contenido. 5. Panel de control de XAMPP En lo que a esta guía respecta sólo nos interesarán los botones asociados a Apache y a MySQL.4. a continuación. Descargue la versión para Linux de XAMPP. que se encuentra en la página: http://apachefriends. Por último. Utilícelo para detener el servicio correspondiente cuando lo desee.4. sustituyendo X e Y por los números correspondientes a la versión de XAMPP que haya descargado: tar xvfz xampp-linux-X. en Apache Friends>XAMPP>XAMPP Control Panel. Como resultado. Puesta en marcha en Linux La instalación y puesta en marcha de XAMPP en Linux no podría ser más sencilla: 1. haciendo clic en Programas o Todos los programas y. ejecute la orden /opt/lampp/lampp start para poner en marcha XAMPP y /opt/lampp/lampp stop para detenerlo.Y.

dedicados a Windows y Linux. Una vez la imagen de disco se monte haga doble clic sobre el archivo XAMPP for MacOS X. uno por cada idioma disponible. De igual forma. Cuando el proceso de instalación concluya sólo restará poner en marcha los servicios. Puesta en marcha en Mac OS X De nuevo. Puesta en marcha de XAMPP en Mac OS X 6. Podrá ver algo parecido a lo que muestra la figura 1. que se encuentra en la página: http://apachefriends. después.org/en/xampp-macosx. Con independencia del sistema operativo que utilice.es el deseado. algo que puede ocurrir si en su equipo ya están instalados y en funcionamiento Apache o MySQL. la orden sudo /Applications/XAMPP/xamppfiles/mampp stop. Figura 1. XAMPP estará disponible a través de la dirección http://localhost/. Para ello abra un terminal y ejecute la orden sudo /Applications/XAMPP/xamppfiles/mampp start . Descargue la versión para Mac OS X de XAMPP. Haga doble clic sobre el archivo DMG descargado. también desde un terminal. . Vaya allí con su cliente Web favorito.pkg y siga los pasos del instalador. La figura 1.html 2. es necesario decir que la instalación de XAMPP en Mac OS X es muy sencilla: 1.6 muestra el resultado de hacer clic sobre Español y. 3.5. podrá ver una página de presentación con diferentes enlaces. sobre Estado en la parte izquierda de la página. para detener los servicios deberá ejecutar.5. 4. al igual que en los dos apartados anteriores.

Figura 1.6. Estado de los servicios de XAMPP

El aspecto de estas páginas es prácticamente idéntico en Windows, Linux y Mac OS X. Ahora que ya tiene XAMPP instalado asegúrese de que Apache y MySQL estén en funcionamiento antes de pasar al siguiente apartado, donde nos pondremos manos a la obra.

Trabajando con MySQL
Nuestro primer paso, siempre que comencemos el desarrollo de una aplicación Web que trabaje con MySQL, debería ser diseñar la base de datos. Existen herramientas que pueden ayudarnos a realizar esta tarea. De entre todas ellas, le recomendamos MySQL Workbench, disponible para Windows, Linux y Mac OS X. Pero antes de utilizar herramienta alguna hemos de tener claro qué información debe contener la base de datos. Para ello, nada mejor que el diálogo con aquellos que lo sepan. Si vamos a desarrollar una aplicación para una empresa, hemos de hablar todo lo que sea necesario con aquellos que tengan más información al respecto, que de verdad sepan cómo debe funcionar. En nuestro caso lo tenemos más fácil: sabemos lo que queremos, puesto que durante este aprendizaje seremos nuestro propio jefe. Vamos a guardar en una tabla dentro de una base de datos de MySQL información sobre géneros cinematográficos. Posteriormente utilizaremos estos géneros conjuntamente con otras tablas, que contendrán información sobre películas.

Creación de la base de datos

Aunque existen herramientas en línea de órdenes para realizar operaciones con MySQL, dejaremos esa opción para aquellos lectores que lo encuentren necesario. MySQL pone a nuestra disposición una herramienta mucho más amable: MySQL Administrator. Puede encontrarla en la siguiente página, formando parte del paquete MySQL GUI Tools: http://dev.mysql.com/downloads/gui-tools/
Not a: Si instaló XAMPP también podrá utilizar phpMyAdmin para realizar estas operaciones en el servidor de base de datos MySQL de su ordenador. phpMyAdmin estará a su disposición a través del URL http://localhost/phpmyadmin/.

La primera vez que se ejecuta MySQL Administrator se presenta un cuadro de diálogo para conectarse a un servidor, que puede ver en la figura 1.7.

Figura 1.7. Conexión con un servidor MySQL

Este cuadro de diálogo le pedirá todos los datos necesarios para que se pueda establecer comunicación con el servidor MySQL con el que quiere trabajar. Basta con que introduzca el nombre del servidor en el cuadro de texto Server Host (si se trata del mismo en el que se está ejecutando MySQL Administrator este nombre será localhost ) y el nombre del usuario en Username. En este caso, como estamos utilizando XAMPP, este nombre será root y no tendrá contraseña asignada, algo que supondría un problema de seguridad en un servidor de producción pero que permite trabajar mucho más ágilmente en un puesto personal. Por supuesto, si el servidor está en otro ordenador, introduzca su nombre o IP en el cuadro de texto Server Host , y utilice el nombre de usuario y la clave correspondientes para intentar conectarse. Haga clic en OK cuando haya terminado. La figura 1.8 muestra el aspecto de MySQL Administrator tras realizar la conexión con el servidor. En dicha figura puede observarse que, en el panel de la izquierda, abajo del todo, aparece un nodo llamado Catalogs. Haga clic con el botón izquierdo del ratón sobre ese nodo. Bajo él aparecerá una lista con todos los catálogos (bases de

datos) disponibles. Haga clic con el botón derecho sobre este nuevo panel y seleccione la opción Create New Schema del menú desplegable que aparecerá.

Figura 1.8. MySQL Administrator, en funcionamiento

MySQL Administrator le presentará un cuadro de diálogo en el que sólo se le pedirá que introduzca el nombre de la nueva base de datos. Escriba videoteca. Ese será el nombre de la base de datos con la que trabajaremos durante el resto del libro. Cuando haga clic en OK el panel que contiene la lista de catálogos mostrará un aspecto similar al de la figura 1.9, donde la base de datos recién creada está seleccionada.

Figura 1.9. Nuestra nueva base de datos

Ésta, videoteca, será la base de datos con la que trabajaremos a partir de ahora. No preste demasiada atención al resto de bases de datos que aparecen en este panel, no las utilizaremos para nada. Si lo desea, puede crear sus bases de datos a partir de scripts SQL. Esta forma de trabajo tiene algunas ventajas sobre la que acaba de ver. Por ejemplo, permite repetir la operación de creación de la base de datos tantas veces como sea necesario, tenga acceso a MySQL Administrator o no. Para ello, una vez conectado con el servidor de bases de datos, seleccione la opción MySQL Query Browser del menú Tools, lo que ejecutará otra de las herramientas de MySQL, pensada para la ejecución de consultas.

MySQL Query Browser permite dar órdenes al servidor MySQL utilizando el lenguaje SQL. Por ejemplo, para crear la base de datos videoteca podría utilizar las siguientes instrucciones:
DROP DATABASE IF EXISTS videoteca; CREATE DATABASE videoteca;

La primera de estas líneas borra la base de datos videoteca en caso de que exista. La segunda, la crea. De esta forma evitará que ocurran errores si intenta crear la base de datos cuando ésta ya existe. Tenga presente, sin embargo, que si existe la borrará y perderá todos los datos que contenga. Para ejecutar las instrucciones anteriores seleccione la opción New Script Tab del menú File. Aparecerá una nueva ficha con el título Script 1. Escriba las dos líneas anteriores en el área central de MySQL Query Browser y haga clic en el botón Execute, que se encuentra en la barra de herramientas (es de color verde y tiene algo así como un rayo en el centro). La figura 1.10 muestra el aspecto de este programa tras ejecutar las dos instrucciones anteriores. El puntero de ratón está sobre el botón Execute. Ahora que tiene la base de datos necesita crear la tabla que contendrá los detalles de cada género.

Figura 1.10. SQL para crear una base de datos

Creación de la tabla
¿Qué detalles queremos guardar de cada género? Por una parte, vamos a guardar su descripción. Esta descripción define el género cinematográfico de forma completa: ciencia ficción, aventuras, drama, etc. También puede ser de utilidad guardar una abreviatura de dicha descripción. Por último, vamos a guardar un identificador numérico que será único para cada género. Utilizaremos este identificador para relacionar cada película con el

género cinematográfico correspondiente. Ya sabe los detalles que debe guardar de cada género. Ahora decida el tipo de datos que tendrá cada uno de ellos. El identificador será un número. Vamos a limitar la longitud del nombre que le damos a ese género, su abreviatura, a dos caracteres, mientras que su descripción podrá tener hasta 32. La figura 1.11 muestra el aspecto que podría tener esta tabla una vez la cree utilizando MySQL Workbench.

Figura 1.11. La tabla de géneros

Not a: El diseño de bases de datos es una tarea fundamental e importante. Puede encontrar algunos consejos al respecto en el capítulo 5.

La figura 1.11 muestra la tabla de géneros después de diseñarla utilizando MySQL Workbench. Este programa nos permite crear tablas y relacionarlas de forma muy sencilla. En la figura 1.12 vemos el panel de MySQL Workbench con el que hemos creado la tabla de géneros.

Figura 1.12. Diseñando la tabla de géneros

Pero lo mejor de todo es que puede obtener el código SQL necesario para crear esta tabla de forma automática, tras realizar el diseño. Sólo ha de hacer clic con el botón derecho sobre la tabla que acabamos de crear en MySQL Workbench y seleccionar la opción Copy SQL to Clipboard del menú contextual que aparecerá. Abra su editor de texto favorito (el bloc de notas, por ejemplo) y pegue el contenido del portapapeles utilizando la combinación de teclas Control-V. Por ejemplo, el siguiente es el código necesario para crear la tabla de géneros:
CREATE TABLE genero ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, nombre VARCHAR(2) NOT NULL, descripcion VARCHAR(32) NOT NULL, PRIMARY KEY (id) );

En el apartado anterior vimos cómo ejecutar código SQL

utilizando MySQL Query Browser. Vamos a utilizar esa técnica de nuevo para crear la tabla de géneros. En primer lugar seleccione la opción New Script Tab del menú File, dentro de MySQL Query Browser. Se abrirá una ficha con un título similar a Script 1 (el número final puede variar, dependiendo de si existen o no otras fichas del mismo tipo). Escriba la siguiente instrucción en el área central de MySQL Query Browser y haga clic en el botón Execute:
USE videoteca;

A partir de ese momento, todas las operaciones que realice estarán referidas a dicha base de datos. Así, cuando creemos la tabla de géneros lo haremos en la base de datos videoteca. Vamos a ello: escriba en la ventana de consultas la instrucción para creación de tabla que vimos anteriormente y haga clic en el botón Execute. Si todo ha ido bien dispondrá de una base de datos y de una tabla, más que suficiente para comenzar a introducir datos. Existen otras formas de crear tablas, utilizando otras herramientas, pero no podemos dejar de mencionar una de ellas, que seguro será de utilidad para aquellos que quieran permanecer lo más alejados que sea posible de SQL.
Consejo: Desde aquí queremos recomendarle que aprenda SQL si aún no tiene soltura con este lenguaje. Le aseguramos que todo el tiempo que emplee en dicho aprendizaje será una inversión que comenzará a ser rentable en un periodo de tiempo muy breve. Garantizado.

Igual que utilizó la interfaz de usuario de MySQL Administrator para crear la base de datos, puede utilizarla para crear tablas. Sólo tiene que hacer clic sobre la base de datos videoteca en el panel de catálogos, que aparece en la parte inferior izquierda cuando se selecciona el nodo Catalogs. En la parte derecha parecerá un panel que, entre otros elementos, contiene un botón llamado Create Table. Haga clic sobre él. MySQL Administrator mostrará una nueva ventana desde la que podrá crear tablas con sólo rellenar los huecos. En la figura 1.13 puede ver cómo la hemos rellenado para crear la misma tabla de géneros que obtuvimos con MySQL Workbench.

sobre el que está el puntero del ratón en la figura 1. posteriormente. el aspecto de este último al seleccionar el nodo Catalogs y. Nuestra nueva tabla Ya puede realizar las primeras inserciones de datos. haga clic en Execute. Para ello.Figura 1. Tanto si creó la tabla con SQL como si se ayudó de la interfaz de MySQL Administrator. videoteca. se le preguntará que confirme la ejecución de la instrucción SQL correspondiente.13.14.13. Figura 1. Crear tablas con MySQL Administrator Cuando haga clic en el botón Apply Changes.14. Inserciones . debe ser similar al que puede verse en la figura 1.

15. que aparece en la parte inferior de la ventana de MySQL Query Browser (el puntero del ratón está sobre él en la figura 1. Inserción de datos en MySQL Query Browser .15). De nuevo. Haga clic sobre el botón Edit . haga clic sobre la base de datos videoteca y. Si utiliza SQL puede escribir las siguientes instrucciones en una nueva ficha del tipo Script (recuerde: File>New Script Tab) dentro de MySQL Query Browser y hacer clic en el botón Execute: USE videoteca. INSERT INTO genero(nombre. 'Aventuras'). INSERT INTO genero(nombre. haga clic con el botón derecho sobre la tabla de géneros y seleccione la opción Edit Table Data del menú desplegable que aparecerá.El último paso que tiene que dar antes de comenzar a trabajar con PHP es poblar la tabla de géneros con algunas entradas. además de SQL. Figura 1. Puede verlo en la figura 1. descripcion) VALUES('A'.15. 'Ciencia Ficción'). tiene la opción de utilizar las herramientas de MySQL Administrator. en lugar de una ficha del tipo Script hay una del tipo Resultset con una consulta ya introducida y ejecutada. descripcion) VALUES('CF'. sorpresa! Se ha abierto MySQL Query Browser pero. ¡Oh. aventuras y drama. 'Drama'). puede añadir los valores necesarios para representar los géneros de ciencia ficción. Seleccione el nodo Catalogs en el panel de la izquierda. por último. Por ejemplo. INSERT INTO genero(nombre. descripcion) VALUES('D'.

16 se está insertando el primero de los géneros. Utilice las fichas de tipo Resultset para realizar consultas en los datos contenidos en las tablas de una determinada base de datos. que se encuentra justo a la derecha del botón Edit (el que tuvo que pulsar para comenzar a añadir registros en la tabla de géneros). Cuando termine de introducir los datos de los géneros haga clic en el botón Apply Changes.16. también editar los existentes. por ejemplo. Figura 1.17 muestra el aspecto de la ventana de consultas después de introducir los tres nuevos géneros. La figura 1. . Insertando registros Not a: No es necesario que se introduzca el identificador del género (campo id). Esta característica de MySQL Query Browser no sólo le permite insertar nuevos registros. Para saber más al respecto consulte el capítulo 5. MySQL se encarga de asignar ese valor automáticamente debido a que uno de los modificadores de su tipo es AUTO_INCREMENT . Por ejemplo. en la figura 1. MySQL Query Browser entrará en el modo de inserción de datos. las de creación de tablas o inserción de datos. "Diseño de bases de datos". lo que le permitirá escribir directamente los valores de las columnas que desee añadir con sólo hacer doble clic sobre el hueco del campo correspondiente.Not a: Las fichas de tipo Script de MySQL Query Browser permiten ejecutar instrucciones SQL que no devuelven resultados como.

en una tabla llamada genero. Por ahora sólo veremos la primera.Figura 1.17. no queda mucho por hacer. una descripción y un número que los identifica de forma única. incorporaba novedades realmente interesantes. Realmente. Not a: Aunque quizá sí hay relación. La mayor parte de ellas estaban relacionadas con la programación orientada a objetos. Una de las novedades que no estaba relacionada con la programación orientada a objetos nos resulta ahora especialmente interesante: el acceso mejorado a MySQL. De esta forma es sencillo reconocer a las funciones de este grupo. Esta nueva forma de acceder tiene nombre: MySQLi. Y tiene una limitación: sólo permite acceder a servidores MySQL modernos. Los tres géneros de partida Cierre MySQL Query Browser. la clave de acceso y el nombre de la . tiene tres registros. Hemos completado el primer paso de nuestro pequeño proyecto. La i latina final viene de improved (mejorado). de la que hablaremos detenidamente en posteriores capítulos. Puede hacerlo pulsando la combinación de teclas Control-F4 o seleccionando la opción Exit del menú File. Así que abra su editor de textos favoritos: ¡vamos a programar! Trabajando con PHP La anterior versión de PHP. Acceder a MySQL a través de esta interfaz es tarea muy sencilla. La función mysqli_connect() recibe como parámetros la dirección en la que se encuentra el servidor (o su nombre). Para ello utilice la función mysqli_connect(). la 5. ya que esta nueva interfaz mejorada de acceso a MySQL viene en dos sabores: funcional y orientado a objetos. Not a: Todas las funciones de la interfaz de acceso a MySQL que vamos a ver comienzan con el prefijo mysqli_. Dentro de ella. Dispone de una base de datos. Aunque gracias a esta restricción el equipo de desarrolladores de PHP ha podido crear un conjunto de funciones cuyo rendimiento y forma de funcionamiento superan en muchos aspectos a las interfaces de acceso anteriores. El siguiente paso consiste en utilizar PHP para acceder al contenido de esta tabla y poder mostrar su contenido en una página Web. cada uno de ellos con un nombre. videoteca. En primer lugar. ha de establecer una conexión con el servidor. tan solo utilizar las herramientas que PHP nos ofrece para conectar con el servidor de bases de datos. el nombre de usuario.

Así le indicará a MySQL Query Browser que quiere trabajar con esa base de datos. Para ello. que el nombre de usuario es root y que no tiene clave (un claro problema de seguridad pero. Sustituya las credenciales de acceso por las correspondientes a su entorno de trabajo. 'videoteca' ). el resultado de llamar a esta función es FALSE .18 puede ver el resultado de ejecutar esta consulta utilizando MySQL Query Browser.'). En el código anterior suponemos que el servidor está en el mismo ordenador en el que estamos trabajando (localhost ). Si todo ha funcionado correctamente. Si es así es que la conexión no se ha realizado correctamente. como ya hemos comentado anteriormente. de forma que informamos del error en la conexión y terminamos el programa llamando a exit(). Pero si todo ha ido bien podemos continuar para bingo. En la figura 1. haga doble clic sobre la base de datos videoteca.. En caso de error. 'root'.base de datos con la que queremos conectar. . el resultado de esta función nos permitirá realizar operaciones en el servidor de base de datos. puede utilizar el siguiente código para realizar la conexión: <?php $conexion = mysqli_connect( 'localhost'. se trata del funcionamiento predeterminado de XAMPP). if ($conexion == FALSE){ echo('Error en la conexión. en el panel de la derecha. A continuación ejecute esta consulta SQL: SELECT * FROM genero. El nombre de la base de datos tiene que ser videoteca en este caso. ''. exit(). } . Schemata. Tras llamar a mysqli_connect() comprobamos si el valor de $conexion es FALSE . Dicho esto. El siguiente paso es obtener todos los valores almacenados en la tabla genero..

. debe liberar la memoria que hayan ocupado. 'SELECT * FROM genero' ). Primero llame a la función mysqli_query() con los parámetros necesarios. A continuación compruebe que $resultado no sea FALSE . mysqli_close($conexion).Figura 1.. $resultado = mysqli_query( $conexion. Si lo es. es un objeto si se pudo ejecutar la consulta. Advert encia: Es conveniente dejarlo todo como estaba antes de comenzar el programa. Esta función recibe como parámetros el valor devuelto por mysqli_connect() y una cadena de caracteres que contenga la consulta a ejecutar. guardando el valor de respuesta en una variable ($resultado). cierre la conexión (con mysqli_close()) y salga del programa con exit().. debe cerrarla antes de terminar el programa.18. o FALSE en caso contrario. es que ha ocurrido un error al realizar la consulta.. así que informe de ello. exit(). } . Si abre una conexión con un servidor MySQL.'). El resultado de esta función.. if ($resultado == FALSE){ echo('Error en la consulta. como en la función de conexión. Podría usarla así: . Este fragmento de código es muy similar al anterior. Recuperando todos los registros Puede utilizar esa consulta desde PHP gracias a la función mysqli_query(). si obtiene un conjunto de registros.

').. deje todo como estaba. $fila[1]. . liberando el espacio ocupado por el resultado de la consulta y cerrando la conexión con la base de datos: . mysqli_free_result($resultado). 'root'. ''. ?> A continuación.%s<br/>".. if ($conexion == FALSE){ echo('Error en la conexión. que muestra en la página los valores de ese registro.. 'SELECT * FROM genero' ). Es decir. exit(). 'videoteca' ). así que ejecute la función printf(). de forma que puede utilizarla en un bucle while: . $fila será diferente de FALSE .. } $resultado = mysqli_query( $conexion. $fila[0]. La siguiente llamada mysqli_fetch_row() devuelve el siguiente registro. Si la función devolvió algún registro. llame a la función mysqli_fetch_row() y guarde el resultado en $fila.. $fila valdrá FALSE y saldrá del bucle. mysqli_close($conexion). } .. como dijimos. dentro de una matriz. $fila[2] ). La función mysqli_fetch_row() le permite recuperar los registros obtenidos uno por uno. Sólo tiene que mostrarlos. Para terminar. completo: <?php $conexion = mysqli_connect( 'localhost'. el código de este ejemplo. y así hasta que no quede ningún registro por mostrar. ya dispone de los datos que quiere mostrar: todos los géneros que tiene almacenados en la tabla genero de la base de datos videoteca.Si no ha ocurrido ningún error. Cuando ocurre eso. while($fila = mysqli_fetch_row($resultado)){ printf( "(%u) %s .

vuelva a escribir el bucle while.19.php. mysqli_close($conexion).). if ($resultado == FALSE){ echo('Error en la consulta.19. El resultado puede verse en la figura 1. } while($fila = mysqli_fetch_row($resultado)){ printf( "(%u) %s .').. Entonces. Sustituya el código del bucle por el siguiente: .. $fila[0]. exit().php. con el nombre generos. $fila[2] ). en PHP Y ahora un detalle curioso: nuestra primera página PHP no ha tenido más que una etiqueta HTML. Los géneros. pero ahora use tablas. la que indica nueva línea: <br/>.%s<br/>". } mysqli_free_result($resultado). visite la página http://localhost/generos. Pero eso podemos solucionarlo. mysqli_close($conexion). que se encuentra dentro de aquella en la que haya instalado XAMPP. Figura 1. ?> Guarde esta página en la carpeta htdocs. ?> <table border="1"> <tr> <th>id</th> <th>nombre</th> <th>descripcion</th> </tr> <?php while($fila = mysqli_fetch_row($resultado)){ printf('<tr>'). . $fila[1].

El código completo de esta nueva página. if ($resultado == FALSE){ echo('Error en la consulta. } ?> <table border="1"> <tr> <th>id</th> <th>nombre</th> <th>descripcion</th> </tr> <?php while($fila = mysqli_fetch_row($resultado)){ printf('<tr>')..php.'). . 'SELECT * FROM genero' ). es el siguiente: <?php $conexion = mysqli_connect( 'localhost'.printf('<tr>').php en la misma ubicación que generos.'). 'root'. exit(). 'videoteca' ). que debe guardar con el nombre generos2. $fila[0]. $fila[2] ). $fila[1]. if ($conexion == FALSE){ echo('Error en la conexión. ''. mysqli_close($conexion). printf('</tr>'). } ?> </table> <?php .. printf( "<td>%u</td><td>%s</td><td>%s</td>". exit(). } $resultado = mysqli_query( $conexion.

$fila[2] ). Gracias a este ejemplo hemos podido comprobar de primera mano lo complejo que puede llegar a ser incluir código HTML dentro del código PHP. como puede ver en la figura 1. printf( "<td>%u</td><td>%s</td><td>%s</td>". con tablas Y ahora. En el capítulo dedicado a las plantillas. veremos algunas de las opciones que tenemos para separar la lógica de la representación. Utilice MySQL Query Browser para ejecutar el código anterior.20. mysqli_close($conexion). pero la apariencia cambia.printf('<tr>'). Figura 1. $fila[1].21. La siguiente instrucción SQL inserta un nuevo registro: INSERT INTO genero(nombre. . 'Terror').20. ?> El resultado de cargar esta nueva página puede verse en la figura 1. } ?> </table> <?php mysqli_free_result($resultado). lo más espectacular: contemplar cómo cambia la página PHP cuando añadimos algún nuevo registro a la tabla genero. El contenido es el mismo. sin necesidad de cambiar el código. por fin. printf('</tr>'). descripcion) VALUES('T'. $fila[0]. facilitando la tarea tanto a programadores como a diseñadores. El resultado es que nuestra tabla tendrá un nuevo registro. Nuestro ejemplo.

El resultado debería ser algo parecido a lo que puede ver en la figura 1. Un nuevo género. ¿verdad? Y esto no ha hecho más que empezar. . Un nuevo género Este cambio en la tabla se reflejará en la página si vuelve a cargarla.Figura 1.22.22. Figura 1. en PHP Impresionante.21.

imágenes. Veremos cómo guardar valores en variables y de qué tipo pueden ser.acronymfinder. aunque en ocasiones no nos quedará más remedio. Estas decisiones las realizaremos utilizando instrucciones condicionales. Entre estas acciones puede estar el mostrar o no información en una página Web. no tenga miedo. etcétera. si decide quedarse con nosotros. PHP está más cerca de lenguajes como C++ o Java que del propio HTML. . Introducción ¿Qué es PHP? A estas alturas ya sabrá que es un lenguaje de programación y que está muy vinculado con las páginas Web que. será entretenido. También utilizaremos instrucciones iterativas. Por el contrario. Se trata de una excelente combinación de las mejores características de los lenguajes de programación más utilizados. Truco: ¿Asustado por la cantidad de siglas que se nos vienen encima? No tema. con un único objetivo: que la programación de páginas dinámicas sea pan comido. se escriben en el lenguaje HTML. avanzará un poco más hacia el objetivo final: combinar la potencia de MySQL con la flexibilidad de PHP. como qué acciones debemos realizar. lo que es más importante. así que no tenga el más mínimo reparo en pasar al siguiente capítulo si cree que tiene los conocimientos necesarios. todas ellas encuentran su traducción en http://www. Después manipularemos esos valores. Repasaremos los conceptos básicos de programación tal y como los entiende PHP. a su vez. Durante este capítulo nos concentraremos en las características de PHP como lenguaje de programación. etcétera). como texto. intentando evitar en lo posible la jerga de los programadores. realizando operaciones sobre ellos (sumas. que permitirán realizar la misma acción varias veces.2 PHP Aunque se utiliza para crear páginas Web dinámicas. HTML son unas siglas que significan "lenguaje de marcas de hipertexto" (Hypertext Markup Language). restas. Usaremos el resultado de esas manipulaciones para tomar decisiones. Este lenguaje sirve para describir las propiedades y la ubicación de una serie de elementos dentro de una página Web.com/. Al terminar este capítulo tendrá las nociones básicas necesarias para comprender cualquier programa escrito en PHP y.

son estas relaciones entre diferentes páginas las que hacen de la Web una herramienta verdaderamente única. Consejo: Se supone que si está leyendo esta guía es porque ya tiene unas nociones básicas de HTML. a los que abreviadamente se les llama enlaces. También puede ver cómo estas etiquetas definen la posición de los elementos: si un determinado texto está entre las etiquetas head y title aparecerá en la barra de título del cliente Web que esté utilizando. Si la guarda con el nombre prueba. la carpeta de archivos del servidor Web es ht docs y se encuentra dentro de aquella en la que decidiese instalar XAMPP.</h1> </body> </html> Este código describe una página muy sencilla. Si no es el caso.1. mientras que la etiqueta h1 permite indicar que el texto será un encabezado de nivel 1. el siguiente es un fragmento de código en lenguaje HTML. Una página HTML muy sencilla Not a: Si leyó el capítulo anterior y decidió seguir nuestra recomendación de utilizar XAMPP. Independientemente de la calidad del contenido de una página. de su interés. podrá ver lo que aparece en la figura 2. no se preocupe. Figura 2. puede seguir leyendo sin miedo a perderse. hemos visto qué son las páginas HTML: .html y la pone en la carpeta de archivos del servidor Web. <html> <head> <title>Prueba</title> </head> <body> <h1>Esto es una página HTML. Mediante estos enlaces podemos vincular unas páginas con otras que pueden estar en nuestro sitio Web o en otro diferente. una de las características más interesantes de las páginas HTML es la posibilidad de hacer referencia a otras páginas mediante hiperenlaces (hyperlinks). En este ejemplo puede comprobar que el lenguaje HTML utiliza etiquetas. Muy por encima. Estas etiquetas se distinguen del resto porque están entre los símbolos menor que (<) y mayor que (>). Como ya sabrá.Por ejemplo.1.

frente a las páginas HTML. el resultado de una misma página PHP puede ser distinto dependiendo de algunos factores. Figura 2. ¿Cómo encaja PHP en todo esto? PHP son también unas siglas. Un ejemplo puede ayudarnos a entender mejor para qué sirve PHP. Ese resultado puede variar en función de la lógica del programa. un chiste de informáticos que difícilmente hace gracia al resto del mundo. Vamos a intentar aclarar aún más las diferencias que hay entre HTML y PHP. con PHP puede crear programas cuyo resultado sea código HTML. Seguramente lo primero que hace es escribir la . Figura 2.net/ si desea más información al respecto. El siguiente código realiza esta tarea: La hora es: <?= date('H:i:s') ?>. Puede visitar http://gtk.3. PHP es un preprocesador de hipertexto.2 muestra el reconocible logotipo de PHP. El resultado se puede ver en la figura 2. Como consecuencia. que son estáticas. Como ya sabrá. La figura 2.3.php. pulsando F5. Es decir. PHP también puede usarse para crear aplicaciones de escritorio. El logotipo de PHP Como su propio nombre indica. El contenido de la página depende de la hora a la que ésta se cargue. Son unas siglas recursivas: están dentro de la definición. comprobará que la hora ha cambiado.2. el medio (Internet) y el servidor Web. cuando utiliza un cliente Web (como Internet Explorer o Firefox) para ver una página hay tres elementos en juego: usted. que vienen de PHP: Hypertext Preprocessor (preprocesador de hipertexto). Por eso a las páginas PHP se las conoce como páginas dinámicas. La hora. Not a: Aunque vamos a concentrarnos en las capacidades de PHP para producir páginas Web.archivos de texto con unas etiquetas especiales que determinan la posición y el formato de sus elementos. tenga presente que no es lo único que puede hacer. con PHP Si recarga la página. Y nada más sencillo que crear una página que muestre la hora. Por poner un ejemplo.

devolverá el resultado. así que invoca al preprocesador de PHP y le pasa el control. seguro que tiene ganas de más. Algo parecido a lo que podemos ver en la figura 2.4 ilustra el proceso.5. En un momento iremos a ello. Cuando termine de procesar la página. Ahora que hemos abierto boca.4 y 2. Sabe que tiene que procesarla antes de devolverla. Figura 2. pulsar la tecla Intro. La figura 2. pero antes vamos a buscar algunas herramientas que puedan ayudarle en la tarea. a continuación. Éste localiza esa página y la devuelve tal y como la encuentra. Este preprocesador busca algunos caracteres especiales. a través de Internet.5.4. Editores . pero como sabe se trata de una muy importante. realizará las operaciones que el creador de la página haya indicado.dirección de la página que quiere ver (su URL) y. En ese momento. se envía la petición al servidor. El servidor se da cuenta de que su extensión no es la de una página HTML. Una página dinámica Sólo hay una diferencia entre las figuras 2. Todo es igual hasta que el servidor localiza la página que le pedimos. Allí donde los encuentre. Figura 2. que será lo que el servidor Web envíe como respuesta a quien le haya pedido la página PHP. Una página estática El proceso es ligeramente diferente si se trata de una página PHP.5.

queremos enseñarle en la figura 2. Si el IDE que va a utilizar no es ninguno de los que le hemos recomendado. Fíjese en que el color de las etiquetas <? y ?> y de lo que aparecen entre comillas simples es diferente del resto. Posiblemente el más completo de todos sea Zend Studio. son precisamente eso y sólo eso. Pero. tendrá un color diferente. asegúrese de que. Resalte de sintaxis . Aunque más avanzado el capítulo veremos ejemplos en los que el resalte de sintaxis será más obvio. también hace falta un servidor de páginas Web. un producto multiplataforma libre que puede encontrar en la dirección: http://eclipse. existen muchas otras alternativas. Codelobster o Nusphere PhpED.6. las cadenas de texto. la clave es que encuentre uno con el que se sienta cómodo.3. cada diferente elemento del código fuente de un archivo PHP. Aptana PHP. Sí. editores de texto. Si puede permitirse pagar los casi 400 euros que cuesta. como mínimo.6 el aspecto que tiene el fragmento de código que dio como resultado la página que pudimos ver en la figura 2.org/pdt/ Not a: Repetimos. Figura 2. entorno integrado de desarrollo). etcétera. la versión 2). no lo dude: evalúelo y adquiera una copia si lo encuentra satisfactorio. Existen otras herramientas desarrolladas exclusivamente para editar PHP que pueden ser de mucha más ayuda en las tareas de programación. están NetBeans. Entre. Aunque estos son ejemplos de editores de texto decentes.Para programar en PHP sólo hace falta un editor de texto. vi en Linux o TextEdit en Mac OS X. los comentarios. pero se supone que ya contamos con él. algo de gran ayuda para encontrar determinadas secciones de código. Un editor de estas características no es sólo un editor: es un entorno de desarrollo o IDE (Integrated Development Environment. las alternativas son muchas. Y nada más. Casi todos los IDE tienen muchas características en común. por sólo mencionar algunas. le proporciona las siguientes herramientas: Resalte de sintaxis: Las palabras clave del lenguaje. una búsqueda en Google bastará para que encuentre más editores de PHP. Nuestra recomendación es que utilice Eclipse PDT (en concreto. existen muchas otras alternativas tanto a Zend Studio como a Eclipse PDT. localizar errores. como el bloc de notas de Windows. Como es costumbre en el mundo del software libre. Pero no se limite a estas. Más que la potencia del editor. como decimos.

8 muestra un asistente de código para argumentos en plena acción con dicha función. Bueno. Figura 2. a falta de mejores palabras.8. el IDE ya le muestra su nombre completo. Podrá ver tanto los argumentos como el valor que devuelve la función. Lista de funciones Asistente de código para argumentos de función: De forma similar al asistente para nombres de función. un asistente de código permitirá ver en una lista desplegable cuántas funciones comienzan con los caracteres que ha escrito. Y una memoria asombrosa hace falta para recordar el nombre de todas ellas. realmente asombroso. el de argumentos muestra la lista de argumentos que admite una función. A medida que escriba. El número de errores que cometa al escribir su código será menor si utiliza esta característica cuando no esté seguro de un nombre. nada más escribir el paréntesis a continuación de su nombre. En el ejemplo con el que mostramos la hora en una página Web utilizamos la función date(). Pero no hay nada .Asistente de código para nombres de función: El número de funciones que PHP pone a su disposición es. Argumentos de una función Ayuda integrada: Los dos asistentes para funciones son muy útiles. como puede verse en la figura 2. Figura 2.7. donde aún sin haber terminado de escribir el nombre de la función date(). pero no se preocupe que sus preguntas tendrán respuesta. La figura 2. Esta característica no hace necesario saber el nombre exacto de una función.7. Por ahora baste con decir que las funciones permiten obtener valores o realizar tareas concretas. A medida que programe con PHP le resultarán hasta imprescindibles. basta con saber al menos cómo empieza para obtener una lista de la que seleccionar la que desee. la verdad es que aún no hemos visto qué es una función.

Al no encontrar ninguno. el resultado será la página PHP tal y como la recibió el preprocesador.9. pero no lo es. Éste buscará fragmentos de código PHP. el servidor Web se la pasará al preprocesador de PHP. Pero. en Eclipse PDT bastaría con situar el putero del ratón la función date() para obtener toda la ayuda disponible en la documentación sobre dicha función.que pueda sustituir a un buen sistema de ayuda integrada en el entorno de desarrollo. funciones. Como ya sabe. el preprocesador deja pasar tal cual el texto en formato HTML. Se dice que estamos "escapando de HTML" cuando escribimos una serie de caracteres que le indican a PHP que lo que aparece a continuación será código PHP. Figura 2. éste no será el caso. cuando alguien pida una página de estas características. No es necesario compilarlo. Por ejemplo. Pruebe todo aquello que pueda hacer más productivo su trabajo. pero ejecuta las instrucciones . Lo primero que tiene que saber sobre un archivo PHP es que podría contener sólo HTML y seguiría siendo un archivo PHP válido. cualquier otra ayuda a la programación será bienvenida. Ahora que ya dispone de un editor de código medianamente decente para trabajar con PHP ¡comienza la diversión! Estructura de un archivo PHP Un archivo PHP no es más que un archivo de texto. puede leerse con cualquier editor de texto. Por lo general. Lo normal es que en una misma página coexistan HTML y PHP. ¿cómo se diferencia el código PHP del código HTML? Escapar de HTML Parece el título de una película. personalice el entorno de trabajo hasta que lo sienta como suyo propio. Ayuda integrada Not a: Por supuesto. juegue con todas las características que el IDE con el que trabaje le proporcione. Como vio en el anterior apartado. Este sistema le permite obtener ayuda sobre PHP (sintaxis.9. precisamente como muestra la figura 2. etc.) sin tener que vagar por la documentación en línea de PHP.

con una salvedad: en aquellas partes en las que quiera introducir algún valor que se genere de forma dinámica. En la anterior instrucción..texto en formato HTML. Cuando escapa de HTML entra en PHP.. ya que nos serán de mucha utilidad. vamos a ver ahora las que se utilizan para mostrar información en la página HTML resultante de procesar una página PHP. . siempre debería ser posible escapar de PHP de esa forma. Existen varias formas de escapar de HTML. pero ejecuta las instrucciones PHP. ?> De estas dos. <? . Ya hemos visto un ejemplo de cómo escapar de HTML en el primer fragmento de código PHP de este capítulo: La hora es: <?= date('H:i:s') ?>. una página que cumple el estándar XHTML. estas dos líneas de código son equivalentes: La hora es: <?= date('H:i:s') ?>. Por ello. que puede estar desactivada. <?php . Y esta operación se repite hasta llegar al final del archivo. algo que no es cierto para la segunda. algo que puede ser útil en determinadas situaciones. Funciones de salida Aunque hablaremos de las funciones en general con posterioridad. ?> 2. ?>. además. Sabe que todo lo que encuentre desde ese momento hasta que aparezca la pareja de caracteres ?> será PHP. más complicado será trabajar mezclando HTML y PHP. en adelante. PHP deja pasar tal cual todo el texto hasta llegar a los caracteres <?. Por lo tanto. Not a: Con el paso de las páginas. Una página PHP que utilice la primera forma es. pero nosotros sólo vamos a comentar dos: 1. la más recomendable es la primera.. utilizaremos la primera vía de escape de HTML: <?php .. Ya hemos utilizado una de ellas: <?= es una forma más corta de escribir <? echo.. escapará de HTML para entrar en PHP. sobre todo si el grupo de trabajo lo conforman varios programadores y diseñadores. por varias razones: Con independencia de la configuración de PHP. La hora es: <? echo date('H:i:s') ?>.. El capítulo dedicado a las plantillas propone algunas soluciones interesantes que le recomendamos. De forma que una página PHP puede ser como una página HTML normal y corriente. descubrirá que mientras mayor sea el proyecto para el que esté empleando PHP.

La función date() recibe como parámetro el formato en el que se mostrará. Si comenzamos una línea con la pareja de caracteres //. ?> La hora es: <?= date('H:i:s') ?>. No nos cuesta ningún esfuerzo modificar el programa que muestra la hora para añadir comentarios de esta forma: <?php // El siguiente programa muestra la hora // actual. La hora se representa como H y los segundos como s. // // La función date() recibe como parámetro el // formato en el que se mostrará. Los comentarios de párrafo comienzan con la pareja de caracteres /* y terminan con */. Todo lo que PHP encuentre en medio lo considerará un comentario. Comentarios PHP nos permite escribir texto que el preprocesador ignorará. Existen dos tipos de comentarios: de línea y de párrafo. lo que se conoce como comentarios. La hora se // representa como H y los segundos como s. dejaremos para otro momento hablar de ellas. a pesar de la existencia de comentarios al comienzo. La página HTML resultante del código anterior es exactamente la misma que se puede ver en la figura 2. Los comentarios son útiles para explicar qué intentamos hacer a lo largo de un determinado programa.3. esa línea será tomada por PHP como un comentario. . pero atención que para los minutos se utiliza i y no m. // // Las horas.De igual forma puede utilizar la función print() para que el parámetro que le pase se muestre en la página HTML resultante: La hora es: <? print(date('H:i:s')) ?>. Algo que hoy nos parece obvio puede ser difícil de entender cuando volvamos a ver el código pasados unos meses. así que podemos volver a escribir el código anterior así: <?php /* El siguiente programa muestra la hora actual. Aunque existen otras funciones para mostrar información. los minutos y los segundos se // separarán con dos puntos. // pero atención que para los minutos se // utiliza i y no m.

El resalte de sintaxis también tiene en cuenta los comentarios. Comentarios resaltados Truco: Lo más probable es que su IDE permita cambiar los colores de resalte de cada tipo de elemento del código PHP. la antigüedad del mismo y podrá partir con ventaja al conocer de mano del autor algo sobre el funcionamiento de la página.10. Podemos modificar la página PHP de prueba para que incluya ese encabezado. De esta forma.10. podrá ignorarlos sin dificultad cuando no le sean necesarios. Este encabezado podría contener el nombre del autor del código. Se trata de un ejemplo de página . pero podrá leerlos si lo desea. Le recomendamos que seleccione un color lo más apagado posible para los comentarios. Otra costumbre saludable es comenzar sus programas con un encabezado común. El resultado podría ser el siguiente: <?php /* Autor: Juan Diego Gutiérrez Gallardo Fecha: miércoles 24 de junio de 2009 Descripción: El siguiente programa muestra la hora actual. los minutos y los segundos se separarán con dos puntos. El resultado seguirá siendo el mismo.Las horas. o cualquier otra persona vuelva a trabajar con esa página sabrá sólo con echar un vistazo al encabezado contra el trabajo de quién va a luchar. El último fragmento de código se puede ver resaltado en la figura 2. */ ?> La hora es: <?= date('H:i:s') ?>. mostrándolos de un color diferente al del resto del código. Figura 2. la fecha en la que comenzó a escribirlo y una breve descripción del objetivo de dicha página. Cuando usted. pero que sea legible.

org/. dependiendo de las circunstancias. En la jerga de los programadores. La función date() recibe como parámetro el formato en el que se mostrará. los minutos y los segundos se separarán con dos puntos. Este espacio se encuentra en la memoria principal del ordenador. el nombre de éstas comienza siempre con el símbolo del dólar ($ ). Nuestras posibilidades estarían muy limitadas si eso fuese todo lo que podemos hacer en PHP. pero atención que para los minutos se utiliza i y no m.Se trata de un ejemplo de página dinámica muy sencillo. como el tiempo va pasando. El primer carácter a partir del $ debe ser una letra o un carácter de subrayado (_). Después puede incluir números. Para diferenciar las variables de otros elementos dentro de PHP. Una variable tiene un nombre. Por ejemplo: <?php . Variables Los datos no son etéreos. es necesario almacenarlos en algún lugar. ya sea para consultarlos o para modificarlos. La hora se representa como H y los segundos como s. En el ejemplo anterior. Por cierto. */ ?> La hora es: <?= date('H:i:s') ?>. Not a: Quizá le interese echar un vistazo a PHPDoc. A continuación veremos qué son las variables y de qué tipo las hay. cada vez que cargue la página el resultado será diferente. un tipo y un valor. ésta ha sido la última vez que utilizamos la forma abreviada de escapar de HTML. los segundos avanzando. Las horas. Para declarar una variable en PHP sólo tiene que escribir el nombre de la variable y asignarle un valor. Gracias a ellas nos acercaremos aún más a descubrir el verdadero potencial que hay tras PHP. en la RAM. Advert encia: Y mucho cuidado: PHP diferencia entre mayúsculas y minúsculas. es decir. Una variable es el lugar en el que vamos a guardar los valores que necesitaremos más adelante. reservar el espacio necesario para guardar dichos valores se conoce como "declarar una variable". Hemos comentado que a partir de una sola página PHP puede obtener diferentes páginas HTML. Su página Web se encuentra en la dirección http://phpdoc. un estándar para la documentación de PHP con el que Eclipse PDT es compatible.

En una variable. un valor booleano FALSE equivale al cero. Not a: A diferencia de otros lenguajes de programación. su tipo determina la naturaleza de los datos que almacena. PHP se reserva dos palabras para indicar esos valores: TRUE (verdadero) y FALSE (falso). $_hora = date('H:i:s'). decimales. Internamente. sino que lo determina el valor que se le asigna para crear la variable. Se trata de algo muy importante.<?php $hora = date('H:i:s'). $_1hora = date('H:i:s'). enteros. ¿Qué tipos de datos nos ofrece PHP? Tipos de datos PHP dispone de varios tipos de datos. ya que su nombre comienza con un número: $1hora = date('H:i:s'). Puede utilizar cualquier combinación de mayúsculas y minúsculas para escribir estos valores: PHP siempre los reconocerá. En el siguiente fragmento de código declaramos dos variables de tipo booleano: $millonario = false. $hipotecado = true. una línea de código se diferencia de la siguiente utilizando precisamente dicho carácter. recuerde utilizar dicho separador. esta declaración es incorrecta. De todos ellos vamos a ver los que más útiles le pueden ser durante el comienzo de su aprendizaje: tipos booleanos. $Hora = date('H:i:s'). mientras que cualquier otro valor numérico sería equivalente al valor booleano TRUE . Booleanos Una variable de tipo booleano puede tener dos posibles valores: verdadero o falso. cadenas y matrices. Las siguientes líneas son ejemplos de declaraciones correctas: $hora = date('H:i:s'). Para declarar una variable de este tipo sólo tiene que escribir su nombre y asignarle el valor correspondiente. en PHP el tipo de una variable no se declara de forma explícita. En PHP. El código anterior almacena en la variable $hora la hora tal y como la mostrábamos en los ejemplos anteriores. Enteros En una variable de tipo entero puede almacenar valores . ?> Advert encia: Es posible que se haya fijado en que aparece un punto y coma al final de la línea en la que se asigna un valor a la variable $hora . Sin embargo.

Decimales Una variable de tipo decimal puede contener cualquier número en coma flotante. En bloque.".enteros positivos y negativos. el decimal. incluido el cero. posiblemente el tipo de datos que más vamos a utilizar en PHP. Con comillas simples. Las cadenas entre comillas dobles tienen una característica añadida que las hace muy interesantes: si contienen el nombre de una variable existente. $j = -40. Por ejemplo: $i = 20. Existen límites en cuanto a los valores que puede almacenar en una variable de tipo entero. 3. Dicho límite depende del sistema operativo en el que PHP esté instalado.14. el contenido de la . Si quiere incluir una comilla simple dentro de una cadena de este tipo. PHP permite definir cadenas de tres formas diferentes: 1. así: $cadena = 'Esto es una comilla simple: \'. debe incluir una barra invertida antes del carácter. PHP transformará de forma automática esa variable al siguiente tipo de datos que vamos a ver. Tras ejecutar estas dos líneas. Una cadena de texto no más que una secuencia de caracteres. Con dobles comillas. 2. PHP sustituirá la variable por su valor. Not a: Paradójicamente. $cadena = "Un año tienen $i meses. Por ejemplo: $i = 12. lo que llamamos número en coma flotante utiliza como separador de decimales un punto. Cadenas Y llegamos a las cadenas. De esta forma.'. Si intenta asignar a una variable de tipo entero un valor superior al límite. Las cadenas más sencillas son las que se especifican entre comillas simples: $cadena = 'Esta es una simple cadena. Se trata de un convenio que varía entre países. $k = 0.'. la siguiente instrucción nos sirve para declarar una variable de tipo decimal: $pi = 3. Esto se debe a que la mayoría de la información que se va a mostrar en una página HTML es de este tipo.

tabuladores con \t . utilizaremos \" en el segundo. $cadena = <<<CADENA Esto es una cadena definida en bloque. Otra diferencia entre las cadenas con comillas simples y las cadenas con comillas dobles son los caracteres de escape. Truco: No se deje llevar por la tentación de rodear siempre sus cadenas entre comillas dobles porque sean más flexibles. no verá retorno alguno. CADENA. Se trata de la sintaxis más adecuada para cadenas de gran longitud. Podemos utilizar variables como en las cadenas de dobles comillas. Esto se debe a que HTML ignora los retornos de línea. Es mucho más sencillo manejar este tipo de cadenas en bloque que con las dobles comillas. Para separar su texto en diferentes líneas ha de utilizar la etiqueta <br/>.\n". así: $i = 12. habrá observado el trabajo con cadenas con PHP es mucho más . Lo veremos en algunos de los ejemplos posteriores. y algunos otros. Podríamos haber definido esa cadena utilizando dobles comillas. Esto es un ejemplo: $i. es muy similar al segundo tipo. La diferencia principal está en la forma de utilizarlas.\n Podemos utilizar variables como\n en las cadenas de dobles comillas. Igual que para incluir una comilla simple utilizábamos \' en el primer tipo de cadenas. Y nada mejor que utilizar un ejemplo para explicar cómo utilizar este tipo de cadenas: $i = 12.\n Esto es un ejemplo: $i. una serie de caracteres especiales que comienzan con la barra invertida. en bloque. Pero ¡atención! Si incluye un retorno de línea en una cadena de texto y luego muestra esa cadena en la página Web. Utilice comillas simples siempre que no sea necesario utilizar sustitución de variables. Pero también puede incluir retornos de línea con \n. principalmente porque no es necesario utilizar caracteres especiales para indicar los retornos de línea. Le recomendamos que consulte la documentación de PHP si desea más información al respecto de estos caracteres de escape. El tercer tipo de cadenas. el símbolo del dólar con \$ . $cadena = "Esto es una cadena\n definida en bloque. Esas ventajas tienen un inconveniente: PHP tardará más en procesarlas. Si conoce algún otro lenguaje de programación.".variable $cadena será "Un año tiene 12 meses.

Las matrices le permiten tener esa información mucho más organizada. Con lo aprendido hasta ahora podría hacerlo así: $peliculas_enero = 9. Es muy importante tenerlo en cuenta para no cometer errores al trabajar con matrices.en enero: $peliculas[0]. Puede añadir nuevos elementos a una matriz después de haberla creado. $peliculas_marzo = 21. con más posibilidades.en marzo: $peliculas[2]. Esto es aún más cierto para las matrices.en marzo: $peliculas_marzo.<br/> . Not a: El primer elemento disponible en una matriz es el cero (0). Para acceder a estos elementos sólo necesita indicar el índice de cada elemento tras el nombre de la variable. <br/> . Examinará entonces cuántos elementos aparecen entre los paréntesis.en enero: $peliculas_enero. Al utilizar la palabra reservada array para asignar valores a la variable $peliculas. $peliculas_febrero = 12. La siguiente es una de las posibles formas de declarar una matriz que contenga los tres valores anteriores: $peliculas = array(9. Hemos creado una matriz con tres elementos: el primero es 9. En otra parte del código podría utilizar estas instrucciones para mostrar dichos valores: echo <<<PELICULAS Películas vistas:<br/> . <br/> PELICULAS. . para añadir el número de películas vistas en abril: $peliculas[] = 17. <br/> PELICULAS. pudiendo acceder a través de una sola variable y utilizando un índice como modificador. Matrices Imagine que quiere guardar en variables el número de películas que ha visto cada mes del año.en febrero: $peliculas_febrero.en febrero: $peliculas[1]. 12. <br/> . entre corchetes. PHP comprende que queremos crear una matriz. 21). reservando el espacio necesario para poder guardarlos.<br/> . Por ejemplo. el segundo 12 y el tercero 21. Podría mostrar las películas vistas en cada mes con el siguiente código: echo <<<PELICULAS Películas vistas:<br/> .flexible.

esta sería una forma igualmente válida de declarar la misma matriz: $peliculas = array( 'enero' => 9. nuevo elemento y contenido La función print_r() nos presenta los datos que contiene la matriz de una forma muy curiosa. Matriz.11. aunque en realidad lo que queremos es traducir enero por un 9. Para ver el contenido de la matriz tras añadir este nuevo elemento. comenzando por el 0. 12. Así podemos ver que en la posición cero está el 9. en la dos el 21 y en la tres el 17. tras las matrices en PHP hay mucho más que lo que parece a primera vista. 'abril' => 17 ). En nuestro ejemplo de películas podríamos decir que queremos traducir el 0 por un 9. 'marzo' => 21. Por ejemplo. febrero por un 12. Figura 2. con los que podemos traducir de un valor a otro. . print_r($peliculas). el 1 por un 12 y así sucesivamente. $peliculas[] = 17. en la una el 12. tras los caracteres =>.PHP se encargará automáticamente de crear el cuarto elemento de la matriz. en lugar de tener que utilizar números? Pues podemos. Pero puede indicar los índices usted mismo y no limitarse a los números. La declaración de una matriz que hemos utilizado anteriormente es la versión simplificada de la misma. El código resultante podría ser el siguiente: <?php $peliculas = array(9. PHP crea los índices de forma automática. 'febrero' => 12. 21). ?> El resultado lo puede ver en la figura 2. Entre corchetes aparece el índice del elemento y a continuación. el valor del elemento. puede utilizar una función muy útil: print_r(). en la que sólo se asignan valores. etc. A continuación y entre paréntesis podemos ver los elementos que componen la matriz. ¿No sería fantástico poder hacer esa traducción. podríamos considerar que PHP nos proporciona diccionarios. que recibe como argumento una matriz.11. En realidad. Más que matrices. En primer lugar nos dice que se trata de una matriz con la palabra Array.

El resultado de utilizar print_r() con la matriz anterior puede verse en la figura 2. puede sin embargo dar lugar a confusiones. 'abril' => 17 ). Esta decisión.12. utilizando la siguiente sintaxis: $peliculas['mayo'] = 14.12. PHP ha considerado que el más adecuado es el primero libre. Para evitar este tipo de situaciones. Figura 2. PHP utilizará el siguiente que esté disponible. La matriz con la que hemos estado jugando hasta ahora sólo contenía números .13 nos muestra el resultado de utilizar print_r() con dicha matriz. asigne nuevos elementos a una matriz ya creada indicando el índice de los mismos.13. Índices no concordantes Not a: En algunos textos puede encontrar que a este tipo de matriz se le llama matriz asociativa. puesto que nosotros esperaríamos que el índice del mes de mayo fuese el 5. totalmente correcta. el cero. Matriz asociativa Como no hemos utilizado índice alguno. 'febrero' => 12. >$peliculas[] = 14. Considere las siguientes instrucciones: $peliculas = array( 'enero' => 9. Si no indica índice alguno. el que él crea más adecuado. Ha de ser cauto con los índices al añadir nuevos elementos a una matriz. Otra de las peculiaridades de las matrices de PHP frente a las de otros lenguajes es que no todos sus elementos deben ser del mismo tipo. 'marzo' => 21. porque permite asociar dos valores entre sí. pero ¿qué índice tendrá ese elemento? La figura 2. Ya sabe que la última línea añade un nuevo elemento a la matriz. Figura 2.

enteros, pero perfectamente podríamos haber añadido un nuevo elemento de tipo cadena.
Advert encia: Que algo sea posible no quiere decir que deba hacerlo. Aunque en determinadas circunstancias esta característica puede serle útil, le recomendamos que sea ordenado y metódico al programar. Si una matriz contiene valores enteros representando el número de películas vistas durante los meses del año procure que todos sus elementos sean enteros.

Hemos hecho un repaso de los tipos básicos de las variables con las que va a trabajar en los programas de PHP. Veamos ahora cómo realizar operaciones sobre ellas.

Operadores
Por sí sola, una variable tiene utilidad. Puede asignarle un valor (por ejemplo, la hora en un formato determinado) y luego mostrarla como respuesta a quién vea su página. Pero ya sabe que puede obtener el mismo resultado sin utilizar variables. El verdadero potencial de las variables se descubre cuando aprendemos a realizar operaciones sobre ellas. No se trata de nada que no conozca ya: si sabe sumar, restar y multiplicar, ya sabe qué son los operadores.
Not a: Tenga presente que PHP ofrece más operadores de los que vamos a ver en esta sección. Sólo los que vamos a ver son más que suficientes para realizar la mayoría de las tareas del resto del libro. Si está interesado en aprender más sobre los operadores que veremos y los que no veremos, no dude en consultar la documentación de PHP.

Operador básico de asignación
Ya hemos trabajado con el operador de asignación, el signo igual. Lo hemos utilizado en expresiones como:
$hora = date('H:i:s');

En dicha expresión, lo que está a la derecha del operador de asignación, el signo igual, se guarda en lo que está a la izquierda.

Operadores aritméticos
Son los que aprendimos a utilizar en la escuela, para sumar, restar, multiplicar y dividir. De forma bastante previsible, dispone de operadores para: Suma: +. Resta: -. Multiplicación: *. División: /. Combinando estos operadores con el operador de asignación puede comenzar a realizar tareas verdaderamente útiles. Por ejemplo, puede calcular la

suma de dos números:
$i = 2 + 3; echo $i;

Igual que suma valores numéricos directamente, también puede guardar esos valores en variables y posteriormente realizar la suma, así:
$i = 2; $j = 3; $i = $i + $j;

Existen unos operadores que combinan las asignaciones con los operadores aritméticos. Utilizando uno de estos operadores podemos volver a escribir el fragmento de código anterior de esta forma:
$i = 2; $j = 3; $i += $j; // Equivale a $i = $i + $j.

Lo mismo puede aplicarse al resto de operadores aritméticos, con lo que dispone de -=, *= y /=. Podríamos considerarlos como operadores extendidos de asignación.

Operadores de comparación
Permiten comparar dos valores. Como veremos más adelante, en el apartado dedicado a las instrucciones de control, nos basaremos en estas comparaciones para tomar decisiones en nuestro código. El resultado de utilizar este operador es un valor booleano (verdadero o falso), en función de si la comparación se satisface o no. Para realizar comparaciones dispone de varios operadores, que puede ver resumidos en la tabla 2.1.
Tabla 2.1. Operadores de comparación

O p eració n $i == $j $i != $j (o <>) $i < $j $i > $j

D escrip ció n TRUE si son $i es igual que $j. TRUE si son $i no es igual que $j. TRUE si $i es menor que $j.

TRUE si $i es mayor que $j. $i <= $j $i >= $j TRUE si $i es menor o igual que $j. TRUE si $i es mayor o igual que $j.

Operadores lógicos
Operan con valores booleanos, devolviendo TRUE o FALSE dependiendo de si se cumple una condición o no. Veremos cuatro operadores lógicos: and, or , xor y not . and El resultado de utilizar este operador sobre dos valores sólo es TRUE si los dos valores sobre los que se está realizando la operación son TRUE . Suponiendo que las variables $i y $j son de tipo booleano, la tabla 2.2 muestra las posibles combinaciones.
Tabla 2.2. Posibles combinaciones de and

$i FALSE FALSE TRUE TRUE

$J FALSE TRUE FALSE TRUE

$i an d $j FALSE FALSE FALSE TRUE

or A diferencia del operador and, el resultado de utilizar or sobre dos valores sólo es FALSE si los dos valores sobre los que se está realizando la operación son FALSE . De nuevo suponga que las variables $i y $j son de tipo booleano; la tabla 2.3 muestra las posibles combinaciones.
Tabla 2.3. Posibles combinaciones de or

$i FALSE FALSE TRUE TRUE

$j FALSE TRUE FALSE TRUE

$i o r $j FALSE TRUE TRUE TRUE

xor Devuelve TRUE cuando los dos valores son distintos. Puede verlo en la tabla 2.4.
Tabla 2.4. Posibles combinaciones de xor

$i FALSE FALSE TRUE TRUE

$j FALSE TRUE FALSE TRUE

$i xo r $j FALSE TRUE TRUE FALSE

not El operador not es un operador unario, puesto que se aplica a una sola variable, en contraste con el resto de operadores lógicos que hemos visto, que son binarios. En la tabla 2.5 puede ver los posibles valores que obtiene al aplicar este operador a una variable booleana.
Tabla 2.5. Posibles combinaciones de not

$i FALSE TRUE

! $i TRUE FALSE

Operadores de incremento
Y también de decremento. Gracias a estos operadores puede simplificar operaciones como éstas:
$i = $i + 1; $i = $i - 1;

Que son equivalentes a las siguientes:
$i++; $i--;

Aunque ayudan a simplificar, en ocasiones pueden

complicarlo todo. PHP le deja situar estos operadores antes y después de la variable a la que modifican, pero dependiendo de dónde los coloque el resultado puede variar. Comprobarlo es muy sencillo:
$i = 1; $j = $i; // Tanto $i como $j valen 1. echo $i++; echo '<br/>'; echo ++$j;

Mientras que el resultado de la primera expresión de salida es uno, el de la segunda es dos. Esto es así porque PHP entiende que si sitúa el operador de incremento después del nombre de la variable, querrá realizar la operación después del resto de operaciones (en este caso, una operación de salida), mientras que situarla antes del nombre de la variable da prioridad al incremento, que se realiza antes de cualquier operación. Por lo tanto, preste especial atención a este tipo de operadores: puede que obtenga resultados imprevisibles si no anda con cuidado.

Concatenación de cadenas
La operación más importante que puede realizar sobre una cadena es la concatenación: unir dos cadenas para formar una sola. Para ello PHP ofrece un operador que puede ver en funcionamiento a continuación:
$cadena1 = 'Esto es'; $cadena2 = 'una cadena.'; $cadena3 = $cadena1.' '.$cadena2; echo $cadena3;

El resultado de esta operación es la cadena "Esto es una cadena.". Como habrá podido observar, el operador de concatenación es un punto que habrá que situar entre las cadenas que quiera unir. Igual que en las operaciones aritméticas, puede combinar una concatenación con una asignación para simplificar el código, así:
$cadena1 = 'Esto es'; $cadena2 = 'una cadena.'; $cadena1 .= ' '.$cadena2; echo $cadena1;

El resultado será el mismo en ambos casos.

Precedencia de operadores
Debe estar siempre seguro del orden en el que PHP realizará las operaciones que le indique. ¿Lo está ahora? ¿Cuál será el resultado de esta operación, qué contendrá $i?
$i = 2 + 3 * 2;

¿Contendrá 10? ¿Contendrá 8? Depende de la precedencia que tengan los operadores. En este caso concreto, el resultado será 8, porque el operador de

multiplicación tiene prioridad sobre el de suma. Pero ¿y si quisiera que la suma se realizase antes que la multiplicación? Puede modificar la precedencia de los operadores utilizando paréntesis para envolver las operaciones que quiera realizar antes. La operación anterior puede ser modificada para obtener 10 como resultado:
$i = (2 + 3) * 2;

PHP realizará primero la operación que está entre paréntesis, cuyo resultado es cinco. A continuación multiplicará ese valor por dos, y el resultado, diez, lo almacenará en $i.

Cambios de tipo
Como resultado de las diferentes operaciones que realice sobre las variables, es posible que modifique el tipo de alguna de ellas. Sí, pero es normal. Imagine que realiza la siguiente operación:
$i = 100; // Una variable de tipo entero. $cadena = 'veces'; // Una cadena. // Concatenamos el número y la cadena. $i .= ' '.$cadena; echo $i;

¿Cuál será el resultado de estas operaciones? En la página Web resultante podrá leer el texto "100 veces". ¿Ha ocurrido algo más? Vamos a ayudarnos de la función gettype(). Esta función recibe como argumento el nombre de una variable y devuelve una cadena de texto que contiene el tipo de la variable pasada. Cambiemos el código anterior por el siguiente:
$i = 100; // Una variable de tipo entero. $cadena = 'veces'; // Una cadena. echo 'Tipo de $i: ' . gettype($i) . '<br>'; // Concatenamos el número y la cadena. $i .= ' ' . $cadena; echo $i; echo '<br/>'; echo 'Tipo de $i: ' . gettype($i);

Como puede comprobar, antes de la concatenación $i es de tipo entero (integer ), pero después pasa a ser de tipo cadena (string). Para liar aún más las cosas, resulta que también podemos hacer esto otro:
$cadena = 'Soy una cadena'; echo gettype($cadena) . '<br>'; $cadena = 20; echo gettype($cadena);

Y hemos cambiado el tipo de una variable que era una cadena a un entero. ¿Qué está pasando?

PHP no permite que declare el tipo de una variable. En su lugar, es el contexto el que determina su tipo. Así, si asigna un valor numérico a una variable, su tipo será numérico. Si posteriormente concatena ese valor con una cadena, el tipo resultante será una cadena. Esta flexibilidad es muy útil, ya que permite realizar concatenaciones entre números y cadenas sin necesidad de realizar conversiones de tipo de forma explícita. La contrapartida: ha de ser muy cauto si no quiere obtener resultados imprevisibles. Si lo necesita puede comprobar el tipo de las variables utilizando la función gettype(), aunque también puede aprovecharse de otra de las características de PHP y forzar el tipo de las variables. Puede obligar a que una variable de un tipo determinado se comporte como una de otro tipo con solo indicar entre paréntesis y antes de la variable el tipo que desea. Así, puede conseguir que una variable de tipo cadena se comporte como una de tipo entero:
$cadena = '10'; $entero = (integer) $cadena; echo gettype($cadena); echo '<br/>'; echo gettype($entero);

Lo mismo puede aplicarse al resto de tipos, cuyos nombres en inglés puede consultar en la documentación de PHP. Tenga precaución, sin embargo. En el ejemplo anterior $entero contendrá el valor entero 10, pero si $cadena hubiese contenido la cadena "texto" , el resultado sería que $entero contendría el valor 0:
$cadena = 'texto'; $entero = (integer) $cadena; echo $entero;

Por regla general, si la conversión entre tipos no resulta posible, PHP asignará valores predeterminados, como el cero o una cadena vacía. Hay que reconocer que, hasta ahora, lo que hemos visto en este capítulo no ha sido muy divertido. Pero prometemos que esto va a cambiar, porque en los siguientes apartados vamos a examinar las instrucciones de control, que utilizan las variables que acabamos de ver para conseguir que el contenido de la página HTML resultante de procesar la página PHP sea dinámico.

Instrucciones de control
En un programa escrito en PHP las instrucciones de control constituyen las herramientas más importantes para hacer que sus páginas sean dinámicas. Son estas instrucciones las que le permiten evaluar el contenido de las variables y tomar decisiones en consecuencia.

hemos visto cómo crear una página en la que aparece un elemento que cambia en cada llamada. si la vemos después de las 12. realizará la acción que haya escrito. aunque no se trata de un mensaje . que en su expresión más sencilla tiene este aspecto: if (condición) acción PHP evalúa la condición. Pues esto y mucho más es lo que vamos a conseguir con las instrucciones de control. la hora. si la hora es menor que las 12. Si el resultado de esta evaluación es TRUE . Ya sabe cómo hacerlo. Así podrá indicar la acción a seguir en caso de que la condición no se cumpla: <?php $hora = date('H'). la acción asociada se ejecutará. escriba un mensaje indicando que aún no es mediodía. Pero ¿no sería mucho más interesante poder cambiar el contenido de la página dependiendo de la hora? Por ejemplo. En caso contrario. Por ejemplo. De hecho. Instrucciones condicionales Como su propio nombre indica.. else echo 'Ya es mediodía. Algo así: <?php $hora = date('H'). entonces. si ambos valores coinciden. Concretando aún más. la página estará en blanco. Este mensaje podría decir "Buenos días" si la hora está entre las 8 y las 14. Puede mejorar este pequeño programa utilizando else junto con if. algo que también sabe hacer gracias al trabajo que ha realizado con los operadores. if ($hora < '12') echo 'Aún no es mediodía.'. de las que existen dos tipos: las condicionales y las iterativas. podríamos mostrar un mensaje de saludo.Sí.'. permiten determinar qué acciones realizar en función de una condición. Y. puede almacenar la hora en una variable.'. La más simple de este tipo de instrucciones es if. "Buenas tardes" desde las 14 hasta las 19 y "Buenas noches" de las 19 hasta las 8. if ($hora < '12') echo 'Aún no es mediodía. ?> El resultado del código anterior variará dependiendo de si vemos la página antes o después de las 12. la acción se ignora y no se ejecuta. Después puede comparar ese valor con uno en concreto. ?> ¡Esto marcha! Ahora el que vea la página siempre obtendrá un mensaje..

se cumpla o no se cumpla la condición.'.'. else echo 'El mediodía ya pasó. vamos a utilizar una nueva instrucción condicional. if ($hora < '12') echo 'Aún no es mediodía. es decir. la que nos avisa que queda menos para ir a comer. Examine este fragmento de código y díganos el resultado si se ejecuta antes de las 12 del mediodía: <?php $hora = date('H'). ?> Las instrucciones condicionales pueden anidarse. una pregunta con trampa. ?> Ahora. else echo 'Es mediodía.'.muy exacto si lo ve pasadas las 12. if ($hora < '12') echo 'Aún no es mediodía. else echo 'El mediodía ya pasó. else if ($hora == '12') echo 'Ya es mediodía. A esa hora ya no es mediodía.'. pueden escribirse unas dentro de otras. cuando ya hayan pasado las 12 y (el caso que no cubríamos) cuando sean las 12 en punto: <?php $hora = date('H'). ¿verdad? Para ser más precisos en nuestros mensajes. Su respuesta sería correcta si volviésemos a . Para solucionar ese problema puede utilizar las llaves ({}).'. la última línea. elseif. ¡la respuesta no es correcta! Aunque el fallo no será por desconocimiento.'. que permiten asociar grupos de líneas a cada parte de la condición. echo '¡Queda menos para ir a comer!'. si no porque no le hemos dicho que a cada parte de la condición sólo se asocia una instrucción. elseif ($hora == '12') echo 'Ya es mediodía. gracias a lo que podemos volver a escribir el código anterior así: <?php $hora = date('H'). if ($hora < '12') echo 'Aún no es mediodía.'.'. Es decir. que permite evaluar una nueva condición en caso de que la anterior no se cumpliese. digamos a las 8 de la tarde. ?> Si su respuesta fue que sólo veremos el texto "Aún no es mediodía". Podemos entonces ejecutar instrucciones cuando aún no sean las 12. se ejecuta siempre.

'. .'.<br/>'. }elseif ($hora == '19'){ echo 'Hasta mañana. }elseif ($hora == '14'){ echo 'Que aproveche.. switch ($hora){ case '9': echo 'Bienvenido al curro. break. } ?> PHP nos proporciona otra instrucción condicional que permite escribir un programa equivalente al anterior. }elseif ($hora == '16'){ echo 'Lástima de siesta. a las 14 sale a comer.<br/>'.'. case '16': echo 'Lástima de siesta.'. if ($hora < '12'){ echo 'Aún no es mediodía.'. case '19': echo 'Hasta mañana.. case '14': echo 'Que aproveche. aunque a cada parte sólo asocie una línea de código. Utilizando instrucciones if y else puede complicar el programa anterior todo lo que quiera.'. para informar de que a las 9 de la mañana entra a trabajar.. if ($hora == '9'){ echo 'Bienvenido al curro. por ejemplo. comprobando la hora y escribiendo mensajes en función de la misma.'. echo '¡Queda menos para ir a comer!<br/>'.. Podría olvidar incluirlas si más adelante decide añadir una línea más alguna de las partes de la condición.escribir el código anterior así: <?php $hora = date('H'). a las 16 vuelve a entrar y a las 19 se va para casa escribiría el siguiente código: <?php $hora = date('H'). pero de forma más clara: la instrucción switch.'. } ?> Not a: Le recomendamos que siempre utilice llaves con sus instrucciones condicionales if . break. Así. }else{ echo 'Es mediodía. El resultado de utilizarla sería el siguiente: <?php $hora = date('H'). break. lo que podría provocar un fallo en la lógica de su programa.

'. De ella hablaremos más adelante.. expresión3) acción . PHP recorrerá cada instrucción case..echo 'Hasta mañana. que permite ejecutar un bloque de instrucciones un número concreto de veces. Si son iguales. switch ($hora){ case '9': echo 'Bienvenido al curro. Bucle For La primera que vamos a ver es la instrucción for . Después escribimos las instrucciones asociadas a cada caso. break. Puede utilizar la instrucción default . break. } ?> Instrucciones iterativas Estas instrucciones permiten ejecutar un bloque de código tantas veces como sea necesario. cuando no haya un case que satisfaga la igualdad. Not a: La instrucción break es la que marca la salida del swit ch. case '19': echo 'Hasta mañana. La sintaxis de esta instrucción es la siguiente: for (expresión1.'. break. case '14': echo 'Que aproveche. comparando el valor de $hora con el valor correspondiente. con lo que el código resultante mostraría un mensaje de su elección cuando la página se vea a una hora que no esté contemplada: <?php $hora = date('H'). ejecutará las instrucciones asociadas con ese case y terminará de ejecutar la instrucción switch. break. Incluso puede indicar qué hacer en caso de que no se cumpla ninguna de las condiciones. case '16': echo 'Lástima de siesta. es decir. mientras se cumpla una determinada condición. break.'.'. } ?> Como puede comprobar.'. le indicamos a la instrucción sobre qué variable se realizarán las comparaciones.'. expresión2. default: echo 'A trabajar.

escribe el mismo texto: <?php for ($i = 1. Esto sólo se hace la primera vez. lo primero que hace es evaluar expresión1. Las iteraciones continuarán mientras se evalúe como TRUE . a incrementar el valor de $i. la condición se cumple. Sólo lo hace la primera vez. Al encontrar el cierre de llave descubre que la primera iteración ha terminado. Segunda iteración: comparamos el valor de $i con 3. El siguiente fragmento de código contiene un bucle for que se ejecuta tres veces. $i++){ echo 'Probando un bucle for. Cada vez que se termine una vuelta en la instrucción de iteración se evaluará expresión3. Volvemos a ejecutar la instrucción echo(). expresión2: Antes de comenzar cada iteración. después de haber sido incrementada. Ejecución de un bucle for El siguiente es un ejemplo mucho más vistoso de bucle . se evaluará expresión2.14. $i <= 3.. pero como $i vale 2. La cuarta vez que pasemos por la comparación. que incrementa en uno el valor de $i. Figura 2. comprueba que $i no sea mayor que 3. la condición se cumple.<br/>'. expresión3: Al terminar cada iteración. Resumiendo: expresión1: Sólo una vez. Como $i contiene 1. la comparación se evaluará como FALSE y habrá terminado la ejecución del bucle for. así que ejecuta la instrucción echo().. a compararlo con 3 y a ejecutar la instrucción echo. El resultado de ejecutar este código puede verse en la figura 2. A continuación. Cada vez que se dé una vuelta en la instrucción de iteración. } ?> Cuando PHP encuentra el bucle for. Cada vez que lo hace. así que vuelve al comienzo del bucle y evalúa la tercera de las expresiones. asigna 1 a la variable $i.14. al comienzo del bucle.Cuando PHP encuentra una de estas instrucciones. $i valdrá 4.

'marzo' => 21. Puede utilizar este bucle así: foreach (matriz as $valor) acción El bucle se ejecutará tantas veces como elementos tenga la matriz.15. $i <= $meses. Esa matriz podría ser. Bucle For Each Traducido como "para cada".'>Bucle for</h'. } ?> En la figura 2. } ?> Vaya. Vamos a solucionarlo utilizar otra instrucción de iteración: foreach.$i. . ': ' . 'febrero' => 12. for ($i = 1. Claro. son cadenas de texto.for: <?php for ($i = 1. con foreach puede recorrer todos los elementos de una matriz sin necesidad de saber cuántos elementos la componen. // ¿Cuántos meses hay en la matriz? $meses = count($peliculas). cuyo valor se irá guardando dentro de $valor .15 puede ver el efecto del código anterior. Figura 2. '<br/>'. la que contenía las películas vistas durante cada mes: <?php $peliculas = array( 'enero' => 9. $i <= 3. $i++){ echo '<h'. En cada iteración. 'abril' => 17 ).$i.'>'. el resultado de ejecutar este bucle no es el esperado. resulta que los índices utilizados no son números. $peliculas[$i] . por ejemplo. Encabezados dinámicos Un bucle for puede utilizarse para recorrer todos los elementos de una matriz y mostrar su contenido. $i++){ echo $i . se avanzará al siguiente elemento.

'. Bucles While En su forma más sencilla. } ?> Puede ver el resultado de usar foreach en la figura 2. foreach ($peliculas as $mes => $vistas){ echo 'En ' . mientras se cumpla la condición.<br/>'. Esto le puede ser de mucha utilidad en el ejemplo de las películas por mes: <?php $peliculas = array( 'enero' => 9. la condición no se cumpla y se pueda salir del bucle. . 'abril' => 17 ). 'marzo' => 21. ejecutamos la acción. PHP ofrece otras dos instrucciones de control que iteran mientras se cumplan una serie de condiciones: los bucles while y do while. ' vi ' . 'febrero' => 12. que puede ser conocido previamente. Esta acción puede ser un bloque de instrucciones envuelto entre llaves. Pero también puede ejecutar el bucle foreach de esta otra forma: foreach (matriz as $clave => $valor) acción Con esta segunda forma también tendrá acceso al valor del índice asociado con el valor.16. en un momento dado. Figura 2. $vistas .Dentro del bloque de código asociado al bucle puede realizar operaciones con ese valor. La acción puede modificar los factores que se evalúan en la condición para que. Uso de foreach Las dos instrucciones de iteración que acabamos de ver se ejecutan un número determinado de veces.16. el bucle while sigue la sintaxis: while (condición) acción Es decir. $mes .

Compara el segundo actual con cero.'. terminará la ejecución del bucle y llegará a la instrucción echo. Advert encia: Asegúrese de que siempre exista un camino de salida de estos bucles. aunque buscamos el mismo objetivo. Como consecuencia. el cuerpo del bucle do while se ejecuta al menos una vez. echo 'Comienza un nuevo minuto. A continuación. donde vuelve a obtener el valor del segundo. ?> El resultado de este bloque de código es ligeramente diferente al anterior. }while($segundo != '0'). PHP vuelve a comparar el contenido de la variable $segundo con cero y sigue iterando mientras se cumpla la condición. La otra variante de este bucle sigue la siguiente sintaxis: do acción while(condición) Este bucle sigue las mismas premisas que el anterior. comienza el bucle while. Dejando a parte diferencias de sintaxis. Si no es cero.Por ejemplo. pero con algunas salvedades que comprenderemos mejor con un ejemplo: <?php do{ $segundo = date('s'). la página Web nunca le sería devuelta al que desee verla. Salida de bucles . entre en el cuerpo del bucle.'. Por lo tanto. puede crear un bucle de este tipo que mantenga el control mientras el segundo de la hora en la que nos encontremos no sea cero: <?php $segundo = date('s'). mientras que en el bucle while podría darse el caso de que el cuerpo del bucle no se ejecutase ninguna si $segundo valiese cero desde el principio. while($segundo != '0'){ $segundo = date('s'). que le muestra un mensaje. Cuando eso ocurra. debe utilizar do while cuando quiera que el cuerpo del bucle se ejecute al menos una vez y while en caso contrario. ?> Este sencillo programa guarda en la variable $segundo el segundo en el que se encuentra. Pero tarde o temprano no se cumplirá. En caso contrario PHP no podría terminar la ejecución del bucle y el programa se ejecutaría indefinidamente. } echo 'Comienza un nuevo minuto.

suponga que no quiere estar esperando demasiado tiempo a que acabe el minuto.<br/>'. '. 'febrero' => 12. 'abril' => 17 ). foreach ($peliculas as $mes => $vistas){ if ($vistas == 0){ continue. echo 'Comienza un nuevo minuto. Una de ellas ya la vio cuando aprendió a utilizar la instrucción switch: se trata de break. Si está en los primeros diez segundos del minuto y no quiere permanecer dentro del bucle el código resultante sería el siguiente: <?php do{ $segundo = date('s').'. Hemos modificado el mes de marzo para que el número de películas sea cero: <?php $peliculas = array( 'enero' => 9. Si en alguno de los meses no se vio ninguna película se continuará con la siguiente iteración y no se mostrará información alguna. 'marzo' => 0. ?> continue Utilice continue cuando quiera saltarse el resto de líneas de código asociadas a un bucle y continuar con la siguiente iteración. } ?> . ' vi ' . break Puede utilizar esta instrucción para detener la ejecución de los bucles for . foreach. Cuando PHP encuentra esta instrucción dentro del cuerpo de código asociado al bucle entiende que quiere salir de él y continuar con el resto de líneas del programa. while y do while. Podría utilizarlo en el ejemplo de las películas vistas cada mes. Podría utilizar esta instrucción en un bucle do while del que quiera salir antes de que se cumplan todas las iteraciones.Es posible alterar el flujo de la ejecución de un bucle mediante algunas instrucciones especiales. } echo 'En ' . $vistas . } }while($segundo != '0'). En el ejemplo anterior. $mes . if ($segundo <= '10'){ break.

el código anterior sólo mostrará información sobre los meses de enero. ¿verdad? Y eso que hemos dejado muchos temas en el tintero. febrero y abril. . como la escritura de funciones o cómo reutilizar código.Como resultado. Ha sido duro. una terapia de choque. ¡Enhorabuena! Acaba de pasar por un intenso curso de aprendizaje de PHP.

Quienes necesiten extraer información de esos datos sólo tienen que realizar una consulta a la base de datos. modificación (para cambiar los datos almacenados) y borrado (para eliminar datos obsoletos o incorrectos). La figura 3. consulta (para extraer información). Considere este tercer capítulo como una unidad autosuficiente en la que creará su primera base de datos. En resumen. Cuando se es nuevo en el mundo de las bases de datos. para desempeñar su trabajo con MySQL y PHP. Tras muchos años la situación ha cambiado radicalmente.1 simboliza las relaciones entre estos elementos. Las tablas que mantienen datos que tienen que ver entre si están agrupadas en un mismo contenedor: la base de datos. Acompáñenos en el descubrimiento de las bases de datos y. con diferentes tablas para cada grupo de datos con características comunes. dueños de sortilegios para desfacer cualquier entuerto. al menos. pero para ello han tenido que coincidir mil circunstancias. en concreto. Sus administradores eran considerados poco menos que magos. qué es una base de datos. lo que veamos en este capítulo le servirá para tener una visión de conjunto de las operaciones necesarias para manejar un sistema gestor de bases de datos. desde los cimientos hasta los procedimientos más complejos.3 MySQL El mundo de los sistemas gestores de bases de datos ha estado reservado a una élite desde el principio. hasta completar todas las tareas que debería controlar o. En capítulos sucesivos profundizaremos en estos conocimientos. . Y eso es algo que no se puede aprender con teoría. que verá funcionando y sobre la que aprenderá a realizar operaciones de inserción (para incorporar nuevos datos). de la más utilizada en el mundo del software libre. lo más complicado es llegar a entender de qué se nos está hablando. Le permite mantener todos los datos que nos interesan en un formato tabular unificado. conocer. Bases de datos Una base de datos es una buena forma de organizar y compartir información. Es necesario pasar a la acción.

. es común para la mayoría de sistemas gestores de bases de datos que existen hoy en día.1. Existe un lenguaje especialmente diseñado para realizar consultas a bases de datos. llamado SQL. como intenta representar la figura 3. pudiendo realizarse varias consultas de forma simultánea y desde diferentes ubicaciones geográficas. la información se extrae a partir de esos datos: en qué películas ha participado. su fecha de nacimiento. SQL son las siglas de lenguaje estructurado de consultas (Structured Query Language). base de datos y consulta Not a: Fíjese en la diferencia entre datos e información. etcétera).Figura 3.2. etc.1 se ha extendido. Tablas. el modelo representado en la figura 3. Sin embargo. Gracias a este lenguaje podemos realizar preguntas a los servidores de bases de datos. En el caso de un actor. cuántas son en total. Desde la aparición de las redes informáticas. los datos representan hechos acerca de él (su nombre. Este lenguaje.

En la figura 3. Los datos de John Cleese C amp o Nombre Apellidos Fecha de nacimiento Ubicación de la foto Valo r John Cleese 1939-10-27 /fotos/actores/john_cleese. se trata de la página dedicada a ese actor en IMDb (en la dirección http://imdb.com/).jpg . La publicación Web puede verse como una forma más de permitir consultas simultáneas a través de redes. En concreto. se ha desarrollado la tecnología necesaria para publicar bases de datos a través de medios muy asequibles para el público en general. John Cleese. más o menos como estarían almacenados dentro de una base de datos.1. Consultas remotas simultáneas Más aún.3 podemos ver cómo se mostrarían en una página Web. La tabla 3.Figura 3.1 muestra los datos de un determinado actor.2. Tabla 3.

que utilizan como el enlace entre las bases de datos y la Web alguno de los lenguajes antes mencionados. con el servidor de páginas Web Apache. John Cleese en IMDb Como puede comprobar. podrá aprovechar lo que vea en este libro sin ningún esfuerzo tanto en Mac OS X como en Linux. trabajando sobre la misma base de datos. Es precisamente en este tipo de aplicaciones donde MySQL tiene mayor aceptación. ¿Qué es una tabla? . tenga acceso a él. Python o Perl.Figura 3. Not a: Apache. MySQL y los lenguajes mencionados pueden funcionar sobre Windows. a lo largo de las páginas de este libro utilizaremos principalmente el sistema operativo de Microsoft.3. Apache. la página Web muestra las referencias que la base de datos tiene del actor. aplicaciones desarrolladas sobre Linux. sencillamente. Sin embargo. lo que facilita la localización de los datos que más interesantes. La razón por la que se ha escogido Windows en lugar de Linux o Mac OS X es. en el grupo de aplicaciones conocido como LAMP : Linux. presentadas de una forma más atractiva. MySQL y PHP. Se lo dice alguien que trabaja con los tres a diario. que aún sigue siendo el sistema operativo más utilizado del mundo. lo que permite hablar también de WAMP. lo que hace mucho más probable que usted. De hecho. pero distribuidas de manera que sean legibles por un ser humano. Además de poder utilizar una interfaz Web para la consulta de la información también se puede utilizar para la introducción de los datos. Este modelo de trabajo es muy versátil: los encargados de la tarea pueden estar en diferentes ubicaciones geográficas. lector.

En el mundo de las bases de datos. poder pasar una lista de las mismas a otros videoadictos o controlar a quiénes ha prestado alguna. En el mundo de la carpintería es otra cosa. incluso en varios ordenadores diferentes. ni entre base de datos y archivo ya que por cuestiones de rendimiento y aprovechamiento de espacio. Incluso los hay que tienen un verdadero videoclub en el salón. una tabla es un "lugar" en el que se almacenan una serie de datos de similares características. Si su caso es este último seguro que no tendrá dificultad para comprender la utilidad de una base de datos de películas: mantener un control sobre cuáles tiene en su colección. Antaño. son interesantes. Estas posibilidades. este "lugar" con el que nos hemos referido a una tabla era un archivo y dentro de este archivo se organizaban los datos. Una tabla. En este caso concreto se trata de información de texto. con una longitud máxima de 64 caracteres. Hoy en día no es correcto establecer una relación directa entre tabla y archivo.4 podemos ver un ejemplo de tabla. En la figura 3. Pero gracias a organizar los datos de las películas en una base . cada una de un determinado tipo. una base de datos y una tabla pueden estar dispersos en varios archivos.4. sus campos y sus registros Todos los datos pertenecientes a la misma columna de una tabla (el título de las películas. Se llama registro a cada una de las filas de una tabla. Figura 3. Base de datos de ejemplo Quien más y quien menos tiene alguna película en su casa. La mayoría tiene más de una. ya de por sí. por ejemplo) son del mismo tipo. Los datos pertenecientes a un mismo elemento están organizados en campos o columnas.

cuáles son de un determinado año. una que funciona igual en cualquier sistema operativo: la consola. la tabla de películas. cuáles las protagoniza un determinado actor. poder hacer preguntas y conseguir respuestas. A continuación crearemos la base de datos que contendrá los datos de las películas y. Comenzaremos la creación de la base de datos de ejemplo de forma muy sencilla. escriba: mysql -u root -p Pulse la tecla Intro. deberá hacer clic en Inicio>Todos los programas>Accesorios>Símbolo del sistema. si está utilizando el sistema operativo Windows. . pero cubren a la perfección lo necesario para este ejemplo. Si está utilizando XAMPP bastará que pulse la tecla Intro de nuevo. Más adelante veremos dichos tipos de datos. Se le pedirá que introduzca la contraseña del usuario root .6. Cuando tenga acceso a la consola. La figura 3. Para ello.5. Si está utilizando Linux tendrá que abrir un terminal. y una línea describiendo cada columna de la tabla. El terminal de Mac OS X se encuentra en la carpeta de utilidades. dentro de ella. como poder consultar cuáles de sus películas fueron dirigidas por un determinado director. Son pocos datos. en definitiva. almacenando sólo el título de la película. Figura 3. Puede verlo en la figura 3. el nombre del director y el de uno de los actores. En esta tabla guardará los datos de las películas de su colección. con el nombre a la izquierda y el tipo de datos a la derecha.5 muestra el diseño de esta tabla: el nombre de la misma en la parte superior. Herramientas de consulta Vamos a utilizar la más sencilla de las herramientas de consulta a nuestra disposición. El objetivo de este ejemplo es que comprenda lo que se puede hacer con una base de datos. puesto que dicho usuario no tiene contraseña alguna asignada. Nuestra tabla de películas Not a: No se preocupe en absoluto por el significado de los tipos de datos.de datos obtendrá otras ventajas de forma automática.

abra un terminal (utilizando la aplicación del mismo nombre que se encuentra en la carpeta de utilidades). añadiendo la ruta en la que se encuentre MySQL instalado (por ejemplo.6. Si no quiere tener que escribir la ruta completa de cada una de las órdenes de MySQL que necesite ejecutar tendrá que modificar la ruta del sistema. Active la ficha Opciones avanzadas. en el panel de la izquierda del cuadro de diálogo que aparecerá. Si utiliza Windows tendrá que modificar las variables de entorno de su sistema. el programa esperará que se le indique qué órdenes desea ejecutar. haga clic en Variables de entorno y accederá al cuadro de diálogo Variables de entorno. Añada al final la nueva ruta y guarde los cambios realizados. que le permitirá modificar la variable Path. escriba la orden nano . la orden para conectar el servidor de bases de datos sería: /usr/local/mysql/bin/mysql -u root -p Hemos tenido que escribir la ruta completa de la orden para poder conectar con el servidor de bases de datos. XAMPP no incluye las órdenes de MySQL en la ruta del sistema. C:\xampp\mysql\bin\) a la variable Path. antes de $PATH: export PATH=/opt/local/bin:/opt/local/sbin: /usr/local/mysql/bin:$PATH Guarde los cambios realizados y cierre el terminal. La . Lamentablemente. En Windows Vista podrá llegar al cuadro de diálogo correspondiente haciendo clic con el botón derecho sobre Equipo. Podrá ver el cuadro de diálogo Propiedades del sistema. Cliente de MySQL Cuando introduzca la contraseña correcta. y seleccionando la opción Propiedades del menú desplegable que aparecerá. es aquella en la que estará al abrir el terminal) y pulse la tecla Intro. en el explorador de archivos. si MySQL se encontrase instalado en /usr/local/mysql/. En Linux o Mac OS X. Para ello. Podrá ver una línea similar a ésta: export PATH=/opt/local/bin:/opt/local/sbin:$PATH Añada /usr/local/mysql/bin al final. A continuación haga clic en Configuración avanzada del sistema.profile estando en su carpeta personal (por lo general.Figura 3.

mientras que los nombres de bases de datos. es decir. actor VARCHAR(128) ). sólo a los nombres de bases de datos y tablas. la creación de la base de datos. como los acentos. Sin entrar a comentar el significado de cada línea de este script. También se habrá fijado en que las palabras reservadas del lenguaje que utilizamos para dar órdenes a MySQL están en mayúsculas. De ello se encargan las dos primeras líneas de este script: DROP DATABASE IF EXISTS videoteca. Creación de la base de datos Es el primer paso. CREATE DATABASE videoteca. Aunque existen varios métodos para crear bases de datos con MySQL. Esto no es aplicable a los datos que luego contendrán. omitimos el acento. Un script es un fragmento de texto con instrucciones para MySQL. USE videoteca. por lo que evitaremos utilizarlos en los nombres de bases de datos y tablas siempre que sea posible.próxima vez que vuelva a abrir un terminal tendrá acceso a las órdenes de MySQL sin necesidad de escribir la ruta completa de acceso. DROP TABLE IF EXISTS pelicula. aunque mientras el contenido del archivo sea correcto. el más versátil consiste en la utilización de scripts. Not a: Habrá notado que estamos escribiendo pelicula y no película . La razón es que no todas las herramientas de acceso a datos se comportan igual con los caracteres internacionales. ya se puede apreciar que parece que estemos dando órdenes en inglés. tablas y campos están en minúsculas. Por lo general. El nombre de la base de datos que vamos a crear será videoteca. la extensión no es demasiado importante. está mucho más próximo al lenguaje natural que a uno de programación. La extensión SQL se utiliza porque el lenguaje utilizado para escribir estos scripts es precisamente ese. director VARCHAR(128). estos scripts se guardan en archivos de texto con la extensión SQL. Se trata de un convenio ampliamente aceptado que permite diferenciar de un vistazo las diferentes partes de estas instrucciones. del que hablaremos con detalle más adelante. CREATE TABLE pelicula ( titulo VARCHAR(64). SQL. ¿Qué quieren decir las dos líneas dedicadas a la . Si ha trabajado con algún lenguaje de programación verá que éste no se parece a ninguno que conozca.

para que pueda almacenar datos que posteriormente podamos consultar. La segunda línea es la que se encarga de la creación: "Crea la base de datos videoteca". Suponga que ha utilizado en más de una ocasión estas líneas porque está volviendo a probar los ejemplos que acompañan este libro. Escriba en el símbolo del sistema las dos líneas que acabamos de comentar y pulse la tecla Intro al terminar. MySQL le diría que no es posible llevar a cabo la acción. qué decepción! El resultado no es demasiado espectacular. ¿Es posible que hayamos conseguido nuestro objetivo? Para comprobarlo basta con que ejecute la siguiente instrucción: SHOW DATABASES. Figura 3. la que acabamos de crear: videoteca. Los mensajes indican que las consultas se han ejecutado correctamente. la primera línea le dice a MySQL algo así como: "Borra la base de datos videoteca en caso de que exista". precisamente. Llegó el momento: vamos a crear nuestra primera base de datos. la base de datos habrá sido creada. . Traduciendo del inglés.8. Figura 3. Precisamente lo siguiente que haremos. algo no deseable si quiere comenzar con los ejemplos desde cero. Nuestra primera base de datos Para que la base de datos sea realmente útil. Tras la ejecución de la segunda línea. es necesario crear tablas dentro de ella.7 muestra el aspecto de dicha ventana tras ejecutar las instrucciones. La figura 3. Si intentase crear la base de datos y ésta ya existiese. Enhorabuena. porque la base de datos ya existe.8 puede ver que una de las bases de datos existentes es. SQL para crear una base de datos ¡Vaya. Vuelva a examinar las instrucciones anteriores: DROP DATABASE IF EXISTS videoteca. es decir. En la figura 3.7.creación de la base de datos? Con la primera de ellas se le dice a MySQL que borre la base de datos videoteca en caso de que exista.

La tercera línea permite indicarle a MySQL la base de datos con la que debe trabajar: "Utiliza la base de datos videoteca". En la cuarta línea se le pide a MySQL que borre la tabla pelicula si ya existe. director VARCHAR(128). De esa forma. Escriba esas instrucciones y. pulse Intro cuando termine. en la que se indicó con qué base de datos se iba a trabajar. gracias a la instrucción USE nos lo ahorramos. llamada pelicula.9 muestra los mensajes que verá tras crear la tabla de películas y ejecutar posteriormente la instrucción DESCRIBE . Y llega la parte complicada. No se preocupe demasiado por la sintaxis de estas instrucciones. A partir de la quinta línea se instruye a MySQL para que cree una tabla nueva. MySQL sabrá que las siguientes instrucciones que reciba irán referidas a esa base de datos.CREATE DATABASE videoteca. en esta instrucción no se hace referencia a base de datos alguna. Not a: Podríamos haber incluido el nombre de la base de datos antes del nombre de la tabla. CREATE TABLE pelicula ( titulo VARCHAR(64).pelicula . Al igual que con las dos primeras instrucciones. La figura 3. USE videoteca. Esto es así gracias a la instrucción anterior. actor VARCHAR(128) ). en la instrucción de creación de la tabla: CREATE TABLE videot eca. En este caso. todos los campos contendrán información de texto. dentro de la base de datos videoteca. Sin embargo. ¿Quiere asegurarse de que la tabla se ha creado? Escriba la siguiente instrucción: DESCRIBE pelicula. basta con que sepa que estas instrucciones le indican a MySQL las columnas que tendrá la tabla pelicula y el tipo de datos de cada una de ellas. sólo necesita traducir al castellano línea por línea. DROP TABLE IF EXISTS pelicula. . Como puede comprobar. separados por un punto. de nuevo.

Si encuentra instrucciones entre llaves ({}) separadas por el símbolo | querrá decir que son alternativas: puede utilizar una u otra. por lo que le recomendamos que acuda a la documentación de MySQL y complete sus conocimientos sobre ellas si así lo desea. Pero antes de aprender a realizar estas operaciones básicas. Sólo hay que seguir tres normas muy simples: Aquellos fragmentos incluidos entre corchetes ([]) son opcionales.Figura 3. Aunque con lo que verá tendrá las nociones mínimas necesarias. para simplificar la forma en la que la sintaxis está expresada. Operaciones sobre tablas A continuación aprenderá a realizar las operaciones básicas de creación. Si están entre corchetes. puede utilizar una o ninguna de ellas. detengámonos un momento y veamos qué operaciones se pueden llevar a cabo sobre las propias tablas. grandes partes de la descripción pueden sustituirse por un nombre cuya sintaxis se explicará posteriormente. Con lo aprendido hasta el momento estamos listos para comenzar a ver las operaciones básicas de manipulación. Por último. Es realizando estas operaciones como comprenderá para qué sirve realmente una base de datos. Así le será más sencillo entenderla cuando acuda a ella en busca de más información. Verá ejemplos de estas tres normas con la sentencia de .9. lo que quiere decir que no es obligatorio utilizarlos en las consultas. modificación y borrado de tablas. pero ha de utilizar una de ellas. y la ha creado usted mismo. Creación de la tabla Ahora tiene una base de datos con una tabla. las instrucciones que verá disponen de muchas más opciones de las que comentaremos. Para explicar la forma en la que debe utilizar estas instrucciones recurriremos a la sintaxis que MySQL sigue en su documentación.

Entre otras opciones. . Más adelante. es posible indicar el tipo de tabla que se desea utilizar: ENGINE = { ARCHIVE | CSV | FEDERATED | MEMORY | InnoDB | MERGE | MYISAM | NDBCLUSTER } En breve explicaremos las características de los diferentes tipos de tabla existentes. no va a ser éste el caso. Vamos a crear una nueva base de datos en la que realizar las pruebas de este capítulo. Si lo desea puede incluir un valor predeterminado.. en cada inserción se asignará ese valor a su columna. El valor guardado será NULL . hablaremos sobre los tipos de datos. pues NULL es la opción predeterminada). Para ver cómo se crea una tabla nada mejor que un ejemplo. Es más que probable que MySQL ya disponga de una base de datos de pruebas llamada test. Esto evitará que MySQL le informe del error que ocurre al intentar crear una tabla que ya existe. MySQL le permitirá insertar registros sin asignar un valor a dicha columna. que podríamos utilizar para crear tablas de ejemplo. Ejecute las siguientes órdenes para crear la base de datos pruebas: DROP DATABASE IF EXISTS pruebas. . aunque no haya especificado valor alguno. centrándonos en los más utilizados. Creación La creación de una tabla debe hacerse de acuerdo a la siguiente sintaxis: CREATE TABLE [IF NOT EXISTS] nombre [(definición.creación de tablas descrita a continuación. De esa forma. puede incluir IF NOT EXISTS cuando cree una tabla.)] [opciones] Si lo desea.. Si no desea que esto sea así indique NOT NULL . Si indica NULL para una columna (o no indica nada. en este mismo capítulo. La descripción de las características de cada columna se realiza en definición: definición: columna tipo [NOT NULL | NULL] [DEFAULT valor_predeterminado] Debe incluir una definición por cada columna que desee utilizar. El tipo de la columna se indica tras su nombre. Sin embargo.

CREATE TABLE persona( id INT NOT NULL. cambiar valores predeterminados (MODIFY) o eliminarlos. ADD edad INT NOT NULL.DROP DATABASE IF EXISTS pruebas. . modificar las existentes (CHANGE ). que sigue la siguiente sintaxis: ALTER TABLE nombre modificación [.. Ejecute ahora las siguientes órdenes para crear la tabla persona: USE pruebas. Con esta instrucción se pueden añadir nuevas columnas a una tabla (ADD). . nada mejor que modificar la tabla creada en la sección anterior. Además. definición. añadiremos un nuevo campo que permitirá guardar la edad. eliminar columnas (DROP ) o cambiar el tipo de tabla. Para lograr ambos objetivos utilice las siguientes instrucciones: USE pruebas. Ahora bien. modificación.. cada modificación se define de la siguiente forma: modificación: ADD definición | ADD (definición. CREATE DATABASE pruebas. Para ello debe utilizar la instrucción ALTER TABLE . Vamos a cambiar el tipo del campo nombre para que pueda almacenar cadenas de mayor longitud. ALTER TABLE persona MODIFY nombre VARCHAR(32) NOT NULL. como ya sabrá. Como ejemplo.) | MODIFY columna { SET DEFAULT valor_predeterminado | DROP DEFAULT } | CHANGE columna definición | DROP columna | opciones Por definición se entiende la sintaxis vista en la creación de tablas. apellidos VARCHAR(64) NOT NULL DEFAULT '' ).. Modificación Las características de una tabla pueden ser modificadas después de que haya sido creada. ¿es posible modificar las características de una tabla ya existente? La respuesta es sí. Las instrucciones anteriores crean una tabla siguiendo las normas sintácticas que se vieron anteriormente.] A su vez.. nombre VARCHAR(16) NOT NULL. incluso si ya contiene datos..

MySQL permite utilizar diferentes tipos de tabla. nombre.] El nombre de la tabla actual se cambiaría por el nuevo. puede cambiar el nombre de más de una tabla a la vez. Si lo desea. existen muchos otros como. nombre es el nombre de la tabla que se quiere eliminar... actual2 TO nuevo2. dependiendo de sus necesidades.. Las siguientes instrucciones permiten cambiar el nombre de la tabla persona por individuo: USE pruebas. Para borrar la tabla que se ha estado utilizando hasta ahora utilice las siguientes instrucciones: USE pruebas. sin quebraderos de cabeza.. Borrado La sintaxis de la instrucción de borrado de tablas es: DROP TABLE [IF EXISTS] nombre [. es posible borrar más de una tabla a la vez con sólo indicar sus nombres separados por comas. En los siguientes apartados describiremos los tipos de tabla más utilizados: MyISAM e InnoDB. Tipos de tabla Al contrario que otros sistemas gestores de bases de datos. Es posible utilizar transacciones si se trata de uno de los requisitos de la aplicación. Y lo mejor de todo: si sólo necesita un sistema para almacenar datos y posteriormente consultarlos. puede incluir IF EXISTS en la consulta de borrado. Esto evitará que MySQL le informe del error que surge al intentar eliminar una tabla que no existe en la base de datos que esté utilizando en ese momento. Sin embargo. puede olvidar que existen los diferentes tipos de tabla que se verán a continuación. Como puede ver. Si la prioridad es ahorrar espacio de almacenamiento. MySQL puede comprimir las tablas para que ocupen lo menos posible.] En dicha sintaxis. Si precisa velocidad de proceso puede utilizar tablas que estarán directamente en la memoria RAM del servidor. por ejemplo: ARCHIVE: Permite almacenar grandes cantidades de .. DROP TABLE IF EXISTS individuo. Si lo desea. .También es posible cambiar el nombre de las tablas existentes: RENAME TABLE actual TO nuevo[. RENAME TABLE persona TO individuo.

FEDERATED: Permite que se pueda acceder a los datos de una tabla desde servidores remotos. con mejoras como un superior aprovechamiento del espacio y más velocidad en el acceso a datos. MyISAM El tipo predeterminado de tablas que MySQL proporciona es MyISAM. El otro tipo de tabla es BLACKHOLE (agujero negro) y funciona como tal: todo lo que se arroja dentro de una tabla de este tipo desaparece y cualquier consulta devuelve un conjunto vacío. Más aún. Lo mismo hará si no es capaz de crear el tipo de tabla que se indique. Como su nombre indica. Al crear tablas sin indicar de qué tipo serán. Se utiliza en entornos en los que no es necesario guardar los datos en el servidor local pero sí enviarlos a otros servidores de forma distribuida. pero sólo si el propósito de la tabla es archivar información. CSV: Son las siglas de Comma Separated Values (valores separados por comas). Aviso: Existe una excepción a la afirmación anterior. . Not a: Existen un par de tipos de tablas muy curiosos que no hemos mencionado aún. Como consecuencia es muy veloz. utilice la instrucción SHOW CREATE TABLE seguida del nombre de la tabla en cuestión y busque el valor que toma ENGINE. conocido como ISAM (ya descatalogado). NDBCLUSTER: Tipo de tabla para entornos distribuidos y de alta disponibilidad. ISAM son las siglas de método de acceso secuencial indexado (Indexed Sequential Access Method). Permite almacenar datos en archivos de texto separando los valores con comas. no dejan de aparecer tipos de tabla nuevos para cubrir todas las necesidades de los usuarios de MySQL. El nombre de este tipo de tablas viene de la forma en que MySQL accede a sus datos.información sin utilizar ningún índice. para evitar complicaciones. a su vez. se trata de un simple ejemplo que no cumple más función que ilustrar el funcionamiento interno de MySQL en su código fuente. Truco: ¿Quiere saber qué tipos de tabla puede utilizar en su servidor MySQL? Realice la consulta SHOW ENGINES. MySQL utilizará el tipo MyISAM. Si tiene alguna duda sobre el tipo de una determinada tabla. Las tablas de tipo MyISAM pueden. ser de tres tipos: . una evolución del tipo de tabla original. La recuperación de la misma será más lenta en la mayoría de los casos puesto que no se podrá utilizar índice alguno para acelerarla. El tipo predeterminado de las tablas será InnoDB si ha instalado MySQL en Windows utilizando el asistente. El primero de ellos es EXAMPLE (ejemplo).

las tablas MyISAM son especialmente útiles cuando los datos no cambian con frecuencia y la operación más utilizada es la de lectura. Por sus características. MySQL hará que sea de tipo dinámico. Para lograr estos dos objetivos se sacrifica un poco de la velocidad de la que MySQL presume. Comprimidas: Si necesita que el espacio ocupado por sus tablas sea mínimo éste es su tipo de tabla. MySQL bloquea las tablas de tipo MyISAM cuando se realiza una inserción o una actualización en un registro hasta que la operación termine. como el CD-ROM. es recomendable que utilice tablas de tipo InnoDB. MySQL hará que sea de tipo estático. Sin embargo. Si las inserciones de nuevos datos y las modificaciones van a ser algo frecuente o necesita utilizar transacciones en sus operaciones con registros. lo que permite que más usuarios utilicen de forma simultánea la base de datos. . Este tipo de tablas es el más rápido cuando se trata de leer datos del disco: para recuperar los de un registro en concreto sólo es necesario realizar unos sencillos cálculos. Por el contrario.Estáticas: De forma automática. La contrapartida: es necesario más tiempo para acceder a un registro en particular. Delante de cada registro almacenará el espacio que ocupa. Dinámicas: Si crea una tabla con algún campo de tipo VARCHAR. ocupa más espacio que las tablas dinámicas. VARBINARY. El ejemplo más utilizado transcurre en la base de datos de un banco. TEXT o BLOB. durante una transferencia entre dos cuentas. Como consecuencia. Esto se debe a que en cada lectura se pueden recuperar más datos que si la tabla no estuviese comprimida. por lo que deberá realizar las inserciones en tablas sin comprimir y alterar posteriormente las propiedades de la tabla para comprimirla. Un efecto secundario muy interesante de este tipo de tablas es que mejora el tiempo de acceso a los datos si están almacenados en dispositivos muy lentos. como algunos discos extraíbles u ópticos. algo recomendable en aplicaciones de bases de datos que funcionen desde unidades ópticas. por ejemplo. Si su tabla está en este formato sólo podrá leer de ella. VARBINARY. En una tabla de tipo estático. InnoDB Las tablas InnoDB proporcionan bloqueo por registro y control de transacciones. Las transacciones son necesarias en multitud de situaciones. cumpliendo con el estándar ACID. si las tablas son InnoDB. cada registro ocupa siempre el mismo tamaño. estas tablas ocupan menos espacio que las tablas estáticas. si la tabla que está creando no contiene ningún campo de tipo VARCHAR. el bloqueo sólo se realiza en el registro que se esté modificando. TEXT o BLOB. puesto que se necesita leer antes el espacio ocupado por cada registro y hacer los cálculos oportunos.

Para realizar la transferencia han de completarse dos pasos: la cantidad transferida debe sumarse en la cuenta de destino y restarse de la cuenta que origina la transferencia.50). INSERT INTO cuenta VALUES(212. INSERT INTO cuenta VALUES(555.300 WHERE idcliente = 555. UPDATE cuenta SET saldo = saldo + 300 WHERE idcliente = 212. como un corte de suministro eléctrico. no verá que existan problemas: uno le da el dinero a otro y asunto resuelto. ¿En qué situación estaremos si ocurre algún problema entre el primer y el segundo paso. Claro que es todo lo contrario para los clientes. un fallo en el hardware del ordenador que hospeda el servidor de bases de datos. UPDATE cuenta SET saldo = saldo . CREATE TABLE cuenta( idcliente INT NOT NULL. inserte un par de valores para almacenar el saldo de dos clientes: USE pruebas. . La situación se complica en el entorno informático. donde el saldo de las cuentas de ambos clientes debe estar almacenado en un registro dentro de una tabla de una base de datos. Se trata de un valor numérico en coma flotante. Cree una tabla muy sencilla para los saldos de los clientes del banco dentro de la base de datos de pruebas utilizando las siguientes instrucciones: USE pruebas. como un traspaso de dinero de una persona a otra.00). etcétera? El importe a transferir se habrá sumado a la cuenta destino.Si piensa en esta transferencia en el mundo real. 1200. saldo DOUBLE NOT NULL DEFAULT 0 ) ENGINE = InnoDB. pero no se habrá restado de la emisora. A continuación. Para el banco no se trata de algo deseable. 220. Una operación tras la otra: USE pruebas. DROP TABLE IF EXISTS cuenta.

START TRANSACTION. los cambios realizados por una transacción deben permanecer cuando ésta termine. Sin embargo. mientras dure la transacción.300 WHERE idcliente = 555. las instrucciones que la conforman deben tener la impresión de que sólo ellas están en funcionamiento. Siguiendo con el ejemplo. La gestión de las transacciones se realiza mediante unas instrucciones muy sencillas. . Al comienzo de una transacción. ACID son las siglas de atómico. UPDATE cuenta SET saldo = saldo + 300 WHERE idcliente = 212. la transferencia se realizaría de la siguiente forma: USE pruebas. por ejemplo). permaneciendo la base de datos en el mismo estado en el que se encontraba antes de comenzar la transacción. En el ejemplo del banco. Por el contrario. and Durable). Mientras dure una transacción. Esto es permisible siempre y cuando al terminar la transacción se retorne al estado de consistencia inicial. es posible que se pierda la consistencia. el estado de la base de datos debe ser consistente. o ninguno lo hará. Consistent. aunque en realidad se puedan estar realizando otras operaciones en la base de datos. incluso otras transacciones. definidas por el diseño.El estándar ACID se propuso para solucionar este tipo de situaciones. El estado de una base de datos es consistente mientras cumpla unas reglas. ninguno de los cambios que haya realizado se habrán guardado. consistente. Isolated. aislado y duradero (Atomic. una de las reglas de consistencia podría ser que toda transferencia de capital debe estar correspondida por un ingreso. Se dice que uno o más cambios en una base de datos componen una operación atómica si forman una unidad indivisible: o todos se completan con éxito. si la transacción se interrumpe en medio de su trabajo (por un corte de luz. UPDATE cuenta SET saldo = saldo . En último lugar.

Figura 3. Not a: Existe un motivo más para utilizar tablas del tipo InnoDB.10 puede ver cómo almacenaría MySQL los valores de una tabla con una sola columna de tipo CHAR. Ocupación de CHAR . Si existiese un problema antes de ejecutar la instrucción COMMIT . Con la primera instrucción se le dice a MySQL que va a comenzar un bloque de sentencias SQL dentro de una transacción. El bloque termina con la instrucción COMMIT . Verá qué quiere decir esto en el capítulo dedicado al diseño de bases de datos. algo vital para el funcionamiento de la integridad relacional. siempre se ocuparán esos caracteres. Es decir.10. A continuación veremos cuáles pone MySQL a nuestra disposición. se utiliza la expresión cadena de texto cuando se hace referencia a una sucesión de caracteres que pueden formar palabras o frases. Tipos de texto En la jerga informática. el tipo de cada columna debe ser diferente. ya que permiten la existencia de claves externas.COMMIT. Verá un ejemplo más adelante. que finaliza la transacción. Tipos de datos Dependiendo de la naturaleza de los datos que queramos guardar. Los bancos son muy listos. Si la columna puede tener veinte caracteres. eliminando el problema de la inconsistencia. MySQL dispone de varios tipos de datos diferentes para almacenar esta clase de información: CHAR: Permite definir cadenas de texto de longitud fija. A continuación de esta primera instrucción están las operaciones a realizar con los valores dentro de la base de datos. que permite determinar si en las consultas se diferenciará entre mayúsculas y minúsculas. aunque el texto a guardar sea menor. MySQL no hará efectivo los cambios hasta que encuentre una instrucción COMMIT . En la figura 3. La longitud se especifica entre paréntesis a continuación del nombre del tipo y puede estar entre 0 y 255 caracteres. todas las instrucciones anteriores a COMMIT se descartarían. El tipo CHAR admite el modificador BINARY.

BLOB: Aunque no se trata de un tipo de texto propiamente dicho. en total 38.11. pero la recuperación de los datos al hacer consultas es más veloz.VARCHAR: Tiene el mismo rango de longitud que el t i p o CHAR. Este tipo de columnas puede utilizarse para guardar información binaria. El nombre BLOB significa objeto binario de gran tamaño (binary large object). TEXT . no como cadenas de caracteres. con la salvedad de que las cadenas se almacenan en formato binario. La figura 3. lo que da un resultado de 70 caracteres. si define una columna de veinte caracteres y guarda una cadena de diez.10 estuviese creada con un tipo VARCHAR. es necesario hablar de él porque está íntimamente relacionado con el siguiente. Es decir. No confundir con el tipo de datos VARCHAR BINARY. un archivo comprimido con ZIP. con la salvedad de que las cadenas se almacenan en formato binario. 43 caracteres. Y claro está. Figura 3. MySQL sabe que el tercer elemento de la tabla se encuentra tres veces la longitud de la columna a partir del inicio de la tabla. en total. Las consultas realizadas sobre este tipo de columnas diferenciarán entre mayúsculas y minúsculas. Compare el espacio ocupado por los datos en las figura 3. no como cadenas de caracteres. etcétera. más un carácter extra por cada fila. u n CHAR ocuparía veinte caracteres. También VARCHAR admite el m o d i f i ca d o r BINARY para determinar si se diferenciarán mayúsculas de minúsculas en las consultas. Por ejemplo. el mismo comportamiento de CHAR y . mientras que un VARCHAR sólo once. Con VARCHAR tendría que sumar el número de caracteres de cada fila.11.10 y 3. Ocupación de VARCHAR Not a: El tipo CHAR ocupa más espacio. sólo se ocuparán esos diez caracteres más uno para guardar la longitud. No confundir con el tipo de datos CHAR BINARY.11 muestra cómo asignaría MySQL el espacio si la única columna de la tabla mostrada en la figura 3. para una cadena de diez caracteres. VARBINARY: Equivalente al tipo VARCHAR. BINARY: Equivalente al tipo CHAR. también puede utilizarse para guardar texto cuya longitud esté por encima de la permitida por los tipos CHAR o VARCHAR. como el contenido de un archivo JPG. Utilizando CHAR se tienen cinco filas de 14 caracteres cada una. Sin embargo.

Enseguida veremos un ejemplo. Posteriormente. MySQL utiliza un ingenioso sistema para no tener que guardar las cadenas en la base de datos. Los tipos TINYBLOB. Con el ejemplo que veremos en breve quedará más claro cómo se insertan estos valores. TEXT: Exactamente igual que un BLOB. Los tipos TINYTEXT . existen otras alternativas. Internamente. SET: Similar a ENUM . INSERT INTO texto VALUES('A'). Esta tabla estará dentro de la base de datos de pruebas que creamos al principio de este capítulo: USE pruebas. INSERT INTO texto VALUES('a'). Y realice una consulta a los valores de esa tabla. MEDIUMBLOB y LONGBLOB son BLOB de diferentes tamaños. DROP TABLE IF EXISTS texto. en esa columna sólo se podrá insertar alguno de los valores definidos. Not a: Aunque es posible almacenar imágenes y cualquier archivo binario en un campo de tipo BLOB dentro de una tabla de MySQL. CREATE TABLE texto( cadena VARCHAR(32) ). MEDIUMTEXT y LONGTEXT son TEXT de diferentes tamaños. los conjuntos se diferencian en que se pueden insertar varios de los valores definidos al crear la tabla. ahorrando espacio. SELECT * . con la salvedad de que TEXT no distingue entre mayúsculas y minúsculas en las consultas. la utilizaremos para hacer pruebas con los tipos de texto. Cree una nueva tabla llamada texto. INSERT INTO texto VALUES('d'). MySQL sustituye la cadena por un número.VARCHAR cuando se utiliza el modificador BINARY. podría guardar la ruta en la que el archivo se encuentra en un campo de tipo VARCHAR. como relacionar de alguna manera un archivo en disco con un registro dentro de una tabla. ordenándolos de forma alfabética: USE pruebas. ENUM: La enumeración es una clase especial de tipo de cadena. Por ejemplo. Al definir la columna se indican los posibles valores que puede tomar. haciendo menor el espacio ocupado por la base de datos. ahorrando espacio en cada inserción. Inserte algunas cadenas de texto: USE pruebas. INSERT INTO texto VALUES('b').

CREATE TABLE texto( cadena VARCHAR(32) BINARY ). selecciónelos ordenados alfabéticamente. Esta vez el resultado será diferente. Figura 3.13. Ahora. se basa en el orden de inserción. Otra ordenación alfabética Como puede comprobar. Figura 3. pero no diferencia entre mayúsculas y minúsculas.* FROM texto ORDER BY cadena.12. Suponga que .13. un ejemplo de enumeraciones. pero cree la tabla con las siguientes instrucciones: USE pruebas. Puede ver el resultado de esta consulta en la figura 3. Ante la duda. la primera consulta devuelve los registros ordenados alfabéticamente. repita los pasos anteriores. Ordenación alfabética Ahora. razón por la que a aparece antes que A. DROP TABLE IF EXISTS texto. el resultado de la segunda consulta sí se obtiene diferenciando entre mayúsculas y minúsculas. Sin embargo. Vuelva a insertar los mismos valores y. de nuevo.12. Téngalo en cuenta cuando desee obtener listados ordenados alfabéticamente. como puede verse en la figura 3. Por ello A aparece antes que a.

La siguiente inserción generará un error: USE pruebas. El resultado de una consulta de todos los valores de esta tabla puede verse en la figura 3. 'VCD' ). 'VHS'). Puede insertar valores en esa tabla como si de cadenas de texto se tratasen: USE pruebas. Es posible crear en la base de datos de pruebas una tabla con una columna dedicada al soporte en el que se encuentra la grabación.14.14. Como sólo dispone de reproductor de vídeo VHS y de DVD le bastará con que la columna tenga esos dos valores. CREATE TABLE pelicula( titulo VARCHAR(64). Puede ver el mensaje devuelto en la figura 3.quiere almacenar en un campo de su base de datos dedicada a películas el soporte en el que se encuentran las grabaciones. 'DVD' ) ).15. DROP TABLE IF EXISTS pelicula. INSERT INTO pelicula VALUES( 'Blade Runner'. soporte ENUM( 'VHS'. INSERT INTO pelicula VALUES ('TRON'. de esta manera: USE pruebas. Enumeración para soportes de grabación MySQL no permite insertar valores que no estén dentro de los definidos al crear la tabla. INSERT INTO pelicula VALUES ('Alien'. 'DVD'). Figura 3. .

thriller' ). Se podría lograr algo similar creando la columna categoria mediante las siguientes órdenes: USE pruebas. CREATE TABLE pelicula( titulo VARCHAR(64). el uso de enumeraciones no es una buena idea si queremos permitir la inserción de nuevos formatos de grabación. El tipo de datos SET también podría utilizarse en este ejemplo. 'ciencia-ficción. categoria SET( 'ciencia-ficción'. DROP TABLE IF EXISTS pelicula. Inserción que no pertenece a la enumeración Aunque puede simplificar mucho trabajo. INSERT INTO pelicula VALUES( 'Alien'.Figura 3.terror' ). Suponga que quiere guardar en una columna el género al que pertenece una película. . En el capítulo dedicado al diseño de bases de datos veremos cómo permitir que los formatos de grabación puedan ser modificados sin cambiar la estructura de la tabla. 'terror'. La inserción de registros en una tabla con una columna de tipo SET se realiza de la siguiente manera: USE pruebas. Como a veces no es posible encuadrar un título dentro de una única categoría sería interesante poder indicar varías a la vez.15. 'ciencia-ficción. 'thriller' ) ). INSERT INTO pelicula VALUES( 'Blade Runner'. Si utilizásemos enumeraciones tendríamos que modificar las características de la tabla.

más espacio se ocupará en la base de datos. con un rango entre -128 y 127 con signo. Figura 3. Las inserciones de valores no existentes en la definición del campo de tipo SET darían lugar a la inserción de cadenas vacías. es más costoso almacenar y realizar operaciones con números decimales que con números enteros. estaríamos perdiendo información (y eso puede ser más grave) si la columna destinada a almacenar el precio de una película fuese de tipo entero. La primera cantidad es un número entero positivo.16. Por cuestiones relacionadas con la forma en la que los programas están construidos y con el hardware en el que se ejecutan. diferenciados por el rango de valores que pueden contener. El resultado de una consulta sobre los valores insertados en esta tabla puede verse en la figura 3. se perdería. Ocupa un solo byte. Utilización del tipo SET Tipos numéricos MySQL proporciona diferentes tipos de datos para que almacenemos números en las columnas de nuestras tablas. No es lo mismo guardar el número de veces que se ha visto una película que su precio. Cuanto mayor sea el rango. puesto que la parte de la derecha de la coma. es posible seleccionar el tipo de datos más adecuado para cada caso. la parte decimal. SMALLINT: Oscila entre -32768 y 32767. Si no se . Se estarían desaprovechando recursos si se utilizase una columna de tipo decimal para almacenar información de tipo entero. Existen seis tipos básicos para almacenar enteros. 'ciencia-ficción' ).INSERT INTO pelicula VALUES( 'Contact'.16. Estos tipos son: TINYINT: El más pequeño de los enteros. De igual manera. mientras que la segunda es decimal. o de 0 a 255 sin signo. Como existe una gran variedad. Números enteros MySQL proporciona suficiente variedad de tipos para cubrir todas sus necesidades.

cambiando así el tipo de datos que la columna podrá guardar. CREATE TABLE enteros(entero INT). ZEROFILL . Con signo. Utilice la base de datos creada en el apartado anterior para las pruebas con los tipos de texto. Como puede comprobar. Existen otros modificadores que.incluye signo. añadiendo el modificador UNSIGNED. . utilizados de forma conjunta. como puede verse a continuación: USE pruebas. Si se sabe que los valores de una determinada columna no podrán tener más de 4 dígitos es posible utilizar otro modificador para que los números devueltos siempre ocupen esos 4 dígitos. CREATE TABLE enteros(entero INT UNSIGNED). Si quisiese almacenar enteros sin signo en ese campo debería cambiar la tercera línea. DROP TABLE IF EXISTS enteros. La columna entero de la tabla enteros puede almacenar números enteros con signo dentro del rango que se encuentra entre -2147483648 a 2147483647. puede ir desde 0 a 65535. mientras que sin signo el rango está entre 0 y 18446744073709551615. Sin signo desde 0 a 16777215. El espacio consumido es de 3 bytes. Con uno de ellos. sólo se ha añadido el modificador UNSIGNED después del indicador del tipo de la columna. que se encarga de la creación de la tabla. hasta los dígitos seleccionados con el segundo modificador. o desde 0 hasta 4294967295 si no lo utiliza. Cree dentro de ella una tabla con un único campo de tipo INT : USE pruebas. MEDIUMINT: Con signo desde -8388608 a 8388607. MySQL recortará el número hasta el límite más cercano sin avisarnos. puede almacenar valores desde 9223372036854775808 hasta 9223372036854775807. INT: El tipo entero más común. pueden resultarnos interesantes. se le puede indicar a MySQL que rellene con ceros a la izquierda el número. Puede ir desde 2147483648 a 2147483647 si utiliza signo. DROP TABLE IF EXISTS enteros. Al ocupar 4 bytes está especialmente indicado si desea aprovechar las características de la mayoría de procesadores del mercado de hoy en día. rellenando con ceros a la izquierda aquellos que ocupen menos. Dos bytes de espacio. Advert encia: Aunque es posible realizar inserciones fuera de ese rango. BIGINT: El mayor de los tipos enteros ocupa 8 bytes.

Puede que un ejemplo sirva para explicar mejor el funcionamiento de ZEROFILL . INSERT INTO enteros values(10). . el tipo de la columna entero es entero relleno de ceros hasta cuatro dígitos. La siguiente consulta reconstruye la tabla de enteros. INSERT INTO enteros VALUES(10000). Primero las inserciones: USE pruebas. ¿Qué ocurriría si se insertase un valor con más dígitos de los indicados al crear la tabla? Pruebe: USE pruebas. INSERT INTO enteros values(1000).18. cambiando las características de su única columna: USE pruebas. el segundo de los modificadores antes mencionado se añade a continuación del tipo. entre paréntesis. Como comprobará. Por cierto. Y luego la consulta de selección: USE pruebas.17 muestra el resultado de esta consulta. INSERT INTO enteros values(1). Figura 3. Selección de valores enteros Como puede comprobar. Pruebe a insertar algunos valores para después seleccionarlos. INSERT INTO enteros values(100). CREATE TABLE enteros( entero INT(4) UNSIGNED ZEROFILL ). MySQL le permite realizar la inserción sin ningún problema: los modificadores añadidos al tipo de la columna entero sólo afectan a la forma en la que los datos se presentan al consultarlos. el 100 como 0100 y el 1000 tal cual. SELECT * FROM enteros.17. el 1 aparece como 0001. y así ver el efecto que tienen en las consultas. Como ve. La figura 3. DROP TABLE IF EXISTS enteros. el 10 como 0010. ¿qué se obtendrá al consultar ahora los datos de la tabla? Véalo en la figura 3.

los números en coma flotante contienen una parte entera y una parte decimal. Advert encia: Desde aquí queremos recomendarle que sólo utilice este tipo de modificaciones cuando sea estrictamente necesario. como los lógicos o booleanos.99 euros. Por ejemplo. la parte entera es 29 y la parte decimal 99. y la parte decimal a la moneda fraccionaria. en la sintaxis de SQL se utiliza un punto como separador. FALSE y false para trabajar con tipos booleanos. Puesto que un tipo booleano es el que permite diferenciar entre los estados cierto y falso. fuera del contexto de las instrucciones SQL se utilizará la coma como separador. en realidad cuesta 30 euros menos un céntimo. Existen otras formas de dar formato a los números que no pasan por alteraciones en la definición de las columnas de una tabla. . El ejemplo más claro: los precios. Una regla podría ser: mantenga los datos tal como son.18. MySQL ofrece diferentes seudónimos para cada tipo de datos. Si tiene conocimientos de programación. Números en coma flotante Como ya sabrá. en el resultado de las consultas verá el punto como separador. Sin embargo. si el precio de un DVD es 29. Por ello. habrá visto que no se han mencionado otros tipos de datos. De igual forma. El tipo BOOLEAN (o BOOL ) es un seudónimo de TINYINT(1). modifique su presentación en la aplicación que haga uso de ellos. Los números en coma flotante se llaman así porque se utiliza una coma para separar la parte entera de la decimal. Sin embargo. Esta última se utiliza para describir cantidades inferiores a la unidad. existe un seudónimo llamado BIT para trabajar con bits. en los que la parte entera se refiere a múltiplos de la moneda. De igual manera. true. al insertar valores en coma flotante éstos se escribirán utilizando el punto. mientras que el resto se mostrarán tal cual. en un entero de un dígito tendríamos más que suficiente. continuaremos repasando los tipos numéricos con los tipos decimales. Pero para lo que interesa ahora mismo. al enumerar los tipos existentes.Figura 3. Tras comentar los tipos enteros. Utilice las constantes TRUE . Valor con más dígitos A aquellos valores que estén por debajo del ancho establecido al definir el tipo del campo se les añadirán ceros por la izquierda. no se deje engañar.

es posible utilizar ZEROFILL con idénticos resultados. cero incluido.7976931348623157E+308 y 2. con seis dígitos y dos decimales a la derecha de la coma. simplemente se ignorarán los valores negativos. mayor espacio ocupado por el número. CREATE TABLE decimales( precio FLOAT(6. permite almacenar valores entre -3. Es posible utilizar FLOAT(N).MySQL proporciona tres tipos básicos para los números en coma flotante. Aunque el rango de valores que puede almacenar es el mismo que el tipo DOUBLE .99. Para ello. donde N es un valor menor que 53. y 2. con DOUBLE(6. . 2) se estaría indicando que se quiere una columna que almacene números en coma flotante. utilizando aproximaciones. El rango de valores que se podrían almacenar en esta columna estaría entre -9999. utilice el siguiente código: USE pruebas. Aprovechando que disponemos de una base de datos para pruebas. Como con los números enteros.175494351E-38 y 3. DOUBLE: Decimal de precisión doble. Si N fuese menor que 25.2250738585072014E308 y 1. Por el contrario. Existe una forma alternativa de crear columnas para almacenar valores en coma flotante. Estos tipos son: FLOAT: Decimal de precisión simple.7976931348623157E+308. Por ejemplo. Como vimos anteriormente. y 1. cree una nueva tabla en la que experimentar con valores en coma flotante.2250738585072014E-308. Para estos tres tipos se puede indicar el número de dígitos totales para mostrar y el número de dígitos decimales.2) ).99 y 9999. incluido el cero. este tipo guarda valores exactos. DECIMAL: Los dos tipos vistos anteriormente codifican la información del número de manera que ocupe lo menos posible. Sin embargo. se pueden insertar valores entre -9999.99 y 9999. entre paréntesis y a la derecha del nombre del tipo.175494351E-38.99: cuatro dígitos antes de la coma y dos tras ella coma suman seis. DROP TABLE IF EXISTS decimales. mientras que si N está entre 25 y 53 lo harían con precisión doble.402823466E+38 y 1. Inserte algunos y vea el resultado de una consulta de selección: USE pruebas. A mayor precisión.402823466E+38. los valores de la columna se almacenarían con precisión simple. con valores entre -1. especificar que se trata de números sin signo utilizando UNSIGNED no proporcionará un rango de valores más amplio. el espacio ocupado es bastante mayor.

. Por eso 199. cree una nueva tabla: USE pruebas. Puesto que tiene que almacenar el número con 2 decimales. SELECT * FROM decimales.995). puesto que al crear la tabla se le indicó que esa columna tendría dos decimales.USE pruebas. Pero ¿qué ha pasado con el tercer valor? ¡Se insertó 199. Inserción de valores en coma flotante El segundo valor insertado fue 30.19. descarta el tercero.99. De lo anterior se puede deducir que es muy importante definir correctamente la precisión de los decimales.99! Esto se debe al redondeo que MySQL ha realizado. Si el dígito decimal a evaluar está entre 0 y 4.5) ).38000). lo descarta. Para el siguiente ejemplo. INSERT INTO decimales2 VALUES(3835. ya que MySQL redondea las cifras que se salen de la definición del tipo de la columna.19. Inserte un valor: USE pruebas. INSERT INTO decimales VALUES(199. El primer valor insertado ha sido 29. MySQL redondea el número.99). El resultado puede verse en la figura 3. al examinar el cuarto valor insertado se puede comprobar que no se trata simplemente de descartar decimales. INSERT INTO decimales VALUES(29. CREATE TABLE decimales2( precio FLOAT(10. INSERT INTO decimales VALUES(199. DROP TABLE IF EXISTS decimales2. Sin embargo.00.995 ha pasado a ser 200. MySQL añade automáticamente dos ceros a la derecha de la coma.994. pero la consulta muestra 199. INSERT INTO decimales VALUES(30).994). Si está entre 5 y 9 suma uno al siguiente decimal. Figura 3.

por ejemplo la aparición de decimales que no ha indicado. Esto se debe a que. Fechas y horas MySQL permite utilizar los siguientes tipos de datos para almacenar valores relacionados con el tiempo. . pero la parte de la hora debe estar entre 00:00:00 y 23:59:59. internamente. primero la fecha y luego la hora. Problemas de redondeo Como ha podido comprobar. MySQL utiliza precisión doble para los cálculos en coma flotante. como acaba de ver. DATETIME: Combinación de los dos tipos anteriores. Estos seudónimos no son más que tipos básicos cuyas características se han modificado. SELECT * FROM decimales2. minutos y segundos) entre -838:59:59 y 838:59:59. Permite almacenar la fecha y la hora de un determinado instante. Por ello. Figura 3.Ahora. MySQL ofrece seudónimos de los tipos aquí presentados. o simples nombres alternativos. El rango permitido para la parte de la fecha es el mismo que para el tipo DATE . Ya vio el tipo BOOL como ejemplo al hablar de los enteros.20. entre 1000-01-01 y 9999-12-31. mes y día). es recomendable que utilice el tipo DOUBLE para almacenar valores en coma flotante. Especialmente indicado para almacenar tiempos transcurridos entre dos eventos. El formato de este tipo es AAAA-MM-DD hh:mm:ss. si experimenta problemas de esta índole. vea lo que se ha insertado en la tabla: USE pruebas. el valor mostrado en la consulta no es el mismo que se insertó.20. TIME: Para guardar horas con el formato hh:mm:ss (horas. Si utiliza columnas cuyo tipo sea de precisión sencilla es posible que experimente problemas al realizar cálculos. Como puede comprobar en la figura 3. con los tipos numéricos que MySQL pone a nuestra disposición debería tener suficiente para cubrir la mayoría de sus necesidades. como fechas y horas: DATE: Permite almacenar fechas con el formato AAAA-MM-DD (año.

Figura 3. se puede decir que una columna de este tipo debería cambiar su valor cada vez que se produzca una inserción o una actualización en el registro. YEAR: Un año indicado con dos o cuatro dígitos. El siguiente es un ejemplo de funcionamiento del tipo TIMESTAMP . UPDATE pelicula SET titulo = 'Alien' . aunque no incluyó ninguno en la inserción. Al consultar los registros de esta tabla verá que se ha insertado un valor en el campo modificado. mientras que con cuatro dígitos está entre 1901 y 2155. el valor almacenado puede estar entre 1970 y 2069. dependiendo del valor del modificador. modificado TIMESTAMP ).21. Lo utilizaremos para saber la fecha de la última modificación de un determinado registro. Además se puede almacenar el año 0000. Realice una inserción en esta tabla: USE pruebas. DROP TABLE IF EXISTS pelicula. Puede comprobarlo en la figura 3. se ha cometido un error! El título de la película es incorrecto. Contenido de una columna TIMESTAMP La columna modificado contiene la fecha y la hora en la que se realizó la inserción. Su comportamiento varía dependiendo de la versión de MySQL que se utilice. Soluciónelo: USE pruebas.21.determinado instante. TIMESTAMP: Tipo de datos un poco conflictivo. ¡Vaya. Si utiliza dos dígitos. CREATE TABLE pelicula( titulo VARCHAR(64). En líneas generales. INSERT INTO pelicula(titulo) VALUES('Alieni'). De esta forma se puede controlar cuándo se creó un registro o cuándo cambió su valor. Vuelva a crear la tabla pelicula de la base de datos de pruebas para este ejemplo: USE pruebas.

com/doc/mysql/en/column-types.22 muestra el resultado de una consulta sobre la tabla tras la actualización de la columna errónea.titulo = 'Alien' WHERE titulo = 'Alieni'. Si desea más información sobre los tipos de datos no dude en acudir a la documentación de MySQL. aunque de nuevo no se ha indicado valor alguno para esa columna. disponible en la siguiente página Web: http://dev.21.22.mysql. La figura 3. TIMESTAMP cambia automáticamente El repaso a los tipos de datos que MySQL permite utilizar en sus tablas ha concluido. Figura 3.html . el valor de la columna modificado representa ahora un instante posterior al que podía verse en la figura 3. Como puede ver.

de nuevo. Para lograrlo tiene varias opciones.4 PHP orientado a objetos Nuestro tercer encuentro con PHP lo hacemos con bastante ventaja. ya que sólo nos interesa el resultado de utilizar la función. Por supuesto. sin necesidad de volver a escribirlo varias veces. Estas funciones pueden ser invocadas con solo una línea de código. el último dedicado al aprendizaje de PHP. tal y como la entiende PHP y. cómo podemos aprovecharla para que no tengamos que escribir el mismo código dos veces. que tiene este aspecto: function nombre ([lista de parámetros]){ instrucciones } El nombre de la función debe seguir las mismas reglas que mencionamos en el capítulo 2 para los nombres de las variables. puede combinar el uso de funciones con los archivos externos anteriormente descritos. puede crear funciones que no reciban ningún parámetro. Veremos qué es esta forma de programación. . Preste especial atención a este capítulo para poder sacar el máximo partido a la versión orientada a objetos de la nueva interfaz de acceso a MySQL. Luego podrá incluir el código de esos archivos en sus programas. La primera de ellas consiste en agrupar fragmentos de código en unidades funcionales o funciones. conociendo las bases del lenguaje y habiendo programado varios ejemplos. lo que indica que su definición es opcional. Funciones Una función es un fragmento de código agrupado bajo un mismo nombre. verá cómo debe escribir sus programas para que ese trabajo pueda aprovecharse con posterioridad. Not a: La lista de parámetros de la función aparece entre corchetes. Ahora tenemos mucho más claro qué podemos esperar de una herramienta como ésta. La mayoría de los cambios que la versión 5 introdujo afectaban a la programación orientada a objetos. Es decir. Otra manera de lograr el mismo objetivo consiste en situar todo el código PHP común en archivos independientes. Durante este capítulo. quedando oculto el verdadero trabajo que están realizando.

Para declarar más de un parámetro ha de separarlos mediante comas. printf() en el capítulo 2. Por ejemplo. Parámetros La declaración de la lista de parámetros que una función recibe es similar a la declaración de variables. Vamos a crear una función que reciba como parámetro un número entero y escriba en la página Web si el número es par o impar. esa función realiza una serie de operaciones que no es necesario que conozca. . Si el resto de dividir un número entre dos es cero. En el cuerpo de la función utilizamos una instrucción condicional. } } par_impar(7). Veamos un sencillo ejemplo. en este caso $numero y dos. La función recibe un solo argumento. impar. El resultado: una página que muestra el texto impar. escribimos par. Lo único que le interesa es saber que la cadena que pase como parámetro a la función se le mostrará al usuario. ?> Not a: El operador utilizado en la función par_impar() devuelve el resto de dividir los dos operandos. Si lo es. dentro de la función esos parámetros se utilizarán como si de variables se tratasen. }else{ print('impar'). por lo que sus nombres deben seguir las mismas reglas que definimos en el segundo capítulo.Ya hemos utilizado funciones con anterioridad. } } El nombre de esta función es par_impar(). Su código es el siguiente: function par_impar($numero){ if($numero % 2 == 0){ print('par'). }else{ print('impar'). significa que ese número es par. $numero. en caso contrario. La condición es que el resto de dividir el número pasado como argumento entre dos sea cero. Esta función puede recibir como argumento una cadena de texto que será mostrada en el cliente Web cuando se vea la página. A continuación puede ver el código de una página PHP en la que se define y utiliza la función anterior: <?php function par_impar($numero){ if($numero % 2 == 0){ printf('par'). Internamente. De hecho.

La realidad es otra: se muestra el número siete. Tiene razón. Si quiere que los parámetros que pase a la función puedan ser modificados y que esos cambios sobrevivan a la llamada de la función. sin necesidad de hacer nada más. print($i). más adelante. Entonces. Utilice esta técnica sólo cuando tenga soltura con la programación en PHP. qué valor mostrará una página con este código? Claro. a la función le estamos pasando una copia de la variable $i. Para lograrlo. Un parámetro se pasa por valor de forma predeterminada. incrementar($i). Valor y referencia La función par_impar() recibe un número como parámetro. El valor recibido no sufre alteración. Podría suponer que la página resultante mostrará el número ocho. } Not a: En la mayoría de los casos. consulte el apartado “Devolución de valores”. ?> ¿Qué pasará. } $i = 7. debe volver a escribir la función añadiendo un ampersand (&) al argumento en la definición de la función de la siguiente forma: function incrementar(&$numero){ $numero++. PHP pasará la variable en sí misma. Parámetros predeterminados .Sólo tiene que cambiar el valor que se pasa por un número par (digamos seis) para que la página resultante muestre el texto par . PHP permite que los parámetros de una función se pasen de dos formas: por valor y por referencia. resultado de incrementar el parámetro de la función. En realidad. Cualquier modificación que hagamos a dicha variable se perderá al terminar la función. en lugar de pasar una copia de la variable. ha de indicarle a PHP que ese parámetro se va a pasar por referencia. Si desea que su función devuelva algún valor. Pero ¿qué pasaría si lo modificásemos? Fíjese en el siguiente código. como en nuestra función incrementar(). si se lo estamos preguntando será porque no es obvio. no lo escriba en una página para probarlo: <?php function incrementar($numero){ $numero++. nuestras funciones no necesitan modificar los valores de los parámetros que recibe. comprueba que el valor sea par o impar y escribe un mensaje.

}else{ print('impar'). }else{ print('impar'). que es el valor que toma cuando ese parámetro no se pasa: function par_impar($numero = 0){ if($numero % 2 == 0){ printf('par'). Aviso de PHP Not a: En el mensaje de aviso puede verse la ruta en la que se encuentran las páginas. por lo que la función determina que el número pasado como parámetro es par. Sólo tiene que especificar el valor predeterminado del parámetro.PHP nos permite determinar qué valor debe tener un parámetro si al llamar a una función dicho parámetro no se ha proporcionado. el resto de dividir cero entre cero es cero. } } El comportamiento de la función es idéntico al que tenía antes. Puede comprobarlo porque al final de la misma puede leerse el texto par. al tratarse de un aviso (o warning). como puede verse en la figura 4. Argumentos variables Como hemos comentado. Sin embargo. el código de la página se ejecutará. Se trataría de este caso: <?php function par_impar($numero){ if($numero % 2 == 0){ printf('par'). Es muy sencillo evitar el aviso anterior. Pero PHP ofrece una posibilidad muy interesante: crear funciones que aceptan . PHP le avisará que no se ha pasado argumento alguno a la función par_impar(). La carpeta en la que está instalado Apache en su ordenador puede ser otra. Efectivamente. puede crear funciones que acepten más de un parámetro. } } par_impar(). Figura 4.1. con la salvedad de que no se produce ningún aviso. ?> Si intenta cargar la página anterior.1.

15). ha de crear una función sin parámetro alguno y luego ayudarse de las funciones de PHP func_num_args(). Para terminar. La diferencia está en que el código del segundo es mucho más simple. En este ejemplo. } sumatorio(3.un número variable de parámetros. Gracias al uso de estas funciones podrá crear con mucha facilidad una función que reciba una lista de valores y muestre en la página el resultado de sumarlos todos: <?php function sumatorio(){ $parametros = func_num_args(). ?> La función sumatorio(). } printf($resultado). Después. 14. ?> Como recordará. $i < $parametros. ¿Qué es eso de que la función func_get_arg() devuelve una matriz? . $i++){ $resultado += func_get_arg($i). Al finalizar todas las iteraciones. Utilizando la función func_get_args(). La primera de estas funciones devuelve el número de argumentos que la función ha recibido. 32. } printf($resultado). la instrucción foreach permite iterar por todos los elementos de una determinada matriz. que devuelve una matriz con todos los argumentos y el bucle foreach podemos simplificar bastante el código: <?php function sumatorio(){ foreach(func_get_args() as $parametro){ $resultado += $parametro. muestra el resultado. } sumatorio(3. la segunda un argumento en concreto de la lista de argumentos y la tercera una matriz con todos los argumentos que se han pasado a la función. ¡Un momento! Vamos a parar un momento. 14. guarda en la variable $parametros el número de argumentos que ha recibido. usando un bucle for recupera uno por uno el valor de los parámetros y los suma. 15). Para ello. $resultado contendrá la suma de todos los argumentos pasados a la función. en primer lugar. for($i = 0. El resultado será idéntico tanto usando un bucle for como usando un bucle foreach. func_get_arg() y func_get_args(). La variable $parametro contendrá en cada iteración un elemento diferente de la matriz.

} } if(par_impar(7) == TRUE){ print('par'). Por ejemplo. cedemos la decisión de escribir un texto en la página Web resultante al código que llama a la función. puede cambiar el código de la función par_impar() que construimos anteriormente. }else{ return(FALSE). más sosegado. En ese punto la función terminará.¿Cómo puedo hacer para que mis funciones devuelvan valores? Devolución de valores Nada más fácil que conseguir que una función escrita por usted devuelva un valor. En el primer capítulo fue un encontronazo. } } De esta forma. el contenido de la . Sólo ha de utilizar la instrucción return. nos permitió aprender las principales reglas del lenguaje. El código completo del programa podría ser el siguiente: <?php function par_impar($numero){ if($numero % 2 == 0){ return(TRUE). al añadir nuevos registros a dicha tabla. Si recuerda. construimos un pequeño programa para mostrar los géneros cinematográficos que se encontrasen almacenados dentro de la tabla genero de la base de datos videoteca. A continuación de ella indique el valor que la función debe devolver. en este libro hemos tenido dos contactos con PHP. en lugar de hacerlo directamente desde dentro de ella. }else{ print('impar'). El segundo. Ahora la función devolverá TRUE si el número pasado es par y FALSE en caso contrario: function par_impar($numero){ if($numero % 2 == 0){ return(TRUE). Fue entonces cuando comprobamos que. devolviendo el valor que ha indicado al código que la llamó. }else{ return(FALSE). } ?> Trabajando con funciones Hasta ahora. sólo nos interesaba tener una visión de conjunto de las posibilidades que MySQL y PHP ofrecían. Vamos a quedarnos con el primer capítulo.

'Aventuras'). INSERT INTO genero(nombre. descripcion) VALUES('A'. INSERT INTO genero(nombre. La versión final del código de dicha página es el siguiente: <?php $conexion = mysqli_connect( 'localhost'. INSERT INTO genero(nombre. 'Ciencia Ficción'). CREATE DATABASE videoteca. INSERT INTO genero(nombre. } ?> .'). el contenido de la página Web cambiaba sin necesidad de modificar el código PHP. exit(). PRIMARY KEY(id) ). 'Drama').al añadir nuevos registros a dicha tabla.'). if ($conexion == FALSE){ echo('Error en la conexión. 'root'. descripcion) VALUES('D'. nombre VARCHAR(2) NOT NULL. Por si acaso se saltó el primer capítulo. resumiremos. ''. descripcion) VALUES('T'. } $res = mysqli_query( $conexion. 'videoteca' ). 'Terror'). exit(). descripcion) VALUES('CF'. CREATE TABLE genero ( id INT UNSIGNED NOT NULL AUTO_INCREMENT. Ejecute el siguiente código SQL para crear la base de datos videoteca y la tabla genero e insertar los valores iniciales: DROP DATABASE IF EXISTS videoteca. descripcion VARCHAR(32) NOT NULL. mysqli_close($conexion). if ($res == FALSE){ echo('Error en la consulta. USE videoteca. 'SELECT * FROM genero' ).

2 muestra el resultado de ejecutar el código PHP anterior. A continuación escaparíamos de PHP. $fila[2] ). Figura 4. ¿No sería mucho más cómodo disponer de todo el código que se encarga de obtener el listado de géneros agrupado? Un primer intento podría consistir en situar todo lo relacionado con MySQL al comienzo del programa. ?> La figura 4. Podría ser algo así: <?php $conexion = mysqli_connect( 'localhost'. Ha sido necesario escapar de PHP en varias ocasiones. mysqli_close($conexion). Sólo tenemos que volver a PHP desde HTML para escribir la cadena que contiene el listado de géneros. $fila[1]. Puede cambiar el comportamiento del bucle while. printf( "<td>%u</td><td>%s</td><td>%s</td>". para que cree una cadena de texto a partir de los resultados obtenidos al realizar la consulta.2. printf('</tr>'). . } ?> </table> <?php mysqli_free_result($res). $fila[0].<table border="1"> <tr> <th>id</th> <th>nombre</th> <th>descripcion</th> </tr> <?php while($fila = mysqli_fetch_row($res)){ printf('<tr>'). Lista de géneros Si se fija en el listado de la página podrá comprobar que el código PHP está muy mezclado con el código HTML.

$fila[0].= sprintf( "<td>%u</td><td>%s</td><td>%s</td>".'). } $res = mysqli_query( $conexion. $generos . aunque el código está algo más ordenado.'root'. if ($conexion == FALSE){ echo('Error en la conexión. $fila[2] ). } mysqli_free_result($res). ?> <table border="1"> <tr> <th>id</th> <th>nombre</th> <th>descripcion</th> </tr> <?php print($generos).'). mysqli_close($conexion). } while($fila = mysqli_fetch_row($res)){ $generos .= sprintf('</tr>'). exit(). 'videoteca' ). if ($res == FALSE){ echo('Error en la consulta. ¿Y qué nos impide ubicar todo el código PHP en una única función. con dos bloques: uno con PHP y otro con HTML. mysqli_close($conexion). 'SELECT * FROM genero' ). exit(). que devuelva como resultado una cadena de texto con todos los géneros cinematográficos en filas para insertar en una tabla? Por ejemplo. $fila[1].= '<tr>'.2. ?> </table> El resultado es el mismo que puede verse en la figura 4. ''. $generos . así: <?php function cargar_generos(){ .

$fila[0]. 'root'. . $generos . } ?> <table border="1"> <tr> <th>id</th> <th>nombre</th> <th>descripcion</th> </tr> <?php print(cargar_generos()).'). mysqli_close($conexion). } $res = mysqli_query( $conexion.').function cargar_generos(){ $conexion = mysqli_connect( 'localhost'. Hemos conseguido colocar en una función todo el código necesario para cargar el listado de géneros cinematográficos. 'SELECT * FROM genero' ).= '<tr>'. exit(). ?> </table> Not a: Queda como ejercicio para el lector conseguir que la función cargar_generos() devuelva una cadena con toda la tabla en formato HTML. 'videoteca' ). exit(). ''.= sprintf('</tr>'). } mysqli_free_result($res). en lugar de devolver sólo las filas.= sprintf( "<td>%u</td><td>%s</td><td>%s</td>". Puede cargar ese listado todas las veces que quiera llamando a la función varias veces. if ($res == FALSE){ echo('Error en la consulta. $fila[1]. mysqli_close($conexion). $fila[2] ). } while($fila = mysqli_fetch_row($res)){ $generos . $generos . if ($conexion == FALSE){ echo('Error en la conexión. return $generos.

} while($fila = mysqli_fetch_row($res)){ $generos . crearemos un segundo archivo PHP con el siguiente contenido: <?php include('generos. } ?> A continuación. Inclusión de archivos Vamos a crear un nuevo archivo PHP cuyo contenido será única y exclusivamente la función de carga de géneros que acabamos de crear. if ($res == FALSE){ echo('Error en la consulta. si quiere escribir otra página diferente. if ($conexion == FALSE){ echo('Error en la conexión. 'videoteca' ). $fila[0]. $fila[1]. exit(). 'SELECT * FROM genero' ). } $res = mysqli_query( $conexion. mysqli_close($conexion). $generos . mysqli_close($conexion). que también muestre el listado de géneros tendrá que escribir de nuevo el código de la función. ''.php').= sprintf( "<td>%u</td><td>%s</td><td>%s</td>". return $generos. ?> <table border="1"> .'). $generos . $fila[2] ).').Ahora bien.php: <?php function cargar_generos(){ $conexion = mysqli_connect( 'localhost'. exit(). } mysqli_free_result($res).= sprintf('</tr>'). 'root'. Ese archivo podría llamarse generos. Aunque existe una forma de ahorrarse ese trabajo.= '<tr>'.

obtendrá el mismo resultado que pudo verse en la figura 4. puede utilizar la instrucción requiere. ?> </table> Ambos archivos deben estar en la misma carpeta. que sí provoca un error. Figura 4. ¿Qué ocurre si el archivo que se intenta incluir no existe? PHP nos avisará de ello. Archivo no encontrado Not a: Si desea incluir un determinado archivo sólo una vez dentro del contexto de una misma página utilice include_once(). Puede ver un error de este tipo en la figura 4. Podrá comprobar que.3. Si quiere evitar que el resto de la página se siga ejecutando. encuentra la instrucción include.2. Cuando PHP analiza el archivo para saber qué tiene que hacer cuando alguien le pide esa página. Ha aprendido a reutilizar el código mediante funciones. al cargar la segunda página. Sin embargo. Las diferencias entre estas dos son las mismas que entre include() y require(). que también permite reutilizar código pero que proporciona otras ventajas que veremos a continuación. guardando esas funciones en archivos independientes que luego pueden ser incluidos en otros archivos PHP. Entonces busca el archivo indicado a continuación y lo incluye en la página actual. el código de esta segunda página es considerablemente menor que el que se utilizó anteriormente. como si efectivamente ambos fragmentos de código fuesen parte de la misma página.3.<table border="1"> <tr> <th>id</th> <th>nombre</th> <th>descripcion</th> </tr> <?php print(cargar_generos()). También existe require_once(). Un paso más allá está la programación orientada a objetos. Orientación a objetos . pero aún así intentará ejecutar el código del resto de la página.

¿qué es una clase? Clases Podemos definir una clase como la plantilla utilizada para crear un objeto.Ríos de tinta han corrido hablando de la programación orientada a objetos. pero la mayoría de ellas en lo referido a la orientación a objetos. La figura 4. los programas anteriores mostraban la lista de categorías disponibles. pero utilizando orientación a objetos. El resultado de esta operación será una cadena de texto con las filas en formato HTML. una de salida si es de escritura. La versión de PHP 5 incorporó muchas novedades. Podríamos intentar escribir un programa cuyo resultado fuese el mismo.4 muestra una posible representación gráfica de una clase. de manera que vamos a limitarnos a sentar las bases necesarias para que esta metodología de programación no le sea desconocida. ¿Qué es un objeto? Un ejemplar de una clase. ¿Qué puede ser "el aspecto" de la lista de géneros? Por ejemplo. como la devuelta por la función cargar_generos(). La programación orientada a objetos tiene como finalidad una mejor organización de código y su posible reutilización. Sería muy pretencioso por nuestra parte intentar exponer todas esas novedades con el espacio del que disponemos. Una propiedad de la clase para los géneros podría determinar si el resultado se debe ordenar alfabéticamente o no. a la derecha sus propiedades. Las propiedades pueden ser de escritura. tan de moda durante mucho tiempo como XML lo está siendo ahora. . lo tenemos fácil: necesitamos poder pedir a la clase de géneros que cargue los géneros de la base de datos. su ordenación. Las propiedades de una clase describen su aspecto mientras que los métodos se corresponden con su comportamiento. la flecha será de salida. A la izquierda de la caja. de lectura o de ambos tipos. dependiendo de si puede asignarles valores o no. Por ejemplo. los métodos de la clase. Una flecha de entrada indica si la propiedad es de lectura. Intentemos crear una clase que represente a los géneros cinematográficos almacenados en la base de datos. En cuanto al comportamiento. En una clase se definen las propiedades y los métodos de los objetos creados a partir de ella. Si un método devuelve un valor. Para lograrlo hemos de intentar localizar las diferentes entidades con las que trabajamos en nuestros programas y aislarlas. Y una clase.

el contenido del archivo generos. El archivo se llamará generos. sin ordenación de ningún tipo. La propiedad Ordenada será de tipo booleano. Este método devuelve una cadena de texto que contiene todos los géneros de la base de datos. if ($conexion == FALSE){ echo('Error en la conexión. Not a: Si desea más información sobre consultas SQL consulte el capítulo 6. Para ellos vamos a utilizar un archivo que luego incluiremos en las páginas PHP que vayan a utilizar esta clase. de forma que podrá asignarle valores TRUE o FALSE .'). 'root'. } if($this->Ordenada == TRUE){ .cls. Sólo nos queda crear la clase. En caso contrario.Figura 4. Si le asigna TRUE el resultado de llamar al método Cargar() estará ordenado alfabéticamente. mientras que el método Cargar() devuelve un valor. El método Cargar() será similar a la función cargar_generos(). 'videoteca' ). Por tanto.cls. que está dedicado a ello.php podría ser el siguiente: <?php class clsGeneros{ var $Ordenada = False.4.php. ''. La propiedad Ordenada es de escritura. El nombre de la clase es clsGeneros. function Cargar(){ $conexion = mysqli_connect( 'localhost'. Diagrama de una clase Este diagrama describe a la clase perfectamente. exit(). el resultado se mostrará tal cual esté en la base de datos.

exit(). con una salvedad: la consulta que obtiene los géneros de la base de datos es diferente. con la que hemos estado trabajando anteriormente. El prefijo sirve para indicar que se trata de una clase. definimos el nombre de la clase: clsGeneros. como $Ordenada. que permite acceder a las propiedades y métodos de una clase desde el código de la propia clase. A continuación. 'SELECT * FROM genero' ). mysqli_close($conexion). $fila[0]. .= sprintf('</tr>'). cuyo valor predeterminado es FALSE . } mysqli_free_result($res).$res = mysqli_query( $conexion. El código del método Cargar() es como el de la función cargar_generos(). 'SELECT * FROM genero '. return $generos. mysqli_close($conexion).= sprintf( "<td>%u</td><td>%s</td><td>%s</td>". Esta variable es una de las propiedades de la clase. $generos . $generos . El código de la clase está entre llaves. } } ?> Como puede verse en el código anterior. comenzamos la declaración de la clase con la palabra reservada class. dependiendo del valor que tenga $Ordenada. }else{ $res = mysqli_query( $conexion. $fila[2] ). Es necesario utilizar la palabra reservada var antes de declarar una variable propia de una clase. Dentro de una clase puede definir variables. } if ($res == FALSE){ echo('Error en la consulta. 'ORDER BY nombre' ). $fila[1]. Not a: PHP proporciona un objeto especial llamado $t his. } while($fila=mysqli_fetch_row($res)){ $generos .= '<tr>'.'). estando el resultado ordenado por nombre si su valor es TRUE .

y tras estos caracteres. $oGeneros->Ordenada = TRUE. Una vez tenga el objeto necesita acceder a sus propiedades para modificar su comportamiento y realizar tareas mediante sus métodos.cls. Es decir. Puede comprobarlo en la figura 4. $sGeneros = $oGeneros->Cargar(). El resultado de este programa es similar al que pudimos ver en la figura 4. el nombre de la propiedad o el método que quiere utilizar. Para crear dicho ejemplar hemos de utilizar la palabra reserva new: $oGeneros = new clsGeneros. Cuando declaramos una variable cuyo tipo es una determinada clase se dice que estamos creando un ejemplar de esa clase.php'). ya que dicha página es imprescindible para la ejecución de ésta. Para ello ha de utilizar los caracteres -> a continuación del nombre del objeto.2. $oGeneros = new clsGeneros. Fíjese en que utilizamos require en lugar de include. En el programa anterior modificamos el valor de la propiedad Ordenada así: $oGeneros->Ordenada = TRUE. ?> <table border="1"> <tr> <th>id</th> <th>nombre</th> <th>descripción</th> </tr> <?php print($sGeneros). El prefijo o viene de objeto. La clase es la plantilla. pero si crea en su programa una variable cuyo tipo sea la clase tendrá acceso a toda la funcionalidad definida en dicha clase. Y llamamos al método de carga de los géneros así: $sGeneros = $oGeneros->Cargar(). Veamos un ejemplo: <?php require('generos. . el ejemplar de la clase es el objeto. pero la ordenación es diferente. La clase por sí misma no hace nada.Piense en esta clase como en una plantilla.5. ?> </table> Nuestra página comienza incluyendo aquella en la que se encuentra el código de definición de la clase. esta línea crea un nuevo ejemplar de la clase clsGeneros y lo asigna (lo guarda) en la variable $oGeneros.

?> <table><tr><td> <table border="1"> <tr> <th>id</th> <th>nombre</th> <th>descripción</th> </tr> <?php print($sGeneros1).cls. ?> </table> .5. $oGeneros1 = new clsGeneros. $sGeneros2 = $oGeneros2->Cargar(). Géneros ordenados por nombre Puede crear tantos ejemplares de la clase clsGeneros como necesite.php'). $oGeneros1->Ordenada = TRUE. $oGeneros2->Ordenada = FALSE.Figura 4. $sGeneros1 = $oGeneros1->Cargar(). y cada uno de ellos tendrá sus propias propiedades. El siguiente código es perfectamente válido: <?php require('generos. $oGeneros2 = new clsGeneros. ?> </table> </td><td> <table border="1"> <tr> <th>id</th> <th>nombre</th> <th>descripción</th> </tr> <?php print($sGeneros2).

el constructor es un método especial que se ejecuta siempre que se crea un ejemplar de dicha clase. Ahora.. Con y sin orden En la definición de la clase asigne un valor inicial a la propiedad $Ordenada.6. Si añade el siguiente método al código de la clase clsGeneros tendrá su constructor.6. Puede verlo en la figura 4. } Hemos trasladado la asignación de un valor inicial a $Ordenada al constructor de la clase.. Figura 4. mientras que la segunda no. Más allá de las clases . Constructores Dentro de una clase.</table> </td></tr></table> Como resultado de cargar esta página obtendrá dos tablas. Sería interesante que recibiese si quiere o no la lista de géneros ordenada: function clsGeneros($fOrdenada){ $this->Ordenada = $fOrdenada. el comportamiento predeterminado del método de carga será devolver la lista de géneros ordenada. } Al crear el ejemplar de la clase indicaremos si queremos ordenación o no: $oGeneros = new clsGeneros(TRUE). es posible definir una lista de argumentos que el constructor puede recibir. Como si de un método normal y corriente se tratase. Esa operación puede realizarse de otra manera: utilizando un constructor. . function clsGeneros(){ $this->Ordenada = TRUE. Hágalo justo debajo de la definición del método de carga: var $Ordenada. El nombre de ese método especial debe ser el mismo que el de la clase. la primera mostrará la lista de géneros ordenados por nombre.

Con lo visto en este capítulo sobre las clases en PHP no hemos hecho más que descubrir la punta del iceberg. En el tintero hemos dejado algunas de las características más aplaudidas de la programación orientada a objetos: encapsulación, herencia y polimorfismo. De hecho, son estas tres características las que diferencian este sistema de programación de otros. La encapsulación, en la jerga de los programadores, es la capacidad de ocultar las interioridades de las clases a aquellos que las usan. Sin ir más lejos, el método de carga de la clase clsGeneros utiliza la interfaz mejorada de acceso a MySQL pero, si alguien utiliza esa clase para acceder al listado de géneros, ¿debería saber que esos géneros están en una base de datos? No necesariamente. Al usuario le basta con saber que cuando crea un ejemplar de la clase y llama a su método de carga obtiene la lista de géneros. Si más adelante, el programador de clsGeneros decide que el listado de géneros se debe obtener utilizando otra interfaz de acceso a datos, mientras mantenga el mismo sistema para obtenerlos, aquellos programas que utilicen esa clase no deberán ser modificados. La programación orientada a objetos busca símiles entre el mundo real y el de la programación para simplificar la creación y el mantenimiento de programas. La herencia es otro símil, muy próximo al significado de esta palabra en el mundo real. Puede crear una clase con unas determinadas características y, posteriormente, otra que herede de la primera. La clase heredera tendrá todas las características de la primera pero podrá incorporar novedades, lo que le ahorrará mucho trabajo. Por último, el polimorfismo permite tratar clases de diferente tipo como si fuesen del mismo, algo que puede ser de gran utilidad en determinadas circunstancias. No nos extenderemos más para hablar de estas características de la programación orientada a objetos, algo que queda fuera de los objetivos de este libro. Sin embargo, queremos que conozca de su existencia y le recomendamos que busque más información al respecto, ya que sus programas pueden beneficiarse enormemente de ellas.

5

Diseño de bases de datos
Por lo general, creamos bases de datos para poder extraer de ellas posteriormente todo tipo de información útil. Pero los datos no deben guardarse de cualquier manera, hemos de buscar el mayor aprovechamiento de los recursos disponibles, tanto de espacio como de rendimiento. La consistencia de los datos ha de mantenerse durante todo el ciclo de vida de la base de datos, sobre todo si ésta vaya a utilizarse en aplicaciones críticas, como las destinadas a emitir las nóminas de los empleados de una empresa. Si los datos almacenados no mantuviesen la consistencia alguien podría acabar no cobrando este mes. El primer paso en la creación de una base de datos es el análisis del sistema que servirá de modelo, la observación de todos los elementos que lo componen y su descomposición en partes más pequeñas. Tras el análisis, procederemos con el diseño de la base de datos. Un diseño correcto puede ser crucial, de manera que debe dedicarle todo el tiempo necesario hasta estar completamente seguro de que no existan incongruencias y todos los aspectos del sistema están reflejados en la base datos. Durante este capítulo recorreremos todos los pasos que deben darse para dar vida a una base de datos, desde la idea inicial hasta su creación, pasando por los pasos intermedios necesarios. Veremos qué herramientas están a nuestra disposición, tanto las conceptuales como los programas. Al terminar dispondremos de un diseño completo de la base de datos que utilizará como ejemplo durante el resto de capítulos.

El ejemplo
En el capítulo 3 se utilizó como ejemplo una pequeña base de datos que contenía una única tabla en la que se almacenaban sólo tres datos de cada película de una videoteca: el título, el nombre del director y el de uno de sus intérpretes. La figura 5.1 muestra el diseño que se hizo de dicha tabla.

Figura 5.1. Primer diseño del ejemplo

En esta tabla se pueden guardar perfectamente los datos de todas las películas que desee, aunque no sin

limitaciones. De hecho, se trata de una base de datos algo limitada... bueno, muy limitada. ¡Bah, para qué engañarnos! La primera versión de la base de datos de ejemplo no sirve para nada. Se podría conseguir lo mismo usando una hoja de cálculo creada con Excel, Gnumeric o Numbers. Al menos sirvió para su propósito: una primera toma de contacto con el servidor de bases de datos MySQL.

Limitaciones
La primera versión de la base de datos de ejemplo es demasiado simple. Sólo se puede guardar el nombre de uno de los intérpretes de la película, aunque sería mucho más interesante tener los nombres de tantos actores relacionados con un título en concreto como se quisiese. Y aunque no es muy frecuente, existen algunas películas con más de un director. Tampoco se guarda detalle alguno sobre la duración de la película, su fecha de estreno, sus productores, guionistas, es decir, su ficha técnica. Ni se pueden conocer detalles relativos a una copia de la película en particular, como si el formato es VHS o DVD, o si se ha prestado, la opinión que le merece o les mereció a otros, etcétera. Por otra parte, en esta primera versión, cada vez que se guarda una película se han de guardar los datos del director y del actor, incluso si con anterioridad existía algún registro con el mismo actor o director. Quizá los datos podrían estar mejor organizados.

Objetivos
Antes de diseñar de nuevo el ejemplo es necesario dar otros pasos. En primer lugar, debemos conocer las herramientas que tenemos a nuestra disposición para la creación de bases de datos. Por herramientas no sólo nos referimos a los programas, también a otras de tipo conceptual de las que daremos buena cuenta durante este capítulo. En la parte de los programas veremos cómo utilizar MySQL Workbench. Esta aplicación le ayudará en la fase de diseño de bases de datos y en su posterior puesta en marcha, ya que genera de forma automática el código SQL necesario para la creación de bases de datos y tablas. Se trata de un programa de código abierto que se distribuye bajo licencia GPL, creado por la empresa detrás de MySQL sobre las cenizas de DBDesigner .
Not a: Aunque en el momento de escribir estas líneas las versiones para Mac OS X y Linux están en fase alfa, el equipo de desarrollo de MySQL Workbench se ha comprometido a lanzarla en las tres plataformas.

En cuanto a las herramientas conceptuales, primero veremos algunos conceptos que no se han tratado aún. Es el caso del modelo relacional, imprescindible como ayuda para mantener la integridad de los datos. El capítulo

terminará con algunas indicaciones sobre los pasos a seguir para que las bases de datos puedan almacenar los datos de forma inequívoca.

MySQL Workbench
Según las propias palabras del equipo encargado del desarrollo de esta aplicación, "MySQL Workbench es una herramienta para el diseño visual de bases de datos desarrollada por MySQL. Se trata del esperado sucesor del proyecto DBDesigner4". DBDesigner era (y sigue siendo, visite http://fabforce.net/dbdesigner4/) un sistema para el diseño visual de bases de datos que integraba en un entorno unificado las fases de diseño, modelado, creación y mantenimiento. Con MySQL Workbench es posible diseñar tablas, cambiar los tipos de las columnas, sus nombres, una y otra vez, sin tener que escribir ni una sola línea de código. Y cuando estemos satisfechos con nuestro trabajo, el programa puede generar por nosotros todo el código necesario para crear la base de datos en MySQL. En la figura 5.2 puede ver el entorno que este programa proporciona.

Figura 5.2. Entorno de trabajo de MySQL Workbench

No se trata del único programa de este tipo que existe. Otras alternativas son: Navicat, de PremiumSoft. PowerDesigner, de Sybase.

DataArchitect, de theKompany. Rational Rose, de IBM. Lo que diferencia a MySQL Workbench del resto es su licencia GPL, la disponibilidad para múltiples sistemas operativos y, sobre todo, que está mejor integrado con MySQL que los demás. Es normal, ambos productos están desarrollados por la misma empresa.

Instalación
MySQL Workbench está siendo desarrollado para tres plataformas muy diversas. Por lo que sabemos, aprovechará las características particulares de cada una de ellas, de manera que el proceso de instalación será diferente en cada sistema operativo: En Windows se utiliza el típico programa de instalación guiado por asistente. No existen demasiadas opciones que configurar, basta con seguir los pasos y podremos utilizar el programa en un periquete. En Linux, por el momento, las primeras versiones disponibles se están ofreciendo a través de sistemas tan utilizados como APT, disponible Debian y Ubuntu, por ejemplo. A medida de que esta versión madure estará disponible en los gestores para la instalación de paquetes del resto de distribuciones. Las imágenes de disco (archivos DMG) se utilizan para la instalación en Mac OS X. Basta con hacer doble clic sobre el archivo ofrecido para esta plataforma y arrastrar el contenido del mismo a la carpeta de aplicaciones.
Not a: De momento, MySQL Workbench se distribuirá en dos versiones, siguiendo lo que parece será una norma. Por una parte está la versión para la comunidad, disponible de manera gratuita y bajo licencia GPL. Por otra, la versión estándar, distribuida bajo una licencia comercial. Adivine cuál de las dos versiones ofrece más características. Es posible que, en el futuro, aparezcan más ediciones para complementar a estas dos.

Conceptos varios
Antes de comenzar con el diseño del ejemplo que utilizaremos durante este libro es necesario que conozca algunos conceptos que se utilizan en la mayoría de los sistemas gestores de bases de datos y, como no podía ser de otra manera, también en MySQL.

El valor NULL
O el infierno por el que han de pasar muchos. Pido disculpas si no puedo ser parcial en esta sección: he sufrido mucho con NULL. El valor NULL es una de esas herramientas que no dejan indiferentes: muchos la encuentran indispensable, otros prefieren atravesarse el ojo con un hierro al rojo vivo hasta llegar al cerebro antes que utilizarlo.

Parece que he dejado clara mi opinión, mas no se deje influir, permítame que le explique con total imparcialidad cómo funciona NULL. Si no existe un valor para una determinada columna, se suele guardar uno representativo, como una cadena vacía o un cero, dependiendo del tipo de datos de la columna. Pero, ¿qué hacer cuando no se conoce el valor de esa columna? Precisamente ésa es la función de NULL: es el valor contenido en las columnas para las que no se ha introducido dato alguno. Cualquier columna que cree dentro de una tabla, independientemente de su tipo, puede almacenar este valor, a no ser que explícitamente se diga lo contrario. Recuerde que, cuando creó la tabla pelicula en el tercer capítulo, lo hizo así:
USE videoteca;

CREATE TABLE pelicula( titulo VARCHAR(64), director VARCHAR(128), actor VARCHAR(128) );

Como ya insertó algunos registros en esta tabla puede realizar consultas de selección sobre ella. La siguiente consulta muestra el título de las películas en una columna y, concatenados, el nombre de director y el del actor, separados por comas:
USE videoteca;

SELECT titulo, CONCAT(director, ', ', actor) FROM pelicula;

La función CONCAT recibe como parámetros las cadenas que desee concatenar. En este caso se concatenan tres: el nombre del director, una coma seguida de un espacio y el nombre del actor. El resultado de esta consulta puede verse en la figura 5.3.

Figura 5.3. Concatenación de dos cadenas

5. Se ha insertado NULL ¿Qué ocurrirá ahora si vuelve a utilizar la consulta que concatena el nombre del director y el del actor? Podríamos esperar que sólo devolviese el título de la película y el nombre del director.Ahora vamos a insertar una nueva película. INSERT INTO pelicula( titulo. así es como debe ser. De ella conocemos el título y el nombre del director.4: USE videoteca. El resultado de comparar cualquier valor . SELECT * FROM pelicula. pero ningún intérprete: USE videoteca. Concatenación con NULL Y no se trata de un comportamiento erróneo. La inserción se realizará sin problemas. Figura 5. La siguiente consulta de selección devolverá los valores que pueden verse en la figura 5.5.4. sin el actor. Pero la realidad puede verse en la figura 5. director ) VALUES( 'Naves misteriosas'. ya que no se proporcionó valor alguno durante la inserción. Figura 5. La columna actor contendrá el valor NULL. 'Douglas Trumbull' ).

Utilice la instrucción ALTER TABLE que vimos en el tercer capítulo: . como el uso de cadenas vacías. Cualquier operación aritmética en la que participe un valor NULL da como resultado NULL. Por simplicidad. También es posible cambiar las propiedades de la tabla de películas de acuerdo a lo que acaba de ver. Quede claro que esta recomendación se debe nada más que a experiencias personales. pero no el director ni el actor. la recomendación desde aquí es evitar en lo posible el uso de valores nulos. DROP TABLE IF EXISTS pelicula. como en la última que se ha utilizado para la película "Naves misteriosas". Empecemos por eliminar la película que acabamos de añadir ya que el valor nulo en la columna actor de la tabla de películas impide la modificación de dicha característica de la tabla: USE videoteca. pero sin eliminar los registros que ya ha insertado en ella. DROP TABLE IF EXISTS pelicula. El siguiente código hará que se guarde una cadena vacía en esas columnas si no se indica un valor para ellas durante las inserciones: USE videoteca. Puede evitar la aparición de dicho error si asigna un valor predeterminado para las columnas no obligatorias. Existen variadas alternativas para evitar este comportamiento. CREATE TABLE pelicula( titulo VARCHAR(64) NOT NULL. si en una inserción no indica el valor de alguna columna. De esta forma. actor VARCHAR(128) NOT NULL ). DELETE FROM pelicula WHERE titulo = 'Naves misteriosas'. se producirá un error. Para evitar la inserción de valores nulos en los campos de la tabla de películas puede cambiar la forma en la que se crea: USE videoteca. director VARCHAR(128) NOT NULL.con NULL es NULL. CREATE TABLE pelicula( titulo VARCHAR(64) NOT NULL. director VARCHAR(128) NOT NULL DEFAULT ''. actor VARCHAR(128) NOT NULL DEFAULT '' ). En el caso de la tabla de películas podríamos hacer obligatorio el título. Cualquier concatenación con NULL acaba siendo NULL.

por Sigourney Weaver: USE videoteca. a continuación. Insertemos una más.6. llamada "Aliens". con lo que es posible utilizar la misma consulta para aquellas películas de las que no conozca su director o su actor. consulte el contenido de la tabla pelicula y ordene el resultado por título: USE videoteca. MODIFY director VARCHAR(128) NOT NULL DEFAULT ''. SELECT * FROM pelicula . Ahora. esta vez la segunda parte de "Alien". 'James Cameron'. Figura 5.6 muestra el resultado de dicha consulta. La figura 5. Si. podrá comprobar que el resultado ya no incluye ningún NULL. que está dando mucho juego. ejecuta la consulta de selección que concatena el nombre del director y el del actor. 'Sigourney Weaver' ). INSERT INTO pelicula VALUES( 'Alien'. vuelve a insertar la película "Naves misteriosas" y. de nuevo. La inserción se realiza sin problemas.Utilice la instrucción ALTER TABLE que vimos en el tercer capítulo: USE videoteca. ALTER TABLE pelicula MODIFY titulo VARCHAR(64) NOT NULL. MODIFY actor VARCHAR(128) NOT NULL DEFAULT ''. tras modificar la tabla. Concatenación sin NULL Claves primarias Para explicar qué es una clave primaria vamos a volver a utilizar la tabla pelicula. dirigida por James Cameron y protagonizada.

director VARCHAR(128) NOT NULL DEFAULT ''.pelicula ORDER BY titulo. MySQL ha permitido introducir dos películas con el mismo título! Esto no está bien. Con la segunda parte de "Alien" ¡Uy. PRIMARY KEY(titulo) ). ALTER TABLE . Figura 5. Todos los registros deben tener algún valor almacenado en esa columna (no se permiten valores NULL). con las relaciones muchos a muchos. no era Alien sino Aliens. CREATE TABLE pelicula( titulo VARCHAR(64) NOT NULL. Sólo se ha añadido una línea al final de las definiciones de las columnas para indicar qué campos componen la clave primaria. el título de la película debería ser algo único. un valor mediante el cual se puede distinguir de forma única cada elemento de una determinada tabla. También puede modificar la tabla ya existente.7. Cambie la sentencia para crear la tabla pelicula de manera que el título sea la clave primaria: USE videoteca. Y precisamente eso es una clave primaria. ¡Pero aun así. así no perderá los datos almacenados en ella: USE videoteca. actor VARCHAR(128) NOT NULL DEFAULT ''. Vea el resultado de realizar esta consulta en la figura 5. algo que permita diferenciar una película de otras. Veremos un ejemplo de esto al final del capítulo. qué torpe! El título no se ha introducido correctamente.7. Not a: Se puede utilizar más de una columna como clave primaria en aquellos casos en los que sólo se consiguen valores únicos al combinar dos columnas. y todos los valores de dicha columna deben ser diferentes.

Y. que encontrará rápidamente gracias a que está organizado por orden alfabético. se produce un error: existe un valor duplicado para la clave que está intentado crear. Bastante más rápido que leer desde la primera página hasta localizarlo. que le permitía precisamente indicar qué valor se insertaría en una columna si no se indicaba ninguno. cree un índice para ella. Si insertábamos de forma explícita un valor. . Para las tablas se puede utilizar una técnica similar. UPDATE pelicula SET titulo = 'Aliens' WHERE director = 'James Cameron'. con el paso del tiempo. Si sabe que las búsquedas de valores de una determinada columna serán frecuentes. Solucionarlo es bien sencillo: USE videoteca. Podría llevarse una sorpresa si. También hemos realizado un par de inserciones implícitas. No era necesario indicar un valor porque MySQL insertaba la fecha y la hora en la que se estaba realizando la inserción del registro o su modificación. como verá. Ahora que no existen dos películas con el mismo título puede ejecutar la consulta que añade la clave primaria a la tabla sin que se produzca ningún error. ¿Recuerda? "Alien" aparece dos veces. Hablaremos con más detalle los índices en el capítulo dedicado a la optimización. sabíamos que éste sería el almacenado en la columna. se encuentra con que sí existen dos películas con el mismo título. La segunda inserción implícita tenía lugar al utilizar el tipo TIMESTAMP . y allí aparecerá el número de página al que tiene que acudir. Índices Con un índice es posible encontrar más rápido los datos que se necesitan. Una de ellas. Columnas de incremento automático Todas las operaciones de inserción realizadas en los capítulos anteriores tenían algo en común: se conocían de antemano los valores a insertar en cada columna. Es muy importante seleccionar las claves correctas. de manera que sean únicas.ALTER TABLE pelicula ADD PRIMARY KEY(titulo). Como en el que aparece al final de esta guía: busque el término que le interese. al explicar el uso del modificador DEFAULT . las dos en el capítulo dedicado a tipos de datos.

para que MySQL se encargase de hacer que todos sus valores fuesen diferentes. PRIMARY KEY(id) ). dirigida por John Carpenter. La única condición que debe cumplir es que sea diferente para cada registro. Utilice las siguientes instrucciones para crear una tabla con esas características: USE videoteca. Por ejemplo. Anteriormente tomamos la decisión de utilizar como clave primaria de la tabla de películas el título de las mismas. lo ideal sería que la columna fuese de incremento automático. Con cada nueva inserción en la tabla. Podría tratarse de un número. "La cosa". Puede comprobarlo en la figura 5. porque es algo que no se repite. la historia del cine está plagada de películas con títulos idénticos. Y para ahorrar esfuerzos. manteniendo los registros ya existentes: USE videoteca. es una nueva versión de la película del mismo título de 1951. con el mismo título? Una solución podría consistir en añadir una columna más y utilizarla como clave primaria de la tabla. ¿No debería ser posible insertar en la tabla las dos películas. titulo VARCHAR(64) NOT NULL. CREATE TABLE pelicula( id INT NOT NULL AUTO_INCREMENT. Si selecciona todos los registros de la tabla verá que a los existentes ya se les ha asignado un identificador único.Existe otra forma de insertar valores de forma implícita en una columna: utilizando el incremento automático. ADD id INT NOT NULL AUTO_INCREMENT FIRST. actor VARCHAR(128) NOT NULL DEFAULT ''. Sin embargo.8. . director VARCHAR(128) NOT NULL DEFAULT ''. Es posible que el identificador asignado a cada película que aparece en dicha figura no sea el mismo en su caso. ALTER TABLE pelicula DROP PRIMARY KEY. un nuevo valor se insertará de forma automática en la columna id. diferenciando de forma única cada registro de la misma. un identificador que permita diferenciar entre una y otra película. ADD PRIMARY KEY(id). También existe la posibilidad de modificar la tabla para lograr el mismo resultado.

Por supuesto. Sin embargo. ha decidido guardar en otra tabla de la base de datos una lista de préstamos. Y con el tiempo es al terminar este capítulo. tanto impresas como en Internet. y siempre se le olvida a quién deja qué película. le recomendamos que lo haga.Figura 5. Es más.9.8. En esa lista sólo necesita almacenar el . de ahí la palabra relacional. El modelo relacional Es posible que haya escuchado en más de una ocasión que MySQL es un sistema gestor de bases de datos relacionales. Nueva clave primaria Puede que ahora mismo no encuentre demasiada utilidad a este tipo de columnas. Figura 5. con el tiempo comprenderá que se trata de una herramienta imprescindible. La tabla de películas. tanto histórica como teórica. esto es una guía práctica. que es posible relacionar entre sí las diferentes tablas que componen una base de datos. ¿Cómo se consigue algo así? Vea en la figura 5. a fin de cuentas. Lo mejor para comprenderlo es un sencillo ejemplo. Suponga que tiene tantas buenas películas que sus amigos no hacen más que pedírselas prestadas. tras algunos cambios Si necesitase relacionar una película con otra tabla sólo tendría que incluir en esa tabla el identificador de la película a la que hace referencia. si está interesado podrá encontrar todas las fuentes de documentación al respecto que necesite.9 cómo ha quedado el diseño de la tabla de películas tras aplicar lo aprendido en los apartados anteriores. Tras este modelo para la organización de los datos existe amplia documentación. en esta guía prima lo práctico. En el modelo relacional es necesario que las tablas compartan datos para poder relacionarlas. Pero como de memoria no anda tan bien como de amigos y películas. Sin embargo. A los más puristas no les gustará nada que nos saltemos toda esa parte pero. ¿Qué significa esto? Entre otras cosas.

id. idpelicula INT NOT NULL. que contiene la clave externa. Utilice las siguientes instrucciones para crear la tabla de préstamos: USE videoteca. se dice que se está manteniendo la integridad referencial entre las tablas. La segunda columna. el identificador que MySQL asignó automáticamente a esa película es el 4. Para ello sólo tenemos que realizar inserciones en la tabla de préstamos. fecha DATE NOT NULL. En primer lugar.nombre de la persona.10. algo parecido a lo que se puede ver en la figura 5. Lo ideal sería que MySQL controlase que en ese campo sólo se pudiesen insertar valores existentes en dicha tabla. PRIMARY KEY(id). CREATE TABLE prestamo ( id INT NOT NULL AUTO_INCREMENT. Como la tabla de películas contiene un campo llamado id que identifica a cada registro de forma inequívoca. vamos a prestar "Contact" a Kake. persona.10. y que idpelicula es una clave externa. el identificador de la película. la película que se lleva prestada y en qué fecha se la llevó. contiene el nombre de quien se lleva la película. tiene las mismas características que la homónima de la tabla pelicula: un identificador de incremento automático. mientras que la tabla a la que hace referencia se conoce como tabla madre o principal. Not a: La tabla prest amo. En tercer lugar. DROP TABLE IF EXISTS prestamo. Figura 5. existe la posibilidad de que se inserte como identificador de la película un valor sin contrapartida en la tabla pelicula. Como pudo verse en la figura 5. FOREIGN KEY(idpelicula) REFERENCES pelicula(id) ). puede guardar aquí ese campo para saber qué película se llevó su amigo. persona VARCHAR(128) NOT NULL. Ahora que disponemos de dos tablas relacionadas vamos a comprobar que se cumple lo descrito acerca de las relaciones. que es la clave primaria de la tabla. . así que: USE videoteca. Cuando esa condición se cumple. idpelicula.8. Tabla de préstamos La primera columna. se conoce como tabla hija o secundaria. Pero claro.

intentando prestar una película no presente en la base de datos. MySQL le informará de que ha surgido un error. INSERT INTO prestamo( idpelicula.INSERT INTO prestamo( idpelicula. persona. persona. Si ahora selecciona todos los registros de la tabla prestamo podrá ver algo parecido a lo que aparece en la figura 5. fecha ) VALUES( 123. CURRENT_DATE() ). no se preocupe en absoluto.. Utilice el identificador asignado en su sistema para este ejemplo. CURRENT_DATE() ). 'Germán'. ¿Cómo? ¿Que no informa de ningún error? ¿Que se ha podido realizar la inserción? Claro que se ha podido. sólo intentaba comprobar si prestaba atención. El propósito de esta jugarreta ha sido demostrarle lo sencillo que es perder la consistencia de los datos de una . fecha ) VALUES( 4.11. El primer préstamo Ahora comprobaremos cómo funciona la integridad relacional. hemos utilizado la función CURRENT_DATE() para guardar la fecha actual en la columna fecha. Advert encia: Es posible que el identificador de "Contact" en su tabla de películas sea otro.11. Figura 5. Utilice un identificador de película que no exista: USE videoteca.. 'Kake'. Como ve.

no incorpora los mecanismos de integridad relacional. Ahora. DROP TABLE IF EXISTS prestamo. de las que ya hablamos en el capítulo tercero. así de fácil. Intente ahora la inserción del préstamo de una película inexistente: USE videoteca. no MyISAM. En este caso no bastaría con cambiar el tipo de tabla ya que esa operación no crearía las estructuras necesarias para el mantenimiento de la integridad referencial. . Localizar este tipo de problemas en una tabla con dos registros es sencillo pero. elimine y vuelva a crear la tabla de préstamos: USE videoteca. película que no existe en la base de datos. fecha DATE NOT NULL. FOREIGN KEY(idpelicula) REFERENCES pelicula(id) ) ENGINE = InnoDB. simplemente las ignora. Esta última inserción ha conseguido que se inserte un préstamo de la película con identificador 123. idpelicula INT NOT NULL. PRIMARY KEY(id). MyISAM. el tipo de tabla predeterminado es InnoDB. Para lograr nuestro objetivo hemos de utilizar tablas InnoDB. ALTER TABLE pelicula ENGINE = InnoDB. que rompía la integridad referencial. Esto se debe a que. INSERT INTO prestamo( idpelicula. Si quiere comprobar de qué tipo es una tabla sólo tiene que utilizar la instrucción SHOW CREATE TABLE seguida del nombre de la tabla en cuestión y localizar la palabra clave ENGINE. persona VARCHAR(128) NOT NULL.base de datos si no se presta atención durante la fase de diseño. CREATE TABLE prestamo ( id INT NOT NULL AUTO_INCREMENT. Not a: Aquellos usuarios de Windows que hayan instalado MySQL usando el asistente se preguntarán qué ha ocurrido y por qué no les ha dejado realizar la inserción anterior. Hecho. El primer paso para lograr que la integridad referencial funcione es convertir la tabla de películas en una tabla InnoDB: USE videoteca. ¿y si esta tabla tuviese miles? ¿Por qué no se ha cumplido ni una palabra de cuanto ha aprendido sobre relaciones entre tablas? Muy sencillo: el tipo de tabla predeterminado de MySQL. Cuando MySQL encuentra las instrucciones de integridad referidas a una tabla MyISAM. para ellos. persona.

Figura 5. Una de ellas contendrá información sobre los actores. ya que así sólo podría guardar un registro por película. es el "divide y vencerás".12 muestra un diagrama de su primera base de datos con tablas relacionadas. Uno a muchos: Se da en el caso de que un registro de la tabla hija sólo pueda estar relacionado con un registro de la tabla madre. Tras lo visto hasta ahora dispone de los conocimientos necesarios para afrontar el objetivo de este capítulo. mejorar el diseño de esta base de datos. La figura 5. Como podrá comprobar. fecha) VALUES( 123. Un préstamo sólo se aplica a una determinada película. Sería el caso de la relación entre películas y préstamos si el identificador de la película de esta última fuese la clave primaria. A su vez. y en el de la informática en general.persona. relacionada con la tabla de películas. MySQL ya no le permite insertar en la columna idpelicula identificadores de películas que no estén en la tabla pelicula. . en una película pueden participar muchos actores. Adelantando contenidos. Muchos a muchos: En esta relación. Un actor puede haber participado en muchas películas y. Una de las técnicas más empleadas en el mundo de las bases de datos. Resulta interesante si no se quiere almacenar un histórico de préstamos (algo que ahora sí se puede hacer). Hemos logrado (no sin esfuerzo) nuestro objetivo. un registro de la tabla hija puede estar relacionado con cualquier registro de la tabla madre y viceversa. CURRENT_DATE() ). aunque a lo largo del tiempo esa película la ha podido tener mucha gente. en el siguiente apartado dividiremos la tabla de películas en otras tablas. Es el caso de la relación entre tablas que acaba de crear. 'Germán'. Relación entre películas y préstamos Para terminar este apartado vamos a ver qué clases de relaciones entre tablas existen atendiendo al número de elementos que se ven involucrados: Uno a uno: Un registro de una de las tablas sólo puede estar relacionado con un registro de la otra tabla. un registro de la tabla principal puede estar relacionado con más de uno de la tabla hija. a su vez.12.

director VARCHAR(128) NOT NULL DEFAULT ''. Se guardará en una cadena de 32 caracteres. actor VARCHAR(128) NOT NULL DEFAULT ''. Creación de tablas con MySQL Workbench Vamos a mejorar el diseño de la tabla de películas. aparece en la barra de direcciones.9.13 muestra la página del director Ridley Scott . etcétera). . DVD. nm0000631. Pudo ver su diseño en la anterior figura 5. añadiéndole algunos campos más en los que poder guardar otros datos que pueden resultar interesantes: soporte: Una cadena de tres caracteres que guardará el formato en el que está la grabación (VHS. PRIMARY KEY(id) ) ENGINE = InnoDB. imdb_director: El identificador que la famosa Web IMDb (http://imdb. CREATE TABLE pelicula( id INT NOT NULL AUTO_INCREMENT.Divide y vencerás El punto de partida es la tabla pelicula de la base de datos videoteca que ha construido a lo largo de este capítulo. La figura 5. Una aplicación podría utilizar este dato para mostrar una página con detalles de un director en concreto. Su identificador.com/) dedicada al cine asigna a ese director. titulo VARCHAR(64) NOT NULL. Utilizó estas instrucciones para crearla: USE videoteca.

Inicialmente.14. el aspecto de este programa es que el puede verse en la figura 5. Siga estos pasos para crear esta tabla utilizando MySQL Workbench: 1. genero_desc: Descripción de las siglas del campo anterior.Figura 5. pero aplicado al actor. . genero: Siglas del género cinematográfico al que pertenece la película. Ridley Scott en IMDb imdb_actor: Igual que el campo imdb_director .13. Ponga en marcha MySQL Workbench.

También puede utilizar la combinación de teclas Control-T . 3. Vamos a añadir un nuevo diagrama: seleccione la opción Add Diagram del menú Model. MySQL Workbench 2. tal y como muestra la figura 5.Figura 5.15.14. Para comenzar a trabajar con un documento en blanco seleccione la opción New del menú File. mostrándole una rejilla en la que podrá situar los diferentes elementos que compongan su base de datos. El aspecto de MySQL Workbench cambiará. .

EER Diagram. Escriba videoteca y pulse la tecla Intro. significa diagrama entidad-relación mejorado (Enhanced Entity Relationship). se insertará una nueva tabla. Aparecerá una nueva tabla con un nombre predeterminado table1.14. como puede ver en la figura 5. Cree una nueva tabla. bajo la barra de menús. . El nombre de la base de datos actual es mydb. Antes de nada. Haga clic sobre él. 6. También puede hacer clic con el botón derecho sobre él y seleccionar la opción Rename del menú contextual. es la que pudo ver en la figura 5. Para ello. MySQL Model. Diagrama en blanco Not a: Fíjese en que. espere y vuelva a hacer clic para poder editar su nombre. haga clic en el icono Place a New Table de la barra de herramientas que se encuentra en la parte izquierda de la ventana del programa. cuando haga clic sobre la zona de edición del documento. La primera.Figura 5. La segunda.16.15. Haga clic en la zona de edición del documento. El puntero del ratón cambiará de forma para indicarle que. 4. en la parte central de la ventana donde se encuentra la rejilla. cambie el nombre de la base de datos. aparecen ya dos fichas. 5. Fíjese en el panel de la derecha llamado Catalog.

Figura 5. . Nueva tabla 7. cambiar sus propiedades.17 le muestra este panel tal y como quedaría tras introducir los detalles de las columnas de la tabla pelicula. MySQL Workbench le presentará el editor de tablas. en la parte inferior de la ventana del programa. La figura 5. el tipo de tabla.16. Haga doble clic sobre el nombre de tabla que acaba de aparecer. etcétera. desde el que puede añadir nuevos campos.

Para terminar. Para crear esta tabla cree primero la base de datos . La base de datos de películas que está diseñando se encuentra ahora mismo en lo que algunos llaman la forma normal cero: contiene todos los datos que se desean mostrar y una clave primaria. Diseñando la nueva tabla 8. titulo VARCHAR(64) NOT NULL. Haga clic con el botón derecho del ratón sobre la tabla y seleccione la opción Copy SQL to Clipboard. director VARCHAR(128) NOT NULL DEFAULT ''.17.Figura 5. imdb_director VARCHAR(32) NOT NULL DEFAULT ''. actor VARCHAR(128) NOT NULL DEFAULT ''. genero_desc VARCHAR(32) NOT NULL DEFAULT ''. genero VARCHAR(2) NOT NULL DEFAULT ''. imdb_actor VARCHAR(32) NOT NULL DEFAULT ''. también puede obtener las instrucciones necesarias para crear la que acaba de diseñar. seleccione la opción Save del menú File o haga clic en el botón Save Model to File de la barra de herramientas para guardar el modelo que acaba de crear en la ubicación que desee. Si luego pega el resultado usando Control-V en su editor de texto favorito verá un resultado similar al siguiente: CREATE TABLE pelicula ( id INT NOT NULL AUTO_INCREMENT. soporte VARCHAR(3) NOT NULL DEFAULT ''. PRIMARY KEY (id) ) ENGINE = InnoDB. Además de tener una representación visual de sus tablas.

) y. genero_desc ) VALUES( 'Gladiator'. genero_desc ) VALUES( 'Blade Runner'. 'Russell Crowe'. 'Ridley Scott'. Cree ahora la tabla de películas (no se olvide de seleccionar antes en qué base de datos con USE videoteca. 'nm0000631'. 'DVD'. a continuación. Es posible que ya exista si la creó en el segundo capítulo. 'Ciencia-ficción' ). soporte. imdb_actor. CREATE DATABASE videoteca. 'nm0000148'. director. 'Ridley Scott'. 'nm0000128'. 'Harrison Ford'.videoteca. 'Aventuras' ). soporte. INSERT INTO pelicula( titulo. genero. Las siguientes instrucciones eliminarán esta base de datos si ya existiese y la volverán a crear: DROP DATABASE IF EXISTS videoteca. actor. imdb_actor. 'A'. 'DVD'. . imdb_director. 'nm0000631'. inserte algunos datos en la tabla: USE videoteca. imdb_director. genero. INSERT INTO pelicula( titulo. actor. 'CF'. director.

Fíjese en el uso de \G al final de la operación de consulta. 'VHS'. ocupando más espacio.18. si ese actor ya participó en alguna de las películas que tiene en la base de datos. 'nm0001566'. ¿cómo se encuentra la base de datos? Busquemos todas las deficiencias de diseño que podamos: Cada vez que introduzca el nombre de un actor. El resultado de hacer una consulta de selección tras estas inserciones puede verse en la figura 5. director. genero_desc ) VALUES( 'A propósito de Henry'. imdb_director. Figura 5. 'D'. estará duplicando los datos.18. 'Drama' ). Los datos de partida Con este diseño y estos datos de partida. 'Mike Nichols'. imdb_actor. 'nm0000148'. genero. es posible que cometa algún error al introducir el nombre de algún actor. Podría escribir Harrisond Ford como protagonista de . actor. Con relación al punto anterior. 'Harrison Ford'.INSERT INTO pelicula( titulo. soporte.

19. Si posteriormente hiciese una consulta de las películas protagonizadas por este actor. Figura 5.20. podría dividirlo en dos partes: nombre y apellidos.19 muestra el aspecto de dicha tabla. La figura 5. de los actores. creada con MySQL Workbench. Esto le da la oportunidad de ordenar también por los apellidos. haciendo bueno el dicho "divide y vencerás". siempre que esta división sea útil. Sólo puede indicarse un director por película. Algunas. fueron dirigidas por dos personas. a la vez que se evitan errores en la introducción del nombre. Por sí misma. lo que antes era un único campo (Ridley Scott. Lo mismo se puede decir. la creación de una tabla para la gestión de los directores de películas podría tener sentido. De esta forma. Los datos de los directores ¡Fantástico! Ya tiene una tabla para los directores que. Cree una nueva tabla en la que almacenar los detalles de cada uno de ellos.20 muestra este otro diseño de la tabla de directores. Está claro que la base de datos es manifiestamente mejorable y muchas de estas mejoras se lograrían dividiendo la tabla en fragmentos más pequeños y más manejables. ¿Qué más se puede dividir en esta tabla? El nombre del director. la de Indiana Jones no aparecería. Esta misma fuente de errores se repite con el género de la película y su descripción. Los datos han de dividirse todo lo posible. Pero aún hay algo que falla en esta tabla. División de tablas Vamos a comenzar con los directores. que sólo permitía ordenación por el nombre. por ejemplo). puede llevar a cabo correspondencias con cada película. por ejemplo. Figura 5. y con los códigos de IMDb. por el error en el nombre. ahora se convierte en dos. no hemos continuado con esa división en las tablas obtenidas. Otro diseño de la tabla de directores . con más razón. Aunque hemos comenzado con la división de la tabla principal. utilizando claves externas como las que vio en el apartado dedicado a las bases de datos relacionales.una de las películas de Indiana Jones. La figura 5. como "Delicatessen".

Modificación de la tabla de películas Sólo ha sido necesario sustituir los campos director y .El código necesario para crear esta tabla es el siguiente: USE videoteca. Los datos de los actores. Figura 5. Relacionar tablas El diseño de la tabla de películas ha de cambiarse para reflejar los cambios realizados en la sección anterior.22. para seguir guardando los mismos datos que antes. Fíjese en que la única columna con un valor predeterminado es la que almacena el código de IMDb: puede que no lo conozca para todos los directores. CREATE TABLE director ( id INT NOT NULL AUTO_INCREMENT. por separado El código para crear esta tabla es el siguiente: USE videoteca.22. PRIMARY KEY(id) ) ENGINE = InnoDB. Ha de incluir una referencia al director de la película. El mismo razonamiento que se ha seguido para crear esta tabla de directores puede aplicarse para aquella en la que se guardan los datos de los actores. La figura 5. nombre VARCHAR(64) NOT NULL. apellidos VARCHAR(64) NOT NULL. Figura 5. apellidos VARCHAR(64) NOT NULL. y otra al actor. imdb VARCHAR(32) NOT NULL DEFAULT ''. imdb VARCHAR(32) NOT NULL DEFAULT ''. Este cambio se muestra en la figura 5. es necesario introducir el resto de valores en cada inserción.21 muestra el diseño de dicha tabla.21. PRIMARY KEY(id) ) ENGINE = InnoDB. nombre VARCHAR(64) NOT NULL. Por el contrario. CREATE TABLE actor ( id INT NOT NULL AUTO_INCREMENT.

en este modelo. llamémosla dirigida_por . se encuentra en la parte inferior de la ventana de MySQL Workbench. Primer paso de la creación de relaciones El modelo de datos que tiene ahora permite mantener una lista de directores. El aspecto del modelo en ese momento será similar al que puede verse en la figura 5. Como se trata de saber quién ha dirigido cada película. Por otra parte.23. 6. En este caso hemos de seleccionar la tabla director . La relación entre directores y películas es lo que se definió anteriormente como una relación uno a muchos. Marque la casilla de verificación del campo iddirector . Repita la operación con la tabla de actores. Este . una película sólo la dirige un director. Introduzca el nombre de la tabla con la que quiere relacionar la actual en la primera fila de la columna Referenced Table . 5. Introduzca el nombre que quiera dar a la relación en la primera fila de la columna Foreign Key Name. Para terminar tenemos que relacionar las tres tablas existentes entre sí: actor . que guardaban sus nombres. pero un director puede haber dirigido muchas películas. La columna iddirector debe estar relacionada con la columna id de la tabla director . por los identificadores correspondientes de las tablas que acaba de crear. la columna idactor debe estar relacionada con la columna id de la tabla actor . director y pelicula. Figura 5. 4. 7. Una lista desplegable le permitirá seleccionar entre las tablas existentes. y eliminar los datos de IMDb que se guardaban. que toma datos de las dos primeras. Siga estos pasos para crear relaciones utilizando MySQL Workbench: 1.23. otra de actores y una última de películas. Seleccione el campo id. Haga clic sobre la tabla pelicula para seleccionarla.actor. Active la ficha Foreign Keys. ya que ahora estarán en las tablas correspondientes. Traduciendo: por ahora. 3. 2. Cuando lo haga se desplegará una lista con los campos de la tabla de directores. Justo a la derecha del panel con el que hemos estado trabajando podrá ver la lista de los campos de la tabla pelicula.

Hay que lograr convertirla en una relación muchos a muchos.24. y la incorporación de los campos idsoporte e idgenero a la tabla pelicula. algo que este no permite en este momento. directores y actores Aún se puede añadir una mejora más al modelo. formatos y géneros. pero que en el futuro puede contener los valores de los formatos que vaya añadiendo a su videoteca.proceso de simplificación. idactor3? ¿Y si luego quisiésemos añadir un cuarto actor? Relaciones muchos a muchos La forma más eficaz de lograr este objetivo es cambiar el tipo de relación que existe entre la tabla de actores y la de películas. es necesario utilizar una tabla intermedia. La tabla de películas tendrá una relación de uno a muchos con la tabla de actores por película. dividiendo el modelo. Figura 5. soporte y genero. El soporte en el que está grabada la película puede ser otra tabla que. por ahora. de nuevo. idactor2. permitiendo que una película pueda estar protagonizada por más de un actor. Para ello.24 puede ver el aspecto del modelo resultante tras la nueva división de los datos. Ahora mismo es una relación uno a muchos. sólo contendrá los valores DVD y VHS. puede seguir aplicándose a la tabla de películas. Películas. Puede ver cómo quedará esta . Los géneros también podrían llevarse a otra tabla. La opción más sencilla sería incluir otro identificador de actor más. al igual que la tabla de actores. En la figura 5. El identificador del actor dejará de estar en la tabla de películas y pasará a esta nueva tabla. como ha visto. Pero entonces ¿qué ocurre si se quiere guardar información sobre tres actores? ¿Creamos un tercer campo. los identificadores necesarios a la tabla de películas para mantener las relaciones entre películas. De esta manera. que almacenará las relaciones entre películas y actores. tras eliminar los campos correspondientes de las nuevas tablas. Debería añadir. que ocasiona la aparición de dos nuevas tablas. el resultado final es que la tabla de películas tendrá una relación de muchos a muchos con la de actores.

25. y por último. "Blade Runner" requeriría una inserción en la tabla de actores para disponer de Harrison Ford. DROP TABLE IF EXISTS actores_por_pelicula. apellidos VARCHAR(64) NOT NULL. FOREIGN KEY(idactor) REFERENCES actor(id) ) ENGINE = InnoDB. CREATE TABLE actores_por_pelicula ( idpelicula INT NOT NULL. DROP TABLE IF EXISTS actor. Se ha simplificado la tabla de películas para que sólo incluya los campos interesantes para este apartado. una inserción . para guardar en la base de datos los detalles de una película. Sería necesaria otra inserción en la tabla de películas para crear la película. INDEX actores_por_pelicula_fk1( idpelicula ).25.25 sería necesario ejecutar las siguientes instrucciones: USE videoteca. imdb VARCHAR(32) NOT NULL DEFAULT ''. Figura 5. INDEX actores_por_pelicula_fk2( idactor ). Por ejemplo. DROP TABLE IF EXISTS pelicula. PRIMARY KEY(idpelicula. Tenga en cuenta que ahora. nombre VARCHAR(64) NOT NULL. CREATE TABLE actor ( id INT NOT NULL AUTO_INCREMENT. CREATE TABLE pelicula ( id INT NOT NULL AUTO_INCREMENT.parte del modelo de la base de datos en la figura 5. Una relación muchos a muchos Por ejemplo. PRIMARY KEY(id) ) ENGINE = InnoDB. para crear las tablas que se pueden ver en la figura 5. titulo VARCHAR(64) NOT NULL. es necesario realizar más inserciones. idactor). FOREIGN KEY(idpelicula) REFERENCES pelicula(id). PRIMARY KEY(id) ) ENGINE = InnoDB. idactor INT NOT NULL.

'Hauer'. INSERT INTO actores_por_pelicula( idpelicula. INSERT INTO actor(nombre. 'nm0000148'). 'Ford'. SELECT id FROM actor WHERE imdb = 'nm0000442'. En las operaciones de inserción anteriores se ha supuesto que el identificador del actor es 10 y el de la película es 15. Not a: Es posible combinar los procedimientos almacenados y los desencadenadores para hacer más sencillo el trabajo de inserción de películas en la base de datos. apellidos. imdb) VALUES('Rutger'. SELECT id FROM actor WHERE imdb = 'nm0000148'.en la tabla de actores por película para crear la asociación entre ambos. SELECT id FROM pelicula WHERE titulo = 'Blade Runner'. Encontrará más información al respecto en los capítulos correspondientes. Esta última inserción requiere que conozca los identificadores tanto del actor como de la película. . 'nm0000442'). Este modelo le permitiría incluir un segundo actor relacionado con la película de la siguiente forma: USE videoteca. INSERT INTO pelicula(titulo) VALUES('Blade Runner'). imdb) VALUES('Harrison'. que pueden obtenerse mediante una consulta: USE videoteca. INSERT INTO actor(nombre. idactor ) VALUES( 15. 10 ). apellidos.

27 muestra el mismo diagrama que la 5. ¡El diseño. El ejemplo finalizado Si extiende la modificación en el diseño a la tabla de directores podrá tener varios directores para una película. 11 ).27.INSERT INTO actores_por_pelicula( idpelicula. Not a: En el siguiente capítulo. pero tras utilizar dicho triángulo para simplificar el aspecto del diagrama. La figura 5. idactor ) VALUES( 15. MySQL Workbench ocultará los campos de las tablas. dedicado a las consultas de datos.26. Simplificación del diagrama .26 muestra el diseño final de la base de datos tras incorporar este cambio. por fin! Existe un truquito de MySQL Workbench que permite trabajar con diseños grandes en poco espacio.26. podrá ver cómo recuperar la información de los actores que han trabajado en una determinada película. Figura 5. La figura 5. así como otras consultas más complejas. mostrando sólo sus nombres. ¿Se ha fijado en el triángulo que aparece a la derecha del nombre de cada tabla? Si hace clic en él. Figura 5.

añadir más campos a la tabla principal para guardar la fecha de la película. por ejemplo. así como la posibilidad de que una película pertenezca a más de un género y esté en más de un soporte. Una nota final: queda como ejercicio mejorar el diseño de la tabla dedicada a almacenar los préstamos de las películas. O. una calificación sobre la misma o los comentarios que desee.Durante este capítulo se ha terminado de diseñar la base de datos con la que trabajaremos en los capítulos sucesivos. .

que debe tener lugar al principio del proceso de desarrollo. exploraremos las diferentes variantes de consultas de selección que pueden ser útiles para el trabajo diario y continuaremos con las actualizaciones y las inserciones. borrados o simples solicitudes de información. ya sean inserciones. Mientras la base de datos se encuentre en funcionamiento estas cuatro operaciones serán fundamentales. La base de datos de ejemplo Quizá sería interesante ofrecerle una lista de ventajas y desventajas comparando. pero no va a ser el caso. Comenzaremos creando desde cero la base de datos que diseñamos en el capítulo anterior. Tras repasar las consultas para la creación y el mantenimiento de bases de datos. y un servidor de explotación. Estos valores se utilizarán durante el resto del capítulo. Le recomendamos que. que facilitan mucho las inserciones puntuales. Sin embargo. veremos los borrados. El lenguaje estructurado de consultas. el uso de las herramientas visuales como MySQL Administrator y MySQL Query Browser para crear bases de datos y tablas y. o SQL.6 SQL Las primeras veces que se encargue de él. La práctica logrará que se convierta en una tarea más. lo que permitirá ilustrar algunas de las ventajas de este método de trabajo. en el que podrá hacer todas las pruebas necesarias. el diseño de la base de datos le acarreará dolores de cabeza. siempre que sea posible. Por último. por varios motivos. en el que la aplicación funcionará una vez se haya probado convenientemente. utilice archivos de instrucciones para este tipo de tareas. Continuaremos insertando valores en las tablas de la base de datos. el uso de archivos de instrucciones (también conocidos como scripts). Existe una tarea que le ocupará bastante más tiempo que el diseño: las consultas a la base de datos. actualizaciones. Existen herramientas visuales para llevar a cabo las tareas de mantenimiento de las bases de datos. El primero de ellos es que en la mayoría de trabajos a los que se enfrentará con MySQL contará con un servidor de desarrollo. por un lado. precisamente utilizando instrucciones SQL. . por otro. le permite comunicarse con el sistema gestor de bases de datos para realizar todas esas operaciones. la utilización de SQL proporciona muchas ventajas de las que hablaremos a lo largo de este capítulo.

CREATE DATABASE videoteca. Creación de la base de datos En los archivos de ejemplo de este libro. dadas unas instrucciones muy sencillas. una vez creados los archivos de instrucciones necesarios. Más aún. introduciría un punto de fallo. si existe la posibilidad de automatizarla mediante el empleo de archivos de órdenes. El contenido de ese archivo es el siguiente: DROP DATABASE IF EXISTS videoteca. DROP TABLE IF EXISTS director. Una vez disponga de las instrucciones de creación de la base de datos y de sus tablas. nombre VARCHAR(64) NOT NULL. DROP TABLE IF EXISTS genero. Este archivo contiene todas las instrucciones SQL necesarias para crear tanto la base de datos como las tablas de la videoteca que con tanto esfuerzo ha desarrollado durante los capítulos previos. Sin embargo. cualquiera puede crear la bases de datos. si tuviese que utilizar las herramientas visuales que ha visto hasta ahora cada vez que fuese necesario crear la base de datos y sus tablas.sql. Aunque le cueste más esfuerzo al principio. CREATE TABLE genero ( id INT NOT NULL AUTO_INCREMENT. podrá encontrar un archivo llamado 01 . dentro del apartado dedicado a este capítulo. ahorrará un valioso tiempo en el futuro. Consejo: Le recomendamos encarecidamente que. en cualquier operación que tenga que realizar con MySQL. Podría cometer algún error al repetir las operaciones una y otra vez. nombre VARCHAR(2) NOT NULL. CREATE TABLE director ( id INT NOT NULL AUTO_INCREMENT.Crear la base de datos. PRIMARY KEY(id) ) ENGINE = InnoDB. . puede repetir la operación de forma exacta e idéntica todas las veces que lo necesite. imdb VARCHAR(32) NOT NULL DEFAULT ''. USE videoteca.En este tipo de entornos es mucho más eficaz la utilización de los archivos de instrucciones obtenidos a partir de herramientas de diseño de bases de datos como MySQL Workbench. PRIMARY KEY(id) ) ENGINE = InnoDB. lo haga. apellidos VARCHAR(64) NOT NULL. descripcion VARCHAR(32) NOT NULL. sin necesidad de tener el más mínimo conocimiento acerca del diseño de la misma.

INDEX p_FK1(idsoporte). iddirector). FOREIGN KEY(idpelicula) REFERENCES pelicula(id). CREATE TABLE actores_por_pelicula ( idpelicula INT NOT NULL. PRIMARY KEY(idpelicula. idactor). DROP TABLE IF EXISTS directores_por_pelicula. CREATE TABLE pelicula ( id INT NOT NULL AUTO_INCREMENT. idsoporte INT NOT NULL. INDEX p_FK2(idgenero). imdb VARCHAR(32) NOT NULL DEFAULT ''. descripcion VARCHAR(32) NOT NULL. INDEX dpp_FK2(iddirector). FOREIGN KEY(idactor) REFERENCES actor(id) ) ENGINE = InnoDB. DROP TABLE IF EXISTS actores_por_pelicula. idgenero INT NOT NULL. PRIMARY KEY(id) ) ENGINE = InnoDB. PRIMARY KEY(id) ) ENGINE = InnoDB. nombre VARCHAR(64) NOT NULL. INDEX dpp_FK1(idpelicula). CREATE TABLE directores_por_pelicula ( idpelicula INT NOT NULL. CREATE TABLE actor ( id INT NOT NULL AUTO_INCREMENT. DROP TABLE IF EXISTS soporte. nombre VARCHAR(3) NOT NULL. INDEX app_FK1(idpelicula). PRIMARY KEY(idpelicula. FOREIGN KEY(idsoporte) REFERENCES soporte(id). titulo VARCHAR(64) NOT NULL. FOREIGN KEY(idpelicula) . apellidos VARCHAR(64) NOT NULL. DROP TABLE IF EXISTS pelicula. CREATE TABLE soporte ( id INT NOT NULL AUTO_INCREMENT. iddirector INT NOT NULL. idactor INT NOT NULL. PRIMARY KEY(id). FOREIGN KEY(idgenero) REFERENCES genero(id) ) ENGINE = InnoDB. INDEX app_FK2(idactor).DROP TABLE IF EXISTS actor.

1.Crear la base de datos. En primer lugar. Ahora aprenderá una forma nueva de hacerlo. De nuevo vamos a utilizar archivos de instrucciones. Lo más sencillo: guárdelo en la raíz del disco C: si utiliza Windows o su carpeta home si utiliza Linux o Mac OS X. Y puede repetir la operación las veces que sea necesario con la misma facilidad. Puede utilizar un archivo que se encuentra en la misma ubicación que el que utilizó anteriormente para crear la base de datos. Creación de la base de datos Eso es todo. con los mismos elementos. usted y yo.Insertar valores iniciales. abra una consola (o un terminal en el caso de Linux o Mac OS X) y cambie a la ubicación en la que se encuentra el archivo. ya sabe del archivo 01 .sql El cliente de MySQL le pedirá que introduzca la contraseña y. la base de datos y sus correspondientes tablas. Si ha seguido los pasos dados en los capítulos anteriores ya estará familiarizado con el proceso de ejecución de instrucciones utilizando la consola. guarde el archivo en el disco con el nombre crear. le devolverá el control. El aspecto de la consola será similar al que puede verse en la figura 6. FOREIGN KEY(iddirector) REFERENCES director(id) ) ENGINE = InnoDB.sql. Las instrucciones de inserción incluidas en dicho archivo son las siguientes: . De un plumazo. Entonces. tras pensárselo un momento. hablamos de él anteriormente. Inserción de datos Tras la ejecución de las instrucciones de creación de la base de datos estaremos trabajando. En segundo lugar.1. necesita un archivo en el que guardar las instrucciones SQL que acaba de ver. Recuerde que si instaló MySQL a través de XAMPP y no cambió su configuración predeterminada. Ejecútelo siguiendo los mismos pasos que con el de creación de base de datos y tablas. Si no tiene acceso a Internet tendrá que teclear. Su nombre es 02 . creadas. Ahora vamos a llenar las tablas de la base de datos con los registros que utilizaremos durante los siguientes apartados. Si tiene acceso a Internet no es necesario que las escriba usted mismo.sql. ejecute la siguiente orden: mysql -u root -p < crear.sql. el usuario root no tendrá contraseña. Figura 6.FOREIGN KEY(idpelicula) REFERENCES pelicula(id).

idgenero) VALUES('A propósito de Henry'.USE videoteca. INSERT INTO director(nombre. 'Ford'. INSERT INTO actor(nombre. INSERT INTO genero(nombre. 1). apellidos. imdb) VALUES('Russell'. INSERT INTO pelicula(titulo. idsoporte. descripcion) VALUES('VHS'. 'Nichols'. imdb) VALUES('Mike'. INSERT INTO genero(nombre. INSERT INTO pelicula(titulo. INSERT INTO director(nombre. DELETE FROM soporte. 'Digital Versatile Disc'). INSERT INTO actores_por_pelicula( idpelicula. DELETE FROM directores_por_pelicula. DELETE FROM director. idactor . INSERT INTO pelicula(titulo. 'Scott'. 'nm0000128'). imdb) VALUES('Harrison'. descripcion) VALUES('DVD'. 'Drama'). DELETE FROM actor. INSERT INTO soporte(nombre. 'nm0000631'). DELETE FROM genero. 1). 'nm0001566'). idactor ) VALUES(1. apellidos. descripcion) VALUES('D'. 1. DELETE FROM actores_por_pelicula. imdb) VALUES('Ridley'. idgenero) VALUES('Blade Runner'. 3). INSERT INTO actores_por_pelicula( idpelicula. idsoporte. 2). INSERT INTO soporte(nombre. descripcion) VALUES('A'. INSERT INTO genero(nombre. 'Crowe'. idsoporte. INSERT INTO actor(nombre. idgenero) VALUES('Gladiator'. 1. descripcion) VALUES('CF'. apellidos. 'Ciencia Ficción'). 'Video Home System'). apellidos. 2. 'nm0000148'). 'Aventuras'). DELETE FROM pelicula.

no tendrá que insertar un nuevo registro en esta tabla. iddirector ) VALUES(1. 'Digital Versatile Disc'). descripcion) VALUES('CF'. 2). posteriormente. INSERT INTO soporte(nombre. INSERT INTO directores_por_pelicula( idpelicula. puesto que ya tendrá almacenado el valor necesario. 1). "Blade-Runner" es de ciencia ficción. Por una parte. Con valores en esas dos tablas sí es posible realizar inserciones en la de películas. porque han de cumplirse las reglas de integridad referencial. INSERT INTO actores_por_pelicula( idpelicula.) VALUES(2. Si. Inserte el soporte en que se encuentra la película. 2). y también géneros en la tabla de géneros cinematográficos. USE videoteca. . son los siguientes: 1. Pero hasta que tenga registros en las tablas de directores y actores no podrá asociar valor alguno a la tabla de películas a través de las tablas intermedias. INSERT INTO directores_por_pelicula( idpelicula. Ahora necesita un registro en la tabla de géneros cinematográficos que se ajuste al de esta película. descripcion) VALUES('DVD'. idactor ) VALUES(3. 'Ciencia Ficción'). 1). La principal diferencia consiste en que hasta que no tenga valores en las tablas de las que depende la tabla pelicula no podrá realizar inserciones en ella. 2. 1). iddirector ) VALUES(2. INSERT INTO directores_por_pelicula( idpelicula. ha de tener soportes válidos en la tabla de soportes de grabación. iddirector ) VALUES(3. INSERT INTO genero(nombre. Los pasos necesarios para insertar la película "Blade Runner" en la base de datos. como si fuese la primera que se inserta. inserta otras películas que estén grabadas en el mismo formato.

INSERT INTO actor(nombre. asocie a la película su actor. 4. Si examina el código del archivo 02 . apellidos. idgenero ) VALUES('Blade Runner'. apellidos. Igualmente. La primera inserción de un valor en una columna de ese tipo toma el valor 1. Not a: Este proceso.Insertar valores iniciales. Como la base de datos está recién creada. aunque también una desventaja: la inserción de una película requiere de comprobaciones e inserciones adicionales por su parte. 'Ford'. idsoporte. iddirector ) VALUES(1. imdb) VALUES('Harrison'.3. 1. Como verá en capítulos sucesivos. Recuerde que los identificadores de cada uno de los registros insertados hasta ahora son de incremento automático. asocie el director a la película. INSERT INTO actores_por_pelicula( idpelicula. Las inserciones del resto de películas se han realizado siguiendo estos mismos pasos. 'nm0000148'). Llegado a este punto tiene toda la información necesaria para insertar la película en la base de datos. la segunda el valor 2 y así sucesivamente. a continuación los actores y por último los directores. puede insertar la película utilizando 1 como referencia al formato de grabación y 1 como referencia al género cinematográfico. luego todos los géneros. Siguiendo el mismo razonamiento. aunque también podría insertar en este momento la película. 'nm0000631'). Tras ello se insertan todos los soportes en los que están las películas que tenemos. imdb) VALUES('Ridley'. El último paso previo a la inserción de la película será la inserción de su director en la tabla de directores. cada uno de los elementos que insertados tiene el identificador 1 en su tabla correspondiente. esto no supone ningún problema: . Por lo tanto. idactor ) VALUES(1. tiene múltiples ventajas. 1).sql podrá comprobar que en primer lugar se borran todos los registros de todas las tablas de la base de datos. 5. 7. Adelántese e inserte ya el actor de la película. INSERT INTO director(nombre. INSERT INTO pelicula( titulo. 1). INSERT INTO directores_por_pelicula( idpelicula. mucho más complejo que el utilizado en el diseño original de una sola tabla. 'Scott'. 1). 8. Y es en ese momento en el que se insertan las películas y se asocian con actores y directores.

con los mismos registros ordenados de la misma forma. 'Zemekis'. imdb) VALUES('Rutger'. imdb) VALUES('Douglas'. 'Trumbull'. imdb) VALUES('Bruce'. descripcion) VALUES('LD'. INSERT INTO actor(nombre. imdb) VALUES('Lee'. INSERT INTO actor(nombre. ' Hauer'. INSERT INTO director(nombre. INSERT INTO actor(nombre. idgenero) . 'Comedia'). apellidos. 'nm0000707'). 'Laser Disc'). 'nm0781029'). apellidos. apellidos. imdb) VALUES('Jean'. apellidos. Se llama 03 . comienza el trabajo. con los mismos identificadores. apellidos. 'Dern'. INSERT INTO actor(nombre. 'nm0874320'). 'nm0001136'). 'Seberg'. 'Eastwood'. apellidos. 'McConaughey'. que la utilizada en este libro. INSERT INTO actor(nombre. descripcion) VALUES('C'. 'Young'. 'Boxleitner'. Su contenido es el siguiente: USE videoteca. 'nm0001511'). apellidos. imdb) VALUES('Sean'. imdb) VALUES('Clint'. 'Marvin'. INSERT INTO soporte(nombre. INSERT INTO actor(nombre. 'nm0000310').sql. INSERT INTO genero(nombre. 'nm0000442'). INSERT INTO pelicula(titulo. apellidos. Existe un tercer archivo en el apartado de ejemplos de este capítulo que le será de utilidad. imdb) VALUES('Robert'. 'nm0000142'). Lo usará en el resto del capítulo. imdb) VALUES('Bruce'. idsoporte.Resto de inserciones. Ahora que dispone de la misma base de datos. apellidos.existen formas de simplificar las inserciones para que no tenga que escribir una sola línea de SQL una vez haya comprobado que la base de datos funciona correctamente. imdb) VALUES('Matthew'. apellidos. 'nm0000709'). INSERT INTO actor(nombre. 'nm0000190'). INSERT INTO director(nombre. Ejecute las instrucciones de ese archivo para introducir muchos más valores en la bases de datos de películas. INSERT INTO actor(nombre.

. Si la tabla de películas almacenase el año en el que se estrenaron. Igual que se pueden realizar estas operaciones entre dos valores numéricos en una consulta de selección.VALUES('Naves misteriosas'. La consulta podría ser ésta: USE videoteca. Puede utilizar una consulta de selección de SQL para comprobar el funcionamiento de estos operadores.2. el resultado varía dependiendo del operador que tenga entre los valores. * y /. 1). -. respectivamente. algo que puede ser de mucha utilidad. así funcionan todos los operadores aritméticos: un valor. dígame. resta. Dos más dos son cuatro.2. en el ejemplo dedicado a las transacciones. ¿cuántas son dos más dos? Figura 6. claro. Y mirando a la figura 6. Escriba la siguiente: SELECT 2 + 2. sumaba y restaba cantidades a los saldos de dos personas para realizar una transferencia de capital. 1. no hará falta base de datos alguna. Operadores Desde que aprendió a sumar utiliza operadores: el símbolo de la suma (+) es un operador. Y de los valores. Obviamente. las operaciones de suma. Operadores aritméticos En las cuentas sobre papel. Ya ha utilizado operadores en SQL con anterioridad. se pueden realizar entre un valor numérico y el valor de una columna de un determinado registro. ¿verdad? En líneas generales. Durante los siguientes apartados aprenderá a manejar algunos de los operadores que MySQL proporciona. un operador y otro valor dan como resultado un tercer valor. MySQL permite utilizar esos operadores dentro de las consultas. Con SQL no es diferente. podría saber cuántos años hace que se estrenó una determinada película con sólo restar al año actual el año de estreno. como lo son el de la resta y el de la multiplicación. multiplicación y división se representan utilizando los operadores aritméticos +. Si recuerda. señor maestro Ésta no era difícil.

aunque esto lo va a ver con otro ejemplo. CREATE TABLE operadores( uno TINYINT UNSIGNED. realizando la operación sobre todos y cada uno de ellos. otro TINYINT UNSIGNED ). ¿Qué ocurre en estos casos.SELECT YEAR(CURDATE()) . DROP TABLE IF EXISTS operadores. CREATE DATABASE pruebas. SELECT YEAR(CURDATE()) .estreno FROM pelicula WHERE id = 12. La consulta anterior se realiza sobre un determinado valor de un registro pero. Si tiene algunas nociones de programación. La sencillez del lenguaje SQL es aparente: lo que parece una sola operación aritmética puede tener implícitas miles de ellas si la consulta devuelve miles de registros. Vuelva a utilizar la base de datos de pruebas. inserte un registro: . Donde 12 es el identificador de la película en cuestión y YEAR(CURDATE()) devuelve el año actual. Sin embargo. con una sola instrucción en SQL obtendrá los mismos resultados. la siguiente instrucción calcula el tiempo pasado desde el estreno de todas las películas de la base de datos: USE videoteca. como ya sabrá a estas alturas. Cree una tabla con dos columnas con las siguientes instrucciones: USE pruebas. Y esta sencillez también es aparente en otro aspecto. Ahora. Ya vio cómo crearla: DROP DATABASE IF EXISTS pruebas. Siguiendo con el ejemplo anterior. sabrá que para sumar un determinado valor a todos los elementos de una lista es necesario utilizar un bucle que recorra todos los elementos de dicha lista. las consultas de selección pueden devolver más de un valor. cómo se comporta MySQL cuando se le pide que realice una operación aritmética sobre una determinada columna de una tabla? La respuesta es muy sencilla: la operación se realiza sobre todos los valores devueltos por la consulta.estreno FROM pelicula.

7). cuyo resultado estuviese por encima del máximo permitido por esa operación. FALSE (falso) o NULL . resultado de la suma de las columnas de los primeros valores insertados. que ha intentado almacenar en una columna un valor mayor que el que cabe en ella. tome el mayor número entero que se puede almacenar en MySQL y multiplíquelo por 2: SELECT 18446744073709551615 * 2. La razón. Fíjese en que el resultado cambia si en lugar de multiplicar por 2 (entero) lo hace por 2. Pues hay una sorpresa. Se trata de algo similar a lo que pasaría si intentase multiplicar dos valores enteros muy grandes.0 (coma flotante): SELECT 18446744073709551615 * 2. El resultado: ese mismo número menos uno. valores superiores al máximo que puede almacenar una columna de este tipo (recuerde. de nuevo. El resultado de sumar los valores almacenados en las dos columnas de esta tabla se consigue así: USE pruebas. El resultado de la comparación será NULL si uno de los valores comparados es NULL . Fuera de rango Y es que se ha salido de rango: ha insertado en una columna.0. 500). el valor máximo es 255). INSERT INTO operadores VALUES(300. mire en la figura 6. . Pero. el resultado es 10.USE pruebas. Obviamente. ¿cuál será el resultado de esta misma consulta cuando inserte esta nueva pareja de valores? USE pruebas. que es de tipo TINYINT sin signo. SELECT uno + otro FROM operadores. El resultado de dicha comparación puede ser TRUE (verdadero). Por ejemplo. INSERT INTO operadores VALUES(3.3 cuál ha sido el resultado real. Uno diría que se obtendrán dos registros. el primero con el valor 10. Figura 6. Operadores de comparación Estos operadores permiten comparar dos valores. y el segundo con el valor 800.3.

Éstos son los operadores más utilizados cuando se comienza a trabajar con MySQL. NULL = NULL.5. Por ejemplo. Figura 6. El resultado de esta consulta sí es cierto en ambos casos. Cualquiera diría que el resultado de esta consulta debería ser TRUE (cierto) en ambos casos. Bueno. Vea: SELECT 7 <=> 7. MySQL proporciona operadores para comprobar si dos valores son iguales (=) o diferentes (<>).Not a: MySQL utiliza un cero como FALSE y un uno como TRUE. ahora NULL sí es igual a NULL Las comparaciones se pueden hacer entre cualquier tipo de valores. para localizar en la base de datos de actores todos aquellos cuyo apellido . Téngalo presente al obtener los resultados de las consultas. si uno es mayor (>) o menor (<) que otro. como puede verse en la figura 6. Por ejemplo. NULL <=> NULL. La realidad que muestra la figura 6. Fíjese en los quebraderos de cabeza que puede dar NULL . Figura 6. Las constantes TRUE. cadenas de texto. que hasta existe un operador de igualdad "a prueba de NULL": es el <=>.4. t rue. NULL no es igual a NULL De ahí la existencia del operador "a prueba de NULL". ya que los otros son un tanto esotéricos y no es hasta después de mucho trabajar con bases de datos cuando se encuentra su utilidad.4 es otra: mientras que 7 sí es igual a 7. por ejemplo. El comparador de igualdad se puede utilizar para localizar aquellas cadenas iguales a una dada. Tanto es así. y las variantes mayor o igual (>=) y menor o igual (<=). o si está dentro de un rango. cualquier comparación de un valor con NULL tendrá como resultado NULL . FALSE y false están a su disposición. Pruebe el operador de igualdad comparando dos parejas de valores: SELECT 7 = 7. existen operadores para comprobar si un determinado valor pertenece a un conjunto de valores.5.

El resultado: todos los actores con ese apellido. pero ahora quiere que la consulta devuelva todos los actores con Crow como comienzo de su apellido. SELECT * FROM actor WHERE apellidos LIKE 'Crow_'. se ha utilizado el carácter del tanto por ciento a continuación de la cadena de comparación. Ese carácter concordará con cuantos caracteres aparezcan tras Crow en los apellidos de la tabla de actores. para esos casos existe un operador especial para cadenas. aunque el apellido concuerde exactamente. claro. en . es que su apellido es Crowe. utilizando algunos caracteres especiales. por ejemplo: USE videoteca. Bueno. Esta consulta sólo devuelve aquellos registros cuyo apellido sea Crow más un carácter al final. Operadores lógicos Están basados en las premisas de la lógica booleana. LIKE . SELECT * FROM actor WHERE apellidos LIKE 'Crow%'. Antes buscaba todos los actores cuyo apellido fuese Crow.. Ambos caracteres (% y _) se conocen como comodines.. por ejemplo Russell. no Crow. se obtendrá un resultado. El operador LIKE permite realizar comparaciones con cadenas parciales. puede utilizar el carácter del guión bajo para buscar concordancias con un solo carácter. Si lo desea. Como ve.fuese Crow. Resulta que está buscando un determinado actor con ese apellido. Podría utilizar esta consulta: USE videoteca. pero no recuerda su nombre. Utilice la siguiente consulta: USE videoteca. SELECT * FROM actor WHERE apellidos = 'Crow'. el famoso protagonista de "Gladiador". ¿que no? Ah.

con sólo utilizar paréntesis. OR y XOR. en la figura 6. AND. MySQL no realiza las operaciones según las va encontrando: existe una prioridad. Uso de paréntesis . Figura 6. Figura 6. aunque no es evidente si el resultado de 2 + 2 * 5 será 12 o 20. Puede comprobar que el resultado es 12. Puede comprobarlo ejecutando la siguiente consulta: SELECT 2 + 2 * 5. Las pruebas con NOT deben hacerse de forma distinta. Por ejemplo. Es sencillo saber el resultado de la operación 2 + 2. ya sabe que no siempre se obtiene el resultado esperado. (2 + 2) * 5. Aquellas operaciones rodeadas por paréntesis se realizan antes. ya que se trata del operador de negación y actúa sobre un único valor.7.7 puede ver el resultado. no se olvide de hacer estas mismas pruebas con el valor NULL . ¿Cómo funciona AND? Ah.6 se está investigando el funcionamiento del operador AND. Sin embargo. Cambiando la precedencia Se entiende por precedencia el orden en el que MySQL efectúa las operaciones de una determinada consulta. Dependerá de si MySQL efectúa antes la suma o la multiplicación. Nada hay nada más sencillo que saber cómo funcionan estos operadores.6. es posible modificar esa prioridad siempre que lo desee. Las multiplicaciones o divisiones se evalúan antes que las sumas o las restas.la que las operaciones básicas son NOT . por ejemplo. Y precisamente éstos son los nombres de los operadores. En la figura 6. Esto permite modificar la operación anterior para que la suma se realice antes que la multiplicación: (2 + 2) * 5 sí dará como resultado 20.

pero no hemos visto la sintaxis exacta de la instrucción de creación de bases de datos. En ese caso. una instrucción SELECT debe seguir la siguiente sintaxis: SELECT lista de columnas [FROM lista de tablas] [WHERE lista de condiciones] . veremos las consultas más frecuentemente utilizadas. Creación Las sintaxis de la sentencia de creación de base de datos es muy sencilla: CREATE DATABASE [IF NOT EXISTS] nombre.Manipulación de bases de datos Durante los capítulos anteriores (incluso en éste) hemos creado y eliminado bases de datos. Simplificando. MySQL sólo ejecutará el borrado en caso de que la base de datos exista. Tanto la base de datos como la carpeta y los archivos que conforman la ubicación en disco de la misma serán eliminados. Advert encia: Tenga mucha precaución antes de ejecutar una instrucción de borrado de una base de datos. Si intenta crear una base de datos cuyo nombre ya esté asignado a otra base de datos. Borrado Tan sencilla como la creación. El resultado: si existe una base de datos con ese nombre. aunque puede evitar el mensaje si utiliza IF EXISTS. no se continúa con la instrucción de creación de bases de datos actual. incluya IF NOT EXISTS. Si no desea que dicho error se produzca. MySQL avisará de ello. Sin embargo. el borrado de bases de datos sigue la sintaxis: DROP DATABASE [IF EXISTS] nombre. Si la base de datos no existe. Donde nombre es el nombre que quiera darle a la base de datos. se producirá un error del que MySQL avisará. de manera que vamos a simplificar su definición. Consultas de selección La sintaxis de las consultas SELECT o de selección de valores no es tan sencilla como las vistas hasta ahora. las que más útiles le serán durante su trabajo.

Trabajaremos con la base de datos de películas que construimos al empezar el capítulo.8. La razón es la misma que hace opcional la lista de tablas de la que obtener las columnas: es posible que la consulta no necesite tabla alguna. podrá determinar la ordenación del resultado por una o más columnas. Por último. A continuación veremos algunos ejemplos de las consultas que más útiles pueden serle en su quehacer diario.sql que se encuentran en la Web de esta guía. ¿qué actores están dados de alta en la base de datos? Seguro que sabe cómo obtener ese listado: USE videoteca. pueden ser operaciones de algún tipo. Es necesario que haya ejecutado las instrucciones mostradas al principio de este capítulo. El resultado debería ser similar al que se puede ver en la figura 6. puede indicar una serie de condiciones que quiera que cumplan los campos de los registros sobre los que realiza la consulta. una cadena debe parecerse a otra.8. utilizando operadores de comparación: un valor debe ser mayor que otro. las tablas sobre las que se realizará la selección. Figura 6. como vio con los ejemplos de los operadores. La lista de tablas determinará qué columnas podrá mostrar en la primera sección de la consulta. o igual a otro. En tercer lugar.sql y 03 . 02 . SELECT * FROM actor.sql. es decir.Rest o de inserciones.Insert ar valores iniciales. Listados de una tabla En primer lugar. Not a: Para los ejemplos necesitaremos trabajar con la misma base de datos. Estas instrucciones están también en los archivos 01 .[ORDER BY campos por los que ordenar] La lista de columnas que quiera obtener siempre debe estar presente aunque. Listado de actores . etcétera. no es necesario que sean nombres de columnas de tablas.Crear la base de dat os.

' '. Podría indicar qué campos quiere obtener como. ' '. Aunque también puede concatenar nombre y apellidos en un solo campo: USE videoteca. SELECT id. Encabezado de una concatenación Es muy sencillo cambiar este comportamiento. CONCAT(nombre. ahora la columna de la concatenación se llama nombre. CONCAT(nombre. Para asignar un nombre a esa columna ha de indicarlo tras su definición en la instrucción de selección: USE videoteca.9.10 cómo cambia el resultado. SELECT id. por ejemplo. apellidos) AS nombre FROM actor.9.10. apellidos) FROM actor.El asterisco permite seleccionar todos los campos de las tablas afectadas por las consultas. el identificador. el nombre y los apellidos: USE videoteca. apellidos FROM actor. Figura 6. nombre. SELECT id. Cambio del nombre de un resultado Un posible cambio en esta consulta sería obtener el resultado ordenado por apellido: USE videoteca. Figura 6. apellidos) AS nombre FROM actor . Esta última consulta tiene un problema "estético": observe el encabezado de la columna que muestra la concatenación en la figura 6. Puede ver en la figura 6. ' '. CONCAT(nombre. SELECT id.

así la ordenación sería descendente (en lugar de ascendente). indicando a continuación los campos por los que se quiere ordenar el resultado. Podría cambiar el orden de los resultados utilizando DESC después de cada campo. Por ejemplo. SELECT COUNT(*) actores FROM actor. se ha añadido al final de la consulta la cláusula ORDER BY. La siguiente le dirá el número de actores que tiene en la base de datos: USE videoteca. El resultado de esta consulta puede verse en la figura 6. Puede cambiar el nombre de las columnas devueltas: USE videoteca. . Como puede ver.actor ORDER BY apellidos. CONCAT(nombre. Otra consulta que le resultará muy útil es la que permite contar el número de elementos en una determinada tabla. La siguiente consulta ordena el resultado de la consulta por el resultado de la concatenación de nombre y apellidos de los actores: USE videoteca. la función CONCAT es el segundo campo escrito tras SELECT .' '. SELECT COUNT(*) FROM actor.apellidos) AS nombre FROM actor ORDER BY 2. ¿cómo ordenar el resultado usando un campo calculado (como la concatenación)? Es posible si se indica la posición que tiene ese campo en la lista de la selección.11. SELECT id. Pero.

CONCAT(nombre. Para simplificar las consultas se utilizarán seudónimos para los nombres de las tablas. apellidos) AS interprete FROM . actor. Construya una consulta que devuelva la lista de películas. hasta ahora no podemos hacer algo así ya que sólo hemos visto cómo realizar operaciones sobre una sola tabla.. SELECT titulo. El resultado es caótico.12 puede ver un fragmento del modelo relacional de la base de datos. El primer paso es determinar qué tablas están envueltas en la consulta.Figura 6.11. necesita saber qué campos desea obtener. Para realizar consultas de selección sobre más de una tabla es preciso indicarle a MySQL de qué tablas se trata y cómo están relacionadas. como se hizo con los campos de las consultas. Bastará con el título de la película y la concatenación del nombre y los apellidos del actor. con sus actores. ' '. La parte "complicada" viene a partir del FROM . actores_por_pelicula. La primera parte de la consulta podría ser algo así: . Para poder organizar la información de estas tres tablas ha de utilizar de forma diferente la parte del FROM de la consulta.. En primer lugar. SELECT * FROM pelicula. 120 registros resultantes: ha obtenido todas las combinaciones posibles de los registros de las tres tablas envueltas en la selección... De nada serviría hacer una consulta como ésta: USE videoteca. el . Actores y películas Listados de varias tablas Para sacar partido al modelo relacional es necesario poder extraer información a partir de datos repartidos por varias tablas. indicando ahí cómo se relacionan las tablas. Es mejor ir poco a poco. En la figura 6.

idactor = a.id = app. Como ve.dedicado a películas y actores. CONCAT(nombre. FROM pelicula p JOIN actores_por_pelicula app ON p. seleccionados Considere como tabla principal la de películas. la de películas. En el primer caso. En primer lugar aparece la primera tabla. Cuando utiliza esa palabra le está indicando a MySQL que quiere unir la tabla anterior (pelicula en este caso) con la indicada a continuación (actores_por_pelicula).idpelicula JOIN actor a ON app. el identificador de la película debe ser igual al campo idpelicula de la tabla de actores por película. que de otra forma debería incluir los nombres completos de las tablas. Está claro que debemos utilizar los identificadores de actores y películas para enlazar las tablas entre sí. SELECT titulo. ' '. La palabra reservada ON se utiliza para especificar qué campos se utilizarán como enlace entre los resultados. A continuación puede ver la consulta completa: USE videoteca. Figura 6. Actores y películas. apellidos) AS interprete FROM . Truco: Fíjese en que utilizamos los seudónimos de las tablas inmediatamente. Aunque parezca algo enrevesado. Tras ella. De esa manera se simplifica enormemente el código. La parte del FROM de la consulta que intentamos crear es similar a la siguiente: .12. en realidad no lo es.. Por último.. a la que llamaremos p en la consulta. A esta tabla la llamaremos app. la pareja de campos que han de ser iguales..id . La tabla de actores por película une a los actores con las películas guardando parejas de identificadores de películas y actores. no es necesario utilizar AS. A continuación de su nombre se indica su seudónimo.. La siguiente línea comienza con la palabra reservada JOIN . la tabla de actores tendrá el seudónimo a.

apellidos) director FROM pelicula p JOIN actores_por_pelicula app . más tablas en la parte del FROM y más relaciones entre campos. apellidos) AS director . CONCAT(nombre. sin JOIN .pelicula p JOIN actores_por_pelicula app ON p. seleccionados Vamos a incluir en esta consulta el director de la película. ' '.13 muestra el resultado de esta consulta de selección sobre varias tablas. CONCAT(a. La figura 6. Solucionar este error es bien simple: sólo necesitamos indicar también la tabla a la que pertenecen los campos.13..titulo.. usando el seudónimo de la misma como prefijo del nombre de columna. Comencemos viendo los nombres de los campos: . Parece correcto.nombre. Figura 6. Actores y películas.nombre. MySQL no será capaz de determinar a qué tabla pertenece cada campo y le informará de un error. SELECT p. d. Si intenta hacer una consulta de esta forma. Para ello necesitamos incluir más campos en la selección. ' '.idactor = a. ' '. CONCAT(nombre. SELECT titulo..idpelicula JOIN actor a ON app. a. ' '.apellidos) interprete.. Existe un problema en esta selección: los nombres de los campos de la tabla de actores y de directores son los mismos. CONCAT(d.id = app. apellidos) AS interprete. La siguiente es la consulta que buscamos: USE videoteca. separando ambos con un punto. pero no lo es. muy diferente al obtenido con el primer intento.id.

14. '. el número de películas en las que ha participado en la otra: USE videoteca.14. pero si el resultado de la consulta fuesen miles de registros lo tendríamos mucho más complicado. para mostrar información conjunta.idpelicula JOIN director d ON dpp.idactor = a. .nombre.idpelicula) peliculas FROM actor a JOIN actores_por_pelicula app ON a. Una de ellas. Podríamos saberlo de un vistazo. actores y directores Las consultas que involucran datos de muchas tablas se pueden utilizar de varias formas. '. El resultado de esta consulta puede verse en la figura 6.id JOIN directores_por_pelicula dpp ON p. a.id = dpp. la que acabamos de ver. mostrado en la figura 6. sólo de dos. Otra aplicación interesante sería calcular el número de películas en las que aparece un determinado actor. El resultado. SELECT CONCAT(a.id = app. La siguiente consulta devuelve dos columnas: el nombre del actor en una de ellas.idpelicula JOIN actor a ON app.idactor ORDER BY a.ON p. mirando el resultado de la figura 6. Películas. no parece demasiado de fiar. COUNT(app. protagonista de tres películas en nuestra base de datos? Que sepamos. a.14. Figura 6.15.id = app.nombre) actor. ¿El señor Ford.apellidos.id.iddirector = d.apellidos.

id ORDER BY a. a.16 la información que buscaba.nombre. SELECT CONCAT(a. COUNT(app. a.apellidos. le está diciendo a MySQL que quiere que cuente las veces que aparece idpelicula en la tabla actores_por_pelicula. así: USE videoteca.nombre) actor.apellidos. '.idpelicula) peliculas FROM actor a JOIN actores_por_pelicula app ON a.id = app.15.idactor GROUP BY a. En este caso particular. o para una determinada película. quiere ver las películas de cada actor. Todos los actores y sus películas .Figura 6. así que tendría que agrupar por idactor . '. pero esa cuenta puede realizarse de muchas formas: contando todos los registros que aparecen en la tabla. Esto es otra cosa: ahora puede ver en la figura 6. Fíjese. ¿Cuántas películas tiene un actor? Para utilizar de forma conjunta y correcta COUNT y otros valores en la parte de selección de campos de una consulta es necesario indicar cómo agrupar la información. o para un determinado actor. Figura 6.16.

apellidos.. . '.id ORDER BY a..idactor = a. en la tabla de actores hay más de dos registros.nombre) actor.. FROM actores_por_pelicula app LEFT JOIN actor a ON app. a.id = app.17. ¿verdad? Como sabe. aunque no exista correspondencia en la tabla de la derecha. aquí hay algo que no cuadra. Todos los actores y sus películas Suponga que cambia la forma en la que está construida la consulta. ¿y si quiere que aparezcan también los actores sin película en este listado? Podría utilizar esta otra consulta: USE videoteca. pero no aparecen como resultado de esta consulta.Sin embargo. Al usar LEFT JOIN se obtienen todos los registros de la tabla de actores (que está a la izquierda de LEFT JOIN ).nombre. La razón: esos actores sin película no tienen ningún registro en la tabla actores_por_pelicula. El resultado de esta consulta puede verse en la figura 6. a. SELECT CONCAT(a. de manera que la consulta anterior no los incluye en el resultado.idactor GROUP BY a. Figura 6.. COUNT(app.idpelicula) peliculas FROM actor a LEFT JOIN actores_por_pelicula app ON a.17.apellidos.id . Pero. '. el orden de aparición de las tablas: .

en caso contrario. utilice RIGHT JOIN en lugar de LEFT JOIN : . no sólo el identificador. Inserte los registros necesarios para que esa asociación exista. SELECT id FROM actor WHERE nombre = 'Rutger' AND apellidos = 'Hauer'. Algunos de estos actores están dados de alta porque participan en una de las películas. que muestra el resultado de la consulta. ¿verdad? Fíjese en la figura 6. Aquí hay algo raro. Esta consulta le. use LEFT JOIN. Efectivamente. Pero es sencillo volver a obtener el resultado de la figura 6. Su identificador debería ser el 1. Ahora sí. ¿no? ¿No devuelve nada? Pruebe a buscar sólo por el nombre. Ahora. Es el caso de Rutger Hauer y Sean Young. Volverá a obtener lo que vio en la figura 6.. SELECT id FROM pelicula WHERE titulo = 'Blade Runner'. Figura 6. pero aún no se les ha asociado a ella.idactor = a.El resultado variará.. los identificadores de los dos intérpretes: USE videoteca... Truco: La clave es: ¿en qué parte (izquierda o derecha) está la tabla que sí contiene registros que no están en la otra tabla? Si la que sí contiene esos registros está a la izquierda. Primero necesita saber el identificador de la película "Blade Runner": USE videoteca. use RIGHT JOIN.17.. presentes en "Blade Runner". FROM actores_por_pelicula app RIGHT JOIN actor a ON app.16 porque ahora la tabla de la izquierda no contiene más que esos dos actores..18.. pero obtenga todos los campos..18. fíjese en la separación que hay entre .id .

SELECT id FROM actor WHERE nombre = 'Rutger' AND apellidos = ' Hauer'.] SET columna = valor [. El identificador de este actor es el 8. tabla . Se trata de comparaciones entre valores. SELECT id FROM actor WHERE nombre = 'Sean' AND apellidos = 'Young'. ¿verdad? Not a: En breve verá cómo modificar este registro para solucionar el problema. ¿No le parece que hay más separación entre Hauer y la línea correspondiente? Quizá haya un espacio antes del nombre. . Fíjese en cómo se han utilizado condiciones en la parte del WHERE de la consulta en las consultas anteriores.. Actualizaciones Las actualizaciones de datos se rigen por la siguiente sintaxis: UPDATE tabla [. El último que necesita.Rutger y la línea de la izquierda. ¿Y el de Sean Young? USE videoteca. columna2 = valor2 . A continuación veremos cómo se modifican los valores almacenados en una tabla. su identificador es el 9.] [WHERE condiciones] Tras la palabra reservada UPDATE se indican las tablas sobre las que se quiere realizar la operación de actualización de datos. Inténtelo con esta consulta: USE videoteca. Fíjese en que se ha dejado un espacio entre la comilla simple y Hauer.. a continuación los valores que se tienen que asignar a los campos que interesa modificar. Ejecute la consulta.. utilizando los operadores que vimos anteriormente. Ahora sí..

Uso de TRIM Puede eliminar los espacios que no le interesen de nombres y apellidos en las tablas de actores y directores utilizando la siguiente consulta: USE videoteca. lo que significa que se actualizarán todos los registros de ambas tablas.apellidos = TRIM(a. Ejecute esta consulta: SELECT TRIM(' cadena '). Como ve.nombre). UPDATE actor SET apellidos = 'Hauer' WHERE nombre = 'Rutger'.nombre = TRIM(a. o del nombre? Lo ideal sería poder eliminar esos espacios de todas las columnas donde sea necesario. no se ha utilizado la cláusula WHERE . Aunque puede que le asalte la duda: ¿existirá algún actor más con un espacio delante del apellido. Esta modificación se puede realizar de la siguiente forma: USE videoteca.19. Recuerde que el apellido de Rutger Hauer tenía un espacio al comienzo.Por último.nombre = TRIM(d. algo que causó problemas en el apartado anterior. director d SET a. a. es posible utilizar una lista de condiciones que restringirán el conjunto de registros cuyo valor se modificará.apellidos).apellidos). y el resultado de aplicarle la función TRIM . Es necesario hacer un cambio en un determinado registro de la tabla de actores.nombre). utilizando la función TRIM . Esta función elimina los espacios que anteceden o preceden a una cadena de texto.19 puede comparar el aspecto de la cadena con sus espacios antes y después. Puede hacerlo con una consulta de actualización sobre la tabla de actores y directores. pero .apellidos = TRIM(d. d. UPDATE actor a. d. En la figura 6. que afecte a todos los registros. Figura 6. El apellido del actor Rutger Hauer ya es correcto. Estas condiciones son similares a las utilizadas en las consultas de selección.

CONCAT(nombre. La primera instrucción hace referencia a Rutger Hauer. Pero también puede hacer esto otro: USE videoteca. ' '. Podría insertar el primero así: USE videoteca. 8). la segunda a Sean Young. El siguiente apartado está dedicado a las inserciones de datos. Vea el efecto que han tenido estas inserciones: USE videoteca..idactor = a.. idactor ) VALUES(1. Inserciones La sintaxis de la instrucción de inserción es la siguiente: INSERT INTO tabla [(columna.id = app.. SELECT titulo. Puede ver el resultado de esta consulta en la figura 6. Inserte los valores necesarios en la tabla de actores por película para que Rutger Hauer y Sean Young aparezcan en el reparto de "Blade Runner". 9). viendo de paso cómo realizar las asociaciones entre películas.aún no aparece como intérprete de ninguna película..). La parte en la que se indican los nombres de las columnas se puede omitir si en la parte de los valores éstos se escriben en el orden en el que se definieron al crear la tabla.idpelicula JOIN actor a ON app. apellidos) AS interprete FROM pelicula p JOIN actores_por_pelicula app ON p.titulo = 'Blade Runner'. ..)] VALUES (expression..20. y además existe un valor para cada columna. INSERT INTO actores_por_pelicula VALUES(1. INSERT INTO actores_por_pelicula( idpelicula.id WHERE p.

COUNT(app.Figura 6. Para añadirlo como actor necesitamos conocer el identificador de la película.idactor) interpretes FROM pelicula p LEFT JOIN actores_por_pelicula app ON p. Ya debe tener los conocimientos suficientes para hacerla por sí mismo. 6). Figura 6. También podría construir una consulta que contase el número de actores que tiene cada película. Como puede comprobar. es posible saber si una película tiene más de un actor si su título aparece más de una vez. Si vuelve a repetir la consulta que dice cuántos intérpretes tiene asociados una determinada película.21. Si lo buscamos en la base de datos verá que aparece con el identificador 6. INSERT INTO actores_por_pelicula(idpelicula. Hay una película sin actores: Naves misteriosas. Not a: Queda como ejercicio para el lector repetir el mismo proceso con los directores.idpelicula GROUP BY p. Varios actores para una película Como ve. En caso de que encuentre alguna película sin director. Pero esta consulta devuelve otra información digna de mención. ¿Existirá algún actor de esa película en la tabla de actores? "Naves misteriosas" fue protagonizada por Bruce Dern. que es el 4.titulo. ya lo sabíamos. Intérpretes por película Gracias a esta consulta de selección hemos localizado una inconsistencia en la base de datos: una película sin actores. podrá comprobar que "Naves misteriosas" ya tiene uno.id = app. podemos decirle que Douglas Trumbull dirigió "Naves misteriosas".21. El resultado de esta consulta puede verse en la figura 6.id. idactor) VALUES(4. "Blade Runner" tiene tres actores. Una nueva inserción en la tabla de actores por película solucionará el problema: USE videoteca. .20. entre otros. así que le proponemos que lo intente por su cuenta antes de mirar la solución que se incluye a continuación: USE videoteca. SELECT p.

Figura 6. Una simple equivocación en la condición de borrado y se perderán datos. La figura 6. COUNT(p.Borrados Una de las operaciones más peligrosas es el borrado de registros.id) peliculas FROM soporte s LEFT JOIN pelicula p ON s.23.id. El resultado de esta consulta puede verse en la figura 6. SELECT s.nombre. La sintaxis de esta instrucción es la siguiente: DELETE FROM tabla [WHERE condición].idsoporte GROUP BY s.id = p. Películas en cada formato Puede que se haya deshecho de todas sus grabaciones en LaserDisc. Compruebe qué formatos de grabación están disponibles: USE videoteca. o que el lector haya dejado de funcionar y las . Quizá necesite hacer algún borrado en la base de datos.22. Si no indica ninguna condición se eliminarán todos los registros de la tabla.23: no existe ninguna película en formato LaserDisc.22 muestra el resultado. La parte del WHERE es similar a la utilizada en consultas de selección y permite restringir los registros que se borrarán. Formatos de grabación Puede averiguarlo con la siguiente consulta: USE videoteca. SELECT * FROM soporte. ¿Existen películas en todos esos formatos? Figura 6.

siempre que la base de datos esté diseñada correctamente. pero las herramientas están ahí. actualización y borrado de registros en tablas. DELETE FROM soporte WHERE id = 3. Sin embargo. La sintaxis real de las instrucciones que este capítulo ha cubierto es más compleja. inserción.películas ya no sean útiles. Lo más importante de este capítulo es que comprenda que con SQL se puede extraer cualquier información de una base de datos. manteniendo la consistencia de los datos. Otra conclusión que debe sacar de este capítulo es que el empleo de archivos de órdenes es mejor que el uso de herramientas visuales para tareas repetitivas. y el espacio disponible en esta guía es limitado. en realidad. Elimine ese formato de la tabla de soportes de grabación: USE videoteca. ahora tiene la base necesaria para enfrentarse a la documentación que MySQL proporciona en su Web sobre la sintaxis completa de su versión del lenguaje SQL con muchas más posibilidades de éxito. También hemos visto cómo crear y borrar bases de datos. Las opciones y los modificadores son muchos. Y tan importante como extraer la información es saber guardarla. Quizá unas consultas sean más complicadas que otras. . ¡Adiós. LaserDisc! Durante este capítulo hemos visto la sintaxis de las instrucciones de selección.

la interfaz de acceso a MySQL fue mejorada. para gestionar archivos XML.7 PHP y MySQL Hasta ahora nos hemos dedicado a adquirir los conocimientos básicos de MySQL y PHP. nuestro primer paso para trabajar con MySQL. Acceso mejorado a MySQL Aunque el equipo de desarrollo de PHP 5 se centró en mejorar aspectos del lenguaje como la orientación a objetos. Sin ir más lejos. Es muy importante que sepamos cómo reaccionar ante situaciones no previstas. la nueva forma de acceder MySQL desde PHP que apareció en la versión 5. pero no se trata sólo de aspecto técnicos: acceder a MySQL resulta mucho más sencillo con esta nueva interfaz. Estas opciones de configuración también pueden incluirse en las secciones que se refieran a nuestro servidor Web. claro). Hemos visto lo más destacado de ambas tecnologías. también es posible realizar operaciones de creación de bases de datos y tablas. . para trabajar con archivos en formato PDF y un largo etcétera. PHP agrupa las funciones dentro de extensiones. Existen extensiones para acceder a MySQL. Utilizando esa conexión realizaremos operaciones de consulta. Además de éstas. No dejaremos de ver las técnicas necesarias para controlar los errores que se puedan producir en nuestros intentos de conexión y en posteriores consultas. Pero incluso en ese capítulo nos limitamos a utilizar la cara funcional de MySQLi. pero sin llegar a mezclarlas (exceptuando la toma de contacto del capítulo primero. dentro de la configuración de Apache. inserciones. Ha de prestar especial atención a esta forma de trabajo. Para terminar el capítulo veremos cómo modificar el archivo de configuración de PHP para influir en el comportamiento predeterminado de MySQLi. actualizaciones y borrados sobre bases de datos existentes. no por ello se descuidaron otros. Durante este capítulo veremos cómo utilizar MySQLi en su vertiente orientada a objetos. Comenzaremos viendo cómo se realiza una conexión con un servidor de bases de datos. Not a: No vamos a entrar en los detalles que hacen mejor a esta versión. Realmente largo: PHP dispone de extensiones para casi cualquier operación que pueda imaginar. puesto que es la que utilizaremos en el resto de capítulos.

en la mayoría de las ocasiones bastará con los cuatro parámetros antes enumerados. puede indicar otros valores al realizar la conexión. También se hizo un esfuerzo para que aquellos que ya supiesen cómo utilizar la extensión original de acceso a MySQL no encontrasen complicado dar el salto a la nueva versión. cuál es su clave y cuál es la base de datos con la que va a trabajar. El ciclo de la vida De la vida en común de PHP y MySQL.Mientras que el nombre de la versión primigenia es MySQL. Si es su caso. La "compatibilidad hacia atrás" (backwards compatibility) es un aspecto fundamental en la vida de un lenguaje de programación. conectábamos con la base de datos de películas utilizando el siguiente código: <?php . no tendrá que desandar el camino: todo lo que sepa de MySQL podrá aprovecharlo en MySQLi. Not a: Aunque. Conexión El paso primordial de su relación con MySQL es la conexión. el nombre de la nueva versión es MySQLi. La creencia más extendida es que la última "i" latina significa mejorado (improved) aunque no es descabellado pensar que su significado sea otro. Sin conexión no habrá nada que pueda hacer con su servidor de bases de datos. las nuevas versiones deben ser capaces de ejecutar programas desarrollados para versiones anteriores. operación y desconexión. Para que los programas ya existentes fuesen compatibles con las nuevas versiones de PHP era necesario mantener las anteriores funciones de acceso. opcionalmente. Por ejemplo. Puede realizar la conexión en el mismo momento de crear el objeto que utilizará para conectar con la base de datos. como el puerto o el socket. se entiende. Sólo una cosa más antes de empezar: esta extensión sólo funciona con servidores MySQL a partir de la versión 4. recuerde el ejemplo del primer capítulo. incluyendo las nuevas bajo una denominación diferente. PHP son las siglas de PHP: Hypertext Preprocessor. con qué usuario quiere conectar. Durante el proceso de conexión indique dónde está el servidor de bases de datos.1. Entonces. Todas las operaciones que realicemos desde PHP con MySQL van a seguir los mismos pasos: conexión. A fin de cuentas.

la clave es clave y el nombre de la base de datos es videoteca.. if ($videoteca->errno != 0) { echo('Error en la conexión. que hemos llamado videoteca. 'videoteca' ). que siempre se asigna al ordenador con el que estamos trabajando. exit(). Volvamos a escribir el código de conexión. 'clave'.0. Como parámetros del constructor de la clase hemos pasado el nombre del servidor.. la . por defecto. } . el usuario root de MySQL. 'clave'. Si recuerda lo aprendido sobre programación orientada a objetos en el capítulo 4 reconocerá que la primera línea del fragmento de código anterior crea un ejemplar de la clase mysqli. exit(). Not a: Recuerde que. Not a: Sabemos que ambos servidores están en la misma máquina porque se utiliza localhost como nombre del servidor.'). } . Este código muestra cómo conectar con un servidor MySQL utilizando la versión funcional de MySQLi. pero ahora utilizando la versión orientada a objetos de MySQLi: <?php $videoteca = new mysqli( 'localhost'. 'videoteca' ).$conexion = mysqli_connect( 'localhost'.0.. 'root'. El servidor de bases de datos se encuentra en la misma máquina que el servidor de páginas. el nombre del usuario. el nombre del usuario es root . if ($conexion == FALSE){ echo('Error en la conexión. no tendrá contraseña alguna asignada. Por lo tanto tendrá que sustituir 'clave' por '' (una cadena vacía). si instaló XAMPP para seguir el contenido de este libro.1.'). 'root'. Este nombre se corresponde con la IP 127..

no existir la base de datos o quizá se haya equivocado en el nombre de usuario o en la contraseña. una tienda a través de Internet. los clientes buscarían los productos que les interesasen (realizando consultas). no tiene más que utilizar la propiedad errno de la clase. La primera de las líneas anteriores utiliza la variable $conexión. . if ($resultado == FALSE){ echo('Error en la consulta.clave y el nombre de la base de datos con la que queremos trabajar. la más común de todas las operaciones que vamos a realizar es la recuperación de información a través de consultas. Es el primer parámetro de la función mysqli_query().. Por lo general los usuarios de estas aplicaciones realizarán consultas. devolverá cero.. que en caso de error devuelve el código asociado al mismo. mientras que los administradores se encargarán del mantenimiento de la base de datos. Siguiendo con nuestro ejemplo del primer capítulo. Operación Una vez establecida la conexión. informará de que ha ocurrido un error al realizar la conexión. podrá comenzar realizar operaciones con la base de datos. 'SELECT * FROM genero' ). la creación de aplicaciones Web.. En la tienda que acabamos de mencionar. El segundo es la consulta que queremos realizar en la base de datos. Es posible que ocurra algún error durante el intento de conexión: el servidor MySQL puede estar apagado. mientras que los administradores se encargarían de añadir nuevos productos a la tienda.'). Si no se produjo ningún error. Por ejemplo. en caso de que no sea cero. que contiene la información devuelta por la función mysqli_connect() en el primer fragmento de código. $resultado = mysqli_query( $conexion. } . modificar los ya existentes o eliminar aquellos que estuviesen descatalogados.. por lo general. Así. Para controlar esos casos. este fragmento de código era utilizado para obtener la lista de géneros cinematográficos que hay en la base de datos: . El objetivo de utilizar PHP y MySQL de forma conjunta es. Pero si no ha ocurrido ningún error.

El siguiente fragmento de código muestra el equivalente utilizando la versión orientada a objetos.. $fila[0].. Utilizamos printf() para mostrar los datos que acabamos de obtener. Si olvidase avanzar al siguiente registro. con la que se obtiene el mismo resultado: ..%s<br/>". Al obtener un elemento de la lista de registros devueltos.').. como se suele decir coloquialmente. Sin embargo. a su vez. siendo cada uno de sus elementos un campo del registro. en realidad nos evita muchos problemas. Puede recuperar esos registros utilizando el siguiente código: . Acaba de ver cómo se ejecuta una consulta y se obtienen los datos utilizando la versión funcional de MySQLi. Esto. while($fila = mysqli_fetch_row($resultado)){ printf( "(%u) %s .De igual forma que $conexion almacenaba la información necesaria para que MySQLi pudiese realizar operaciones con la base de datos tras realizar la conexión. pero el avance automático no se realiza. .. } . $resultado contiene la información necesaria para poder recuperar todos los registros devueltos por la consulta.%s<br/>". $fila[1]. "colgado". quedando. Cada llamada a mysqli_fetch_row() devuelve un registro que se almacena en la variable $fila. $fila[1]. avanzamos automáticamente al siguiente. $fila[2] ). el bucle no terminaría nunca y el programa no avanzaría. Esta variable es.. if ($resultado == FALSE){ echo('Error en la consulta. que puede parecer una tontería. } while ($fila = $resultado->fetch_row()){ printf( "(%u) %s . Suponga que escribe el mismo bucle anterior. una matriz. Esta forma de trabajo es similar en otros lenguajes de programación con acceso a bases de datos. existe una ventaja que PHP tiene sobre algunos de ellos. $fila[0]. $fila[2] ). $resultado = $videoteca->query( 'SELECT * FROM genero' ).

en su versión funcional: $fila = mysqli_fetch_row($resultado) Comparémosla con el equivalente orientado a objetos: $fila = $resultado->fetch_row() En la versión funcional. Veamos la instrucción que permite obtener uno por uno todos los registros.. Para terminar este ciclo de operaciones hemos de cerrar la conexión con la base de datos. ese consumo de recursos se deba a que no se cierran las conexiones con la base de datos cuando se termina de trabajar con ella. la variable $resultado. Estamos trabajando con una función. mysqli_close($conexion).. Pero mientras pasa ese tiempo. en la versión orientada a objetos trabajamos directamente con el resultado de la consulta. Sin embargo. El servidor de bases de datos es lo suficientemente inteligente para detectar aquellas conexiones ociosas. utilizando la versión . El buen funcionamiento de sus aplicaciones depende de que sea civilizado en el empleo de los recursos a su disposición. Una conexión no cerrada estará consumiendo recursos.. algo tan sencillo de hacer utilizando la versión funcional de MySQLi como el código que puede verse a continuación: . ?> Mientras que la primera línea elimina de memoria el resultado de la consulta a la base de datos. que no están realizando alguna tarea. cerrarlas. la segunda cierra la conexión con MySQL. lo ha adivinado: en este caso esa variable no es otra cosa que un objeto. Es curioso que. El servidor de bases de datos puede responder simultáneamente a varios clientes. mysqli_free_result($resultado). Una vez alcanzado ese techo. Y. MySQL no podrá responder más peticiones.). } . efectivamente. en muchas ocasiones. Desconexión No por ser la última es la menos importante. El mismo objetivo puede obtenerse con las siguientes líneas. pero hasta un límite. Una de las ventajas de la programación orientada a objetos es que el código resultante es más fácil de comprender que el equivalente funcional.. llamamos a una función que recibe como parámetro el resultado de realizar la consulta. los recursos seguirán malgastándose. y pasado un tiempo.

orientada a objetos de MySQLi: . } $resultado->close(). 'clave'. $videoteca->close().'). ?> Acabamos de recorrer el ejemplo del primer capítulo. exit(). 'videoteca' ). mostrando lo que le pedimos: la lista de géneros cinematográficos que hay en nuestra base de datos. } $resultado = $videoteca->query( 'SELECT * FROM genero' ). $fila[0]. Veámoslo completo: <?php $videoteca = new mysqli( 'localhost'. La figura 7. viendo cómo se obtendría el mismo resultado utilizando la versión orientada a objetos de MySQLi. que pudo ver en la figura 1.1 muestra el resultado de ejecutar esta página. 'root'. $fila[1].19. $videoteca->close(). ?> Aunque dista mucho de ser un programa profesional. $resultado->close(). .'). cumple su función con dignidad. $fila[2] ). if ($resultado == FALSE){ echo('Error en la consulta... } while ($fila = $resultado->fetch_row()){ printf( "(%u) %s . Como puede comprobar es idéntico al que se obtiene con la versión funcional de MySQLi.%s<br/>". if ($videoteca->errno != 0) { echo('Error en la conexión.

Figura 7. aunque entonces con la versión funcional de MySQLi. consulta y desconexión) vamos a profundizar en algunos aspectos interesantes de esta biblioteca de funciones.Figura 7. en el primer capítulo ya realizamos estas operaciones.2 describe las operaciones que tendrá que realizar para lograr su objetivo. La figura 7..1. $resultado = $videoteca->query( 'SELECT * FROM genero' . Conjuntos de registros Ni la conexión ni la desconexión con MySQL guardan ningún misterio. El ciclo de la vida y los géneros Not a: Como recordará. Ahora que sabe cómo utilizar MySQLi para realizar las operaciones básicas (conexión. Sin embargo. Recordemos cómo recuperamos los registros devueltos por una consulta: . Durante este capítulo utilizaremos la versión orientada a objetos.2. con objetos Resumiendo. La lista de géneros.. las operaciones que hemos tenido que realizar para realizar una consulta a nuestra base de datos de películas son siempre las mismas. el resultado de realizar una consulta a la base de datos sí.

con sus métodos y sus atributos.. } while ($fila = $resultado->fetch_row()){ printf( "(%u) %s .... Si la consulta tiene éxito. Sólo tendría que incluir el siguiente fragmento de código. de manera que no se corresponda con el nombre de ninguna tabla existente en la base de datos con la que está trabajando (por ejemplo. cambie en la consulta el nombre de la tabla (genero). lo que permitirá localizar el problema. En este caso. podrá acceder a los resultados gracias a la variable $resultado. . $fila[1]. Puede comprobar el tipo de esta variable utilizando la función gettype(): . Tras realizar una consulta con éxito. se les da el nombre de mixed. La variable $resultado es un ejemplar de la clase mysqli_result . En primer lugar. gettype($resultado)). Pero. ¿qué resultado obtendrá si la consulta no tiene éxito? Para comprobarlo.3: . El resultado será la cadena object . generos).. .. Not a: A estas variables. printf("%s". Si intenta realizar la consulta ocurrirá un error. Veamos algunas de las propiedades más interesantes: num_rows: Contiene el número de registros que la consulta ha devuelto. ha obtenido una referencia a un objeto.%s<br/>". $fila[0]. siendo el resultado el que puede verse en la figura 7. Entonces. ese ejemplar se llama $videoteca. realice la consulta llamando al método query() del ejemplar de la clase la clase mysqli que esté utilizando. que pueden adoptar varios tipos en función de las circunstancias. puede ser interesante mostrar el número de registros encontrados.'). } ..'SELECT * FROM genero' ). el tipo de la variable $resultado será boolean. if ($resultado == FALSE){ echo('Error en la consulta. En nuestro ejemplo de la lista de géneros. Es decir. $fila[2] ). puede acceder a sus métodos y atributos..

en caso de que se utilizasen alias en la consulta. Este valor puede resultar interesante para controlar el ancho de una tabla en la que mostrar el resultado de la consulta. La tabla 7. Nombre de la tabla. Puede ser útil cuando no quiera realizar una iteración por todo el conjunto de resultados devuelto por la consulta que haya realizado. Elementos de fetch_field() Pro p ied ad name orgname table orgtable def max_length flags type decimals D escrip ció n Nombre de la columna. en caso de que se utilizasen alias en la consulta.printf( "Registros encontrados: %s. Número de registros encontrados field_count: Devuelve el número de columnas que tiene cada uno de los registros devueltos.<br/><br/>". Tabla 7. siendo cada uno un elemento de la matriz devuelta. por ejemplo. data_seek: Permite que nos desplacemos a un registro en concreto dentro de los resultados. fetch_field() devuelve información sobre los campos del registro actual. Figura 7..3. Valor predeterminado. Nombre original de la columna. También merecen especial mención los siguientes métodos: fetch_field: Si fetch_row() permite obtener uno por uno los registros devueltos por la consulta. Nombre original de la tabla. Tamaño del campo. Ese mismo .1. como hacía fetch_row(). .. Tipo del campo. Por ejemplo si sólo quiere mostrar los resultados en páginas de un número de elementos cada una.1 muestra los diferentes elementos en los que esta información está repartida. indica el número de decimales empleados. expresados de forma numérica. El resultado lo devuelve en una matriz. $resultado->num_rows ). Podría utilizar estos valores como encabezados de cada columna de una tabla HTML si decidiese mostrar la información de los géneros dentro de una. puede utilizar un bucle for controlado por una variable cuyo valor irá incrementando. Si el campo es entero. Atributos del campo.

que nos permitiría insertar un nuevo género en la base de datos. el método query() puede utilizarse para ejecutar consultas. y así sucesivamente. $fila[1]. .. if ($resultado == FALSE){ echo('Error en la consulta. pero no un conjunto de registros. $resultado->data_seek(0).. $sConsulta = <<<CONSULTA INSERT INTO genero( nombre. 'Thriller' ).%s<br/>". Otras consultas Como ya hemos comentado. printf( "(%u) %s .. Sustituya el bucle while por: . La única diferencia está en que el resultado de ejecutar este tipo de consultas sólo devolverá TRUE en caso de éxito y FALSE en caso contrario. Si obtiene cuatro registros.valor será el que pasaremos a data_seek() para obtener uno por uno los registros que nos interesen. $resultado = $videoteca->query($sConsulta). para obtener el segundo un uno. $fila = $resultado->fetch_row(). El siguiente fragmento de código ilustra el concepto. Not a: Si lo desea puede encontrar más información acerca de la clase mysqli_result . $fila[2] ). CONSULTA. recuperando sólo el primer elemento devuelto por la consulta.'). $fila[0]. para obtener el primero debe pasarle a la función un cero. una vez establecida la conexión: .. Como ejemplo. el siguiente fragmento de código.. . inserción o actualización. sus métodos y sus atributos en la documentación de PHP.. descripcion )VALUES( 'TH'. pero no tienen que ser sólo consultas de selección: también puede tratarse de consultas de borrado.

$sTitulo. Consultas escapadas No se trata de aquellas consultas que se fugaron (perdón por el chiste fácil y malo). $resultado = $videoteca->query( $sConsulta ). Y esta cadena no es otra que una consulta. En la jerga de los informáticos. el objetivo de esta conversión es hacer válida una cadena que no lo es. 'videoteca' ). 'usuario'. como las comillas simples. . en la carga de la página que muestra los géneros podrá ver el que acabamos de añadir.echo('Error en la consulta.". Existen ciertos caracteres que no pueden incluirse en una consulta. " " " titulo. $sConsulta = "INSERT INTO pelicula(". idgenero". 1. La siguiente inserción no sería válida: <?php $videoteca = new mysqli( 'localhost'. } $sTitulo = "Ocean's Eleven". idsoporte. } . ")VALUES(". "escapar" se entiende en algunos contextos como "realizar una conversión". ")". Como resultado.').. if (mysqli_connect_errno() != 0) { echo('Error en la conexión.". 4".. 'clave'. if($resultado == FALSE){ echo('Error en la consulta.".'). " " " '". exit(). En nuestro caso.". Si la inserción no tuvo éxito podrá saberlo gracias al valor devuelto por el método query().')."'.

echo($videoteca->error). El problema se debe. concretamente en la siguiente dirección: http://php. .echo('Error en la consulta. Pero luego encuentra otro carácter de apertura de cadena. la más inmediata consiste en crear una página PHP con el siguiente contenido: <?php phpinfo(). El método real_escape_string() hará los cambios necesarios en el título para que la consulta de inserción pueda realizarse. } $videoteca->close(). Tampoco vamos a verlas todas ahora. ?> .. Y el primer paso es consultar los valores que estas opciones tienen en nuestro sistema. Hay soluciones para todo. debido a que son demasiadas y no es éste un manual de referencia. Configuración Al comienzo del libro hablamos sobre cómo programar usando PHP. Existe numerosa documentación al respecto en la Web de PHP. Inserte la siguiente línea antes de crear la variable $sConsulta: ..net/manual/es/configuration. aunque no entramos en detalles tales como las posibles opciones de configuración existentes para este lenguaje. a que el título tiene una comilla simple.').php Lo que sí trataremos en este apartado son las opciones de configuración de PHP que afectan al funcionamiento de MySQLi. y MySQL lo entiende como el cierre de una cadena. . no cerrado y se hace un verdadero lío. Valores de configuración Aunque existen varias formas de consultar los valores de configuración de MySQLi vigentes en nuestro sistema.. simplemente.... $sTitulo = $videoteca->real_escape_string( $sTitulo ).

El cliente le mostrará la sección de parámetros de configuración de la biblioteca de funciones MySQLi.4. En este caso el valor predeterminado es .default_port: Especifica el número de puerto predeterminado al que realizar las solicitudes de conexión. Como puede ver en la figura 7. La segunda sección es la que nos interesa. la versión de la API y la ubicación del socket (relacionado con la comunicación del servidor MySQL y sus clientes). Figura 7. y que puede cambiar si lo considera oportuno. Configuración de MySQLi Truco: El comportamiento de la función phpinfo() no es siempre el mismo.4. ya que muestra los parámetros de configuración aplicables en este momento.Una vez la tenga. este parámetro no tiene ningún valor asociado. busque dentro de esa página el texto mysqli. april's fools). La primera de ellas muestra detalles sobre el funcionamiento de MySQL. Son los siguientes: mysqli. Utilizando las herramientas de su cliente Web. Compare el logotipo de PHP que aparece al principio de la información devuelta por la función. No cabe duda: tienen sentido del humor. si al establecer la conexión no ha indicado ninguno. es decir. por lo que cualquier intento de conexión sin indicar servidor será fallido. Not a: API son las siglas de interfaz de programación de aplicaciones (Application Programming Interface). mysqli. con la imagen que muestra si usted cambia la fecha de su ordenador al 1 de abril (el día de las inocentadas de los angloparlantes. puede acceder a ella con cualquier cliente Web.4. del propio MySQLi.default_host: Le permite indicar cuál será el servidor MySQL al que se conecte por defecto. La información respecto a la configuración de MySQLi está divida en dos partes. Debería ver algo parecido a lo que muestra la figura 7.

es decir. mysqli. el puerto estándar de MySQL.default_user: Nombre del usuario predeterminado si al intentar conectar no indica ninguno.reconnect: Por defecto desactivado. Not a: En la figura 7. Pero. mysqli. este parámetro no contiene ningún valor.3306. La primera se refiere a los valores aplicables a la página que estamos viendo ahora.default_socket: Permite indicar el socket que se utilizará durante la comunicación entre el servidor de bases de datos y el cliente. Si no se indica ningún valor (como es el caso) PHP utilizará los valores internos de los que dispone. respectivamente). Sin este parámetro de configuración tendría que incluir el número de puerto al realizar la conexión. mysqli.max_links: Número máximo de conexiones con MySQL permitidas desde sus aplicaciones PHP. aunque también puede estar en la carpeta en la que instaló PHP. Por defecto. de forma automática. Por defecto no contiene ningún valor.default_pw: Clave de acceso predeterminada. Permite que PHP intente. de forma que su servidor no se colapse ante un aluvión de peticiones. En cambio. tras el nombre de la base de datos. En breve veremos cómo hacer esta distinción. la que sus intentos de conexión utilizarán si no indica ninguna al intentar conectar. ¿cómo puede cambiar los valores de estos parámetros? Modificación de la configuración Todos los parámetros de configuración de PHP se encuentran en el archivo php. La ubicación de este archivo varía dependiendo del sistema operativo que utilice y de cómo haya instalado PHP.ini. Ahora ya conoce los valores predeterminados de estos parámetros de configuración y cómo afectan al funcionamiento de la biblioteca de funciones MySQLi. la reconexión con el servidor MySQL en caso de que ésta se perdiese. Es la existencia de este parámetro el que permite realizar la conexión sin indicar valor alguno para el puerto. mysqli. Está obligado a especificar el nombre del usuario porque. Si utiliza Linux o Mac OS X.4 habrá podido comprobar que existen dos columnas asociadas a valores: Local Value y Mast er Value (valores locales y maestros. en Windows. sin límite. o de la potencia y recursos de su servidor. puede que quiera indicar un límite. mysqli. . es una buena idea mantenerlo en la carpeta del sistema (C:\WINNT puede ser uno de los nombres que tome). Dependiendo de la naturaleza de las aplicaciones que esté desarrollando. es más que probable que pueda encontrar este archivo en algún lugar de la carpeta /etc. mientras que la segunda a los aplicables a todas las páginas. por defecto.

indicando su nombre entre corchetes. PHP y MySQL.ini se encontrará en la carpeta /apache/bin/php.5 realizamos dicha búsqueda con el bloc de notas. Sección MySQLi en php.5. si utilizó XAMPP para instalar Apache.ini dentro de la carpeta en la que XAMPP se instaló. Una vez reiniciado podrá utilizar la página PHP que llama a la función phpinfo() para comprobar que el valor del parámetro de configuración es el que hemos indicado en el archivo php. . sólo tiene que reiniciar el servidor de páginas Web. que ahora mismo no tiene ninguno asignado. Esté donde esté el archivo.ini. Figura 7. sea localhost .ini Haga una prueba sencilla: cambie el servidor predeterminado al que conectar de manera que el valor de esta variable. En la figura 7. El resultado debería ser similar al que se puede ver en la figura 7.6. Cuando haya realizado el cambio y guardado el archivo. ábralo con su editor de textos favoritos y busque la sección MySQLi. el archivo php. Apache.Independientemente del sistema operativo.

} . 'root'. Recapacitemos durante un momento: ¿qué beneficio puede obtener modificando estos parámetros de configuración? Ventajas Suponga que tiene una página PHP por cada lista de valores de la base de datos.. if ($conexion == FALSE){ echo('Error en la conexión. no indicando el servidor MySQL al que quiere conectar. Sin embargo.Figura 7.6. 'videoteca' ). Anteriormente esa cadena era localhost . el primer parámetro que pasamos al constructor de la clase. ahora es una cadena vacía. 'clave'. Como puede ver. Servidor MySQL predeterminado ¿Cómo puede aprovecharse de este cambio en sus programas? Por ejemplo.'). exit(). podrá comprobar que la página sigue conectando. El siguiente fragmento de código le permite conectar con el servidor MySQL que tenga en el mismo ordenador en el que esté trabajando: <?php $conexion = new mysqli( ''.. En cada una de esas páginas debe realizar una conexión con el servidor MySQL para . que debería ser el nombre del servidor. recuperando la lista de géneros cinematográficos y mostrándolos perfectamente.

Y por último. conservando las opciones globales del archivo php. o sus propios archivos INI. Imagine lo desconcertante que puede ser ver una línea de código que conecta con un servidor MySQL que no se especifica. Podría utilizar archivos de inclusión. El acceso por parte de desaprensivos a estos archivos es más complicado. indicando el servidor. Pero existe otra ventaja. relacionada esta vez con la seguridad. Digamos que tiene cinco páginas PHP y. este método también tiene sus inconvenientes. es decir. de los que hablamos en el capítulo cuatro. esta información se encuentra en un archivo de configuración del sistema. el nombre de usuario y la contraseña. Tiene entonces el nombre de usuario y su contraseña en todos los archivos que conectan con la base de datos. También ha de asegurarse que en ninguna página de la Web se muestre la información devuelta por phpinfo(). Inconvenientes No todo iban a ser ventajas. aunque no demasiado importante. antes de sus cambios. ¿No sería mejor tenerlos escritos en un solo sitio. una sola vez? De esa forma. es que tiene que dejar claro a otros que puedan trabajar con usted dónde están almacenados tanto el nombre de usuario como la contraseña de acceso. Sin embargo. ya que esa página mostraría a todo el mundo la forma de conectar con el servidor de bases de datos. Además. Si logra que ese nombre de usuario y esa contraseña estén en un solo lugar habrá reducido cinco veces la probabilidad de que alguien se haga con la forma de acceder a su base de datos. Not a: Existen otras técnicas para almacenar en un único lugar los parámetros de conexión al servidor MySQL. Obviamente. . Uno de ellos. si por cualquier motivo tuviese que cambiar el nombre de usuario o su contraseña. en cada una de ellas. debe asegurarse de que la aplicación funciona correctamente bajo cualquier circunstancia. sin utilizar ni nombre de usuario ni contraseña. algo que puede ayudarle a mejorar la seguridad de su aplicación Web. existe una forma de modificar las opciones de configuración de MySQLi para sus aplicaciones. no todas las aplicaciones utilizarán los mismos parámetros de conexión. como programador. Esta ventaja supone comodidad para usted que.posteriormente obtener los registros que quiere mostrar en la página. podría hacerlo sabiendo que ese cambio en la configuración de MySQL sólo implica un cambio en su aplicación Web. el nombre de usuario y la clave.ini tal y como estaban. estos valores son globales. se aplican a todas las aplicaciones Web que se ejecuten bajo su servidor PHP.

busque la cadena de texto htdocs dentro de un elemento <Directory>. localice la etiqueta que cierra esta sección de la configuración: </Directory> A continuación de esta etiqueta escriba las siguientes directivas de configuración: <Directory "C:/xampp/htdocs/pruebas"> Options Indexes FollowSymlinks AllowOverride None Order allow.Opciones de PHP en Apache La opción más simple para probar los programas PHP de ejemplo que hemos estado estudiando durante esta guía es guardar los archivos correspondientes en la carpeta htdocs. la segunda muestra el valor localhost. . Es justo esto lo que queremos cambiar. dentro de la carpeta en la que XAMPP se instaló. reinicie el servidor Apache y ahora recargue las dos páginas que muestran el resultado de llamar a la función phpinfo() que están en las carpetas htdocs y htdocs/pruebas.ini.deny Allow from all php_admin_value mysqli. todas basadas en las opciones de configuración contenidas en el archivo php. PHP y Apache pueden trabajar de forma conjunta. si revisa las opciones de configuración de MySQLi que dichas páginas muestran. comprobará que han dejado de contener la misma información.7. lo encontrará en la carpeta /apache/conf/. Su nombre es httpd. Si abre dos clientes Web para observar la información devuelta por cada página podrá comprobar que son idénticas. como en la figura 7. dentro de htdocs.conf y. si utiliza XAMPP. llamada pruebas. Vamos a editar el archivo de configuración de Apache. pero cada una con sus particularidades. Vamos a crear una nueva carpeta. Debería ser algo así en Windows: <Directory "C:/xampp/htdocs"> La ruta será diferente en Linux y Mac OS X. Usando estas directivas. Es posible incluir ciertas directivas en los archivos de configuración de Apache que serán pasadas a PHP. Ahora. Guarde dentro de esta nueva carpeta una copia de la página PHP que llama a la función phpinfo() para mostrar las opciones de configuración. puede separar sus aplicaciones PHP. Ahora. en la ruta en la que Apache esté instalado. Mientras que la primera no tiene valor definido para el servidor MySQL predeterminado.default_host localhost </Directory> Guarde los cambios. Una vez tenga el archivo abierto con su editor preferido.

} .default_host localhost Puede ignorar las otras opciones de configuración.7. también puede diferenciar entre servidores virtuales. sepa que puede utilizar archivos .. ''. Para más información consulte la documentación de Apache y póngase en contacto con el administrador de sus sistemas. if ($conexion == FALSE){ echo('Error en la conexión.ht access para modificar las opciones de Apache de las carpetas Web a las que tenga acceso. ''.Figura 7.. Not a: Los pasos descritos anteriormente son aplicables a configuraciones estándar en las que tiene acceso a los archivos de configuración de Apache. pudiendo realizar las conexiones con las bases de datos así: <?php $conexion = new mysqli(''.'). exit(). Ahora sí que podría establecer un nombre de usuario y una clave diferente por cada aplicación. Diferentes valores locales y globales La línea importante es la siguiente: php_admin_value mysqli. Si no tiene acceso a ellos o no puede solicitar estos cambios al administrador del sistema. en este caso sólo aplicable a la carpeta pruebas. ''). . Con php_admin_value le indica a Apache que lo que viene a continuación es una variable de configuración de PHP. Y cada una de sus aplicaciones utilizaría los valores de configuración de PHP que hubiera indicado en el archivo de configuración de Apache. por ejemplo. siempre que las colocase en carpetas diferentes. Y no sólo puede establecer estas diferentes configuraciones para cada carpeta que le interese.

es cierto que en el código que acabamos de escribir hemos introducido algunos controles para los errores: al conectar y al realizar consultas. intente cargar de nuevo la página que muestra la lista de categorías.8. Cuando el servidor de bases de datos esté detenido. . Control de errores Sin embargo. es necesario llevarlos a cabo en la base de datos para poder mostrarlos en la página. Lo solucionaremos en el capítulo dedicado a Smarty. ha aprendido lo básico de PHP. Aunque se trata de una página dinámica. además de a usarlos de forma conjunta. La gestión de errores que hemos realizado hasta ahora no ha servido de nada. En el capítulo dedicado a los formularios HTML verá cómo modificar el contenido de la base de datos directamente desde una página Web. Esto es así por tres motivos. Veremos cómo combinar las herramientas que PHP nos proporciona para procesar los errores con las propias de MySQL en el capítulo dedicado a la gestión de errores. se trata de un proceso muy importante que con más frecuencia de la deseada se descuida. Y nunca más cierto que en este caso: no por ser el último es el menos importante de los motivos. A partir de aquí comienza la parte divertida. Pero.Anteriormente hicimos un comentario no del todo favorable acerca de la profesionalidad de las páginas que hemos programado durante este capítulo. Figura 7.8. Sí. no permite que realicemos cambios. ¿estamos seguros de que funcionan? La prueba más simple consiste en parar el servidor de bases de datos y volver a cargar la página. El primero salta a la vista: el aspecto que tiene la lista de categorías no es demasiado vistoso. cuyo aspecto cambia a medida que cambia el contenido de la base de datos con la que está trabajando. Hasta ahora. El segundo motivo es la falta de interactividad. Podrá ver el desastre que muestra la figura 7. MySQL. El último motivo que vamos a mencionar es la gestión de errores.

a partir de ahora será capaz de modificarlo. Un formulario no es más que un conjunto de elementos que podemos incluir en nuestras páginas HTML sobre los que los usuarios pueden realizar acciones y que. Lograremos este objetivo utilizando scripts en el lado del cliente. el usuario puede enviar. Durante este capítulo verá cómo crear sus propios formularios. . entendiéndola como la posibilidad de modificar desde nuestro propio cliente Web la forma en la que nos presentan los datos que solicitamos.8 Formularios No sólo de mostrar información vive la Web. los clientes pueden responder con los valores que hayan introducido en los campos de los formularios. La figura 8. Uno de los principales atractivos de la programación con PHP y MySQL está en la interactividad. Si con lo visto hasta este capítulo ha logrado mostrar el contenido de una base de datos en una página Web. Verá también cómo orientar a los usuarios para que no envíen valores incorrectos. junto con la petición de una nueva página. describimos la forma en la que un cliente Web solicitaba información a un servidor. ¿Recuerda cómo. una serie de valores. en el primer capítulo. pueden enviarse de vuelta al servidor. Al igual que el servidor envía las páginas a los clientes. y éste se la devolvía? En el caso de los formularios se trata de algo parecido: desde una página. e incluso los propios datos. como cadenas de texto donde se esperaba un número.1 ilustra el proceso. posteriormente. qué tipo de elementos puede incluir dentro de ellos para permitir que los usuarios le envíen información y cómo procesar esa información en sus páginas PHP para poder atender así a sus peticiones. El único requisito necesario para que los usuarios de nuestras aplicaciones puedan decirnos qué quieren hacer es aprender a utilizar una de las características del estándar HTML: los formularios. Cómo funcionan los formularios Hablar de formularios es hablar de intercambio de información.

Intercambio entre páginas Es decir. Los cuadros de texto nos permiten introducir el nombre del nuevo género y su descripción.2 se puede apreciar el aspecto de un hipotético formulario para dar de alta nuevos géneros cinematográficos. Esa página se encargará de dar de alta un nuevo género cinematográfico con el nombre y la descripción que el usuario de nuestra aplicación Web haya introducido en los cuadros de texto.2 es muy rudimentario. Figura 8. Veamos cómo crear utilizarlos. los datos que el cliente introduzca en los dos cuadros de texto se enviarán a la página de destino. Si es la primera vez que se enfrenta a un formulario ahora veremos con un poco más de detalle el aspecto de un formulario. Formulario para nuevos géneros Not a: El aspecto de la página de la figura 8. además de los cuadros de texto y los botones. En la figura 8. Para los formularios disponemos de muchos otros elementos. desde el formulario (sea lo que sea) enviamos de forma simultánea la petición de una nueva página y algunos valores. Al hacer clic en el botón Guardar (el tercer elemento del formulario). En esta página hemos creado un formulario con tres elementos: dos cuadros de texto y un botón.1. El servidor Web pasa esos valores a la página. Formularios HTML Los formularios son como cualquier otro elemento que . pero lo mejoraremos notablemente en el capítulo dedicado a las plantillas. que los procesa y devuelve un resultado.Figura 8.2.

Nos permite indicar en qué ventana se abrirá la página indicada en el atributo action del formulario. mientras que el método POST los incluye en los encabezados HTTP. La información del formulario se enviará a la página genero. No es sencillo de comprender sin ver un ejemplo. Cada método tiene sus ventajas e inconvenientes. puesto que se utilizará para dar de alta un nuevo género cinematográfico en nuestra base de datos. Página a la que se enviará la información del formulario. la siguiente sería la declaración del comienzo de un formulario: . Tabla 8. aunque sólo algunos de ellos enviarán información al servidor. se abra en una nueva ventana con sólo añadir t arget ="_blank" como atributo de la declaración del formulario. Es esa página la que tendrá que procesar los valores que el usuario haya introducido en el formulario y crear un nuevo género con ellos. la indicada en act ion. Truco: Puede provocar que la página de destino del formulario. Por último.. Atributos de un formulario At rib ut o name action method target D escrip ció n Nombre con el que puede referirse al formulario. Forma en la que dicha información es enviada al servidor.pueda definir en una página HTML. Los más importantes de estos aparecen en la tabla 8. que también comentaremos en este capítulo.. algo que haremos en breve. Su declaración sigue las mismas reglas que la creación de tablas o la inserción de imágenes.1. Por ahora. el método determina cómo se enviarán los datos entre las dos páginas. <form name="frm_alta_genero" action="genero. Es decir. baste decir que el método GET envía los datos en el mismo URL de llamada a la página de destino. Se consideran elementos del formulario todos los que haya entre estas dos etiquetas.php. El elemento de apertura de un formulario dispone de algunos atributos con los que se puede modificar su comportamiento. El nombre de este formulario es frm_alta_genero. Creación de formularios Un formulario HTML debe comenzar con la etiqueta <form> y terminar con la etiqueta </form>..1. . Es un nombre que describe adecuadamente la función del formulario.php" method="get"> ..

Cuadros de texto El más sencillo de todos los elementos de un formulario. Antes de hablar de ellos.3 puede verlos todos juntos. Un cuadro de texto puede tener los siguientes atributos: . Not a: Aunque existen otros elementos que puede incluir en un formulario HTML.3 le son familiares: son los mismos que puede encontrar en los programas de su gestor de ventanas y se comportan de igual forma que en ellos. etcétera). menús desplegables.Elementos de un formulario Hasta ahora ha visto dos de los elementos que pueden componer un formulario: cuadros de texto y botones. Veamos ahora uno por uno todos los elementos que podemos incluir en un formulario. botones de opción. Figura 8. Estos elementos se crean de igual forma que cualquier otro elemento dentro de una página HTML: utilizando etiquetas. Todos ellos comparten el nombre de la etiqueta. en la figura 8. <input> y algunos atributos: type: Su valor determina de qué elemento se trata (cuadro de texto. como casillas de verificación. name: El nombre por el que tendrá que referirse a los elementos del formulario para recuperar su valor. La única diferencia está en que ahora es usted el que crea la aplicación y no otras personas. Pero también dispone de otros. con los que vea en este capítulo podrá satisfacer la mayoría de las necesidades de sus aplicaciones Web. value: El valor que toma el elemento. es el cuadro de texto. botón. así como sus atributos.3. Elementos de un formulario Seguro que los elementos mostrados en la figura 8. listas e incluso elementos ocultos. Para crear uno dentro de sus formularios ha de crear un elemento input y asignar el valor text al atributo type. y con diferencia.

<input name="casilla" . lo que modificaría su aspecto. Casillas de verificación Una casilla de verificación puede tener dos estados: marcada o no marcada. independientemente de si ha asignado un valor a dicho atributo. y cuyo atributo type tiene el valor password. maxlength: Limita el número máximo de caracteres que se pueden incluir en el cuadro de texto. por ejemplo. Así.. Cuadro de texto El código HTML para generar este cuadro de texto es el siguiente: . ésta aparecerá marcada. Si checked está presente en los atributos de la casilla de verificación. el siguiente código HTML sirve para generar una casilla de verificación. TRUE o FALSE. Figura 8. pero es el atributo checked el que determina si la casilla está marcada o no..4. con un máximo de 32 caracteres. marcada por defecto: . cada carácter que introduzca en el cuadro de texto aparecerá como un asterisco. su ancho. Las casillas de verificación también pueden tener asociado un valor. type: Si este atributo está presente y su valor es password.. para evitar que miradas indiscretas sepan lo que está escribiendo.4 puede ver un cuadro de texto de 16 caracteres de ancho.. En la figura 8. Son ideales para representar valores de tipo booleano. pero el número máximo de caracteres podría ser 32.size: Determina el ancho del cuadro de texto.. <input name="texto" type="password" value="" size="16" maxlength="32"> . Un cuadro de texto podría tener un tamaño de 16 caracteres..

Si está presente. el estado de un botón de opción depende de la existencia o no del atributo checked.5 muestra cómo puede utilizar estos elementos en un formulario.. Si no está presente.5. el código de los botones de opción dentro del formulario que puede verse en la figura 8. <input name="lenguaje" type="radio" value="php" checked="true"> PHP<br/> <input name="lenguaje" type="radio" value="asp"> ASP<br/> <input name="lenguaje" type="radio" . Botones de opción En contraste con las casillas de verificación. Botones de opción Y a continuación. Figura 8.. La figura 8. Igual que las casillas de verificación. Para lograr este comportamiento ha de llamar igual a todos los botones de opción. Si selecciona uno de los botones de opción cancelará la selección de otro. los botones de opción suelen ir por grupos y permiten escoger entre valores con más de una opción.name="casilla" type="checkbox" value="checkbox" checked="true"> .5: . activo o no). el botón de opción estará marcado. utilizando el atributo name. independientemente de su valor... no lo estará. que permiten seleccionar entre dos valores (cierto o falso.

<select name="genero"> <option value="1" selected="true"> Ciencia Ficción </option> <option value="2"> Aventuras </option> <option value="3"> Drama </option> <option value="4"> Comedia </option> </select> .type="radio" value="perl"> Perl<br/> <input name="lenguaje" type="radio" value="mande"> ¿Páginas dinámicas? ¿Mande?<br/> .. Por otra parte. Menús desplegables Podríamos establecer parecidos entre los botones de opción y los menús desplegables. el menú contiene las opciones. El texto que aparecerá en cada una de las opciones del menú debe . El valor de este atributo es indiferente.. el segundo las opciones.6 es una buena muestra de ello. el menú de la figura 8. Géneros disponibles Para crear una lista desplegable necesita dos elementos. cada una de las opciones necesita un valor y una de ellas. ya que ambos ofrecen una serie de opciones de las que sólo puede seleccionar una.. Así. Figura 8. La figura 8. El primero de ellos es el menú... dispondrá del atributo selected. La declaración del menú sólo precisa de un nombre.6 se crea con el siguiente código: .6. la seleccionada..

estar entre las etiquetas de apertura y cierre del elemento option. Listas Una lista es una variedad de menú desplegable cuyo aspecto es el de una lista. Con la misma sintaxis que los menús y sólo añadiendo el atributo size con un valor mayor de uno podrá ver las opciones disponibles con otro aspecto. Por ejemplo, en la figura 8.7 puede ver una lista con los mismos valores que el menú de la figura 8.6.

Figura 8.7. Los géneros, en una lista

Pero existe una diferencia, ya que la declaración de esta lista es la siguiente:
... <select name="genero" size="4"> ...

Es decir, tiene un tamaño de 4 elementos. Aún existe una variante más que permite que se pueda seleccionar más de un elemento de la lista, de nuevo modificando la declaración de la lista. Observe el siguiente código:
... <select name="genero" size="4" multiple="true"> ...

Como puede apreciar existe un atributo más, multiple. Su valor es indiferente, basta con su existencia. El resultado: podrá seleccionar más de un elemento de la lista, como puede verse en la figura 8.8. Para lograrlo sólo tiene que seleccionar un elemento y, posteriormente, mientras mantiene la tecla Control (o Comando en Mac OS X) pulsada, hacer clic sobre otro elemento.

Figura 8.8. Más de un género seleccionado

Botones

Botones Se trata de uno de los elementos más importantes de todo formulario: es el que permite enviar la información introducida en el formulario de vuelta al servidor, para que la página de destino (la indicada en el atributo action del formulario) la procese. Dos son los tipos de botón más utilizados. El primero de ellos se utiliza para devolver a sus valores predeterminados a todos los elementos del formulario del que forma parte. El atributo type de estos botones toma el valor reset . El segundo tipo es el que permite enviar el formulario a la página de destino. En este caso, el atributo type toma el valor submit .
Not a: Existe un tercer tipo de botón que se utiliza cuando se desea que se ejecute alguna tarea al hacer clic sobre el botón, en lugar de provocar el envío de los campos del formulario.

Campos ocultos Hemos dejado para el final aquellos campos que, aunque no se vean, pueden formar parte de un formulario. Estos campos son muy útiles para enviar a la página de destino algún valor que no sea introducido o modificado por el usuario. Para crear un campo oculto, el atributo type del elemento input debe tomar el valor hidden, como muestra el siguiente fragmento de código:
...

<input type="hidden" name="servidor" value="pruebas"/>

...

Cuando se envíe la información a la página de destino, además de todos los campos visibles, también se enviará una variable llamada servidor cuyo valor será test . Y con esto ya hemos visto cómo crear un formulario y los elementos que lo integran. Seguramente estará deseando ponerse manos a la obra. Y a ello vamos.

Envío de información
Vamos a crear un formulario para enviar a otra página la información necesaria para dar de alta un nuevo género cinematográfico. El aspecto de esta página pudo verse en la figura 8.2, pero no así su código. Es el siguiente:
<html>

<head> <title>Nuevo género</title> </head>

<body>

<form name="frm_genero" method="get" action="">

<strong>Nombre:</strong><br> <input type="text" name="nombre"><br>

<strong>Descripción:</strong><br> <input type="text" name="descripcion"><br>

<input type="submit" value="Guardar">

</form>

</body>

</html>

Puede guardar esta página con el nombre genero.html. Tras la descripción que vimos anteriormente sobre los componentes de un formulario, y el mismo formulario, llaman la atención dos cosas. La primera, que el atributo action del formulario no tiene ningún valor asociado. En estos casos, el cliente Web asume que el destino de la página será la misma página. En segundo lugar, no hemos dado nombre al botón, entre otras cosas porque no nos interesa el nombre que tenga, sólo que realice la acción de enviar los datos. No pasa lo mismo con los cuadros de texto: precisamente queremos enviar su contenido. Cree una página HTML cuyo código sea el anterior y cárguela en su cliente Web. Introduzca algún valor en los dos cuadros de texto, haga clic en el botón Guardar y fíjese en el URL de la página que se cargará. Se tratará de la misma, no lo olvide. Ese URL puede verse en la figura 8.9.

Figura 8.9. Envío de información

¿Qué hemos logrado al hacer clic en el botón Guardar ? El cliente Web ha recogido los nombres y los valores de todos los elementos del formulario al que pertenece el botón. Luego, ha construido un URL que comienza con el destino del formulario. A continuación de ese URL ha situado un signo de interrogación para marcar el final del mismo y, tras dicho signo, el nombre de cada elemento de formulario y su valor, con un signo de igualdad entre ambos. Cada pareja está separada por un ampersand (&). Así, tras la interrogación tenemos nombre=T , que indica que el campo nombre tenía el valor T , y descripcion=Terror , que nos indica que la descripción del género es Terror . Esto es así porque hemos utilizado el método GET para enviar los valores del formulario. Si hubiésemos seleccionado el método POST no veríamos ningún valor en el URL puesto que todos se envían en los encabezados HTTP, sólo visibles por el servidor, pero con los que de igual forma podrá trabajar en sus páginas PHP. Hemos realizado esta primera prueba con una página HTML, que no nos permite trabajar con la información enviada desde un formulario. Por fortuna, con PHP podemos.

Recuperación de información
El primer paso: convertir la página anterior a PHP. Es fácil, sólo tiene que cambiar la extensión del archivo y seguirá funcionando como hasta ahora. Su nombre será genero.php. El segundo paso es añadir al principio de la página el código PHP necesario para realizar alguna operación con los valores recibidos. Pero antes, veamos dónde encontrar esos valores. En el segundo capítulo vimos una de las características que más sorprende a los que llegan a PHP desde otros lenguajes de programación: las matrices. Como vimos, en PHP podemos utilizar lo que se conoce como matrices asociativas, en las que cada elemento de la misma dispone de un nombre y un valor asociado. ¡Vaya, qué casualidad! Es justo lo que un formulario pasa a la página de destino, ¿verdad? Para facilitarle la tarea, PHP pone a su disposición dos matrices globales, disponibles en todas sus páginas, dentro de las que se encuentran todos los valores pasados desde una página a otra: $_GET y $_POST . Lógicamente, la primera de las matrices contendrá los valores pasados a la página cuando el método seleccionado sea GET , mientras que la segunda lo hará cuando el método sea POST . La forma más sencilla, más rápida, pero también la

menos elegante, de utilizar estas variables es incluir el siguiente código al comienzo de la página PHP:
<?php

echo('<pre>'); print_r($_GET); echo('</pre>');

?>

...

Cargue de nuevo la página genero.php tras añadir ese código al principio de la página. Verá algo parecido a lo que aparece en la figura 8.10, algo no demasiado agradable.

Figura 8.10. Aún no vemos nada

Y cuando introduzca valores en los cuadros de texto y haga clic en el botón Guardar , el aspecto de la página no va a mejorar, pero sí podrá ver que algo está empezando a funcionar: habrá conseguido mostrar en la página los valores del formulario, como puede verse en la figura 8.11.

Figura 8.11. Mostramos los valores pasados

Como ve, la matriz $_GET tiene un elemento por cada uno de los pasados en el URL. De igual forma, si el método empleado fuese el POST , utilizaríamos la matriz $_POST . Pero ¿qué ocurre cuando no sabe qué método se empleó para enviar la información a la página actual? La página que vamos a crear a continuación le será de mucha

utilidad, tanto ahora como en sus futuros desarrollos, para comprobar los valores que una página pasa a otra. Esta página, a la que llamaremos formulario.php, averiguará el método empleado para el paso de valores desde el formulario que la llama y mostrará una tabla con todos los valores pasados. El primer paso será aprovecharnos de una circunstancia: los valores se deben pasar con el método POST o con el método GET , pero no con los dos a la vez. Tanto $_GET como $_POST son matrices, de forma que puede saber el número de elementos que contienen. Así que podemos tener una variable que apunte a una de las dos matrices, aquella que tenga elementos, no teniendo que elegir entre trabajar con una o con otra. El código de formulario.php comienza así:
<?php

$pParametros = FALSE; if(count($_GET) != 0){ $pParametros = $_GET; }elseif(count($_POST) != 0){ $pParametros = $_POST; }

...

Con este bloque de código hemos logrado nuestro objetivo. Creamos una variable llamada $pParametros. La p viene de puntero, apuntador, un lastre de tiempos pasados que tendrá connotaciones malignas para aquellos que conozcan lenguajes como C. El valor predeterminado de esta variable será FALSE . Si no se han pasado parámetros a la página, podrá saberlo comprobando que $pParametros es FALSE . En ese caso no tendrá que mostrar ninguna información. A continuación, compruebe si $_GET contiene algún elemento. Si es así, sabrá también que $_POST no contendrá ninguno, así que haga que $pParametros apunte a $_GET . En caso contrario, $pParametros apuntará a $_POST . El resultado: sea cual sea el método empleado para el paso de los valores a esta página, $pParametros contendrá esos parámetros. Sólo queda mostrar la información pasada a la página:
...

if($pParametros == FALSE){ echo('No se ha pasado valor alguno.'); exit(); }

echo('<table border="1">');

A medida que vaya creando sus propios formularios. Figura 8. Seguirá viendo lo mismo que en la figura 8. por ejemplo. } echo('</table>').php el código que acaba de ver. echo('</tr>').$valor). Así.php.12.echo('<tr>'). printf( "<td>%s</td><td>%s</td>". salvo que ahora los valores pasados no aparecerán en el URL. echo('<th>Nombre</th><th>Valor</th>'). La página le informará de que no se le ha pasado ningún valor. Ahora ya puede emprender la tarea que era el objetivo desde que comenzó este capítulo: crear una página PHP .12.3. ya que le permitirá comprobar que una página pasa a la otra los valores que usted esperaba. ?> Guarde en una página llamada formulario. cambie el método de envío de la página HTML. aquella cuyo código se podía ver al principio del apartado 8. foreach($pParametros as $nombre => $valor){ echo('<tr>'). Abra la página HTML en un cliente Web. Recargue la página en su cliente Web. intente cargar la página formulario. Podrá ver algo parecido a lo que muestra la figura 8. asigne valores a los cuadros de texto y haga clic en Guardar . cambie el valor del atributo action por formulario. $nombre. introduzca valores en los cuadros de texto y haga clic en el botón. la página de destino será esta nueva. de get a post . esta página le será de mucha ayuda. sin llamarla desde ninguna otra. Todos los valores pasados Pruebe dos cosas más. al hacer clic en el botón Guardar . Ahora. La primera. en cualquiera de las páginas que hemos creado en este capítulo como. En segundo lugar.php directamente.12. echo('</tr>').

4. El resultado es que tendremos todos los parámetros pasados a la página en $pParametros: <?php $pParametros = FALSE.php. Vamos a utilizar una sola página. Aunque ya hemos visto su código.que le permita dar de alta nuevos géneros. if(count($_GET) != 0){ $pParametros = $_GET. Es el siguiente: <html> <head> <title>Nuevo género</title> </head> <body> <form name="frm_genero" method="get" action=""> <strong>Nombre:</strong><br> <input type="text" name="nombre"><br> <strong>Descripción:</strong><br> <input type="text" name="descripcion"><br> <input type="submit" value="Guardar"> </form> </body> </html> Como sólo vamos a utilizar una página. }elseif(count($_POST) != 0){ $pParametros = $_POST. con la misma intención que en el apartado 8. Sólo nos queda ponerlo todo junto. introduciremos las instrucciones PHP al comienzo de ella. . ya sea el método GET o POST . El primer paso consiste en crear la referencia a la matriz de valores pasados que corresponda. Inserción de registros La verdad es que casi disponemos de todos los elementos necesarios para crear una página que nos permita insertar nuevos géneros cinematográficos en la base de datos de películas: tenemos el formulario y sabemos cómo obtener los valores que necesitamos para realizar la inserción. a la que llamaremos genero. no está de más recordarlo.

Ya disponemos de todos los valores necesarios. Informar del éxito o fracaso de la operación.. } . Primero.. Lo que nos interesa ahora es ver qué código escribimos dentro del bloque if.. } . En la página formulario.'. if(($sNombre == '') or ($sDescripcion == '')){ $sMensaje = 'El nombre y la descripción '. puesto que ese será el que realizará la inserción en la base de datos. Es en la parte del else en la que realizaremos la inserción en la base de datos.. así que vamos a ello. $sNombre = $pParametros['nombre']. pero ahora nos interesa hacer justo lo contrario. Obtener los valores que necesitamos y comprobar que son válidos. Por lo tanto. El primer paso es bien simple: .php.. 'del nuevo género no pueden '. Debemos llevar a cabo tres tareas: 1. el siguiente paso era comprobar si $pParametros era FALSE . Realizar la inserción en la base de datos.. }else{ .. if($pParametros != FALSE){ . echo($sMensaje). sólo realizaremos alguna acción si se pasó algún parámetro a la página: . creamos la consulta: ..} ... $sDescripcion = $pParametros['descripcion']. 2.... 3.. 'ser cadenas vacías.

en la que se comentan algunos aspectos de la configuración de las aplicaciones PHP. ''. Not a: Si le parece raro cómo realizamos la conexión con la base de datos. } echo('Nuevo género añadido. 'videoteca'). ¿verdad? A continuación puede ver el código completo de está página. el del usuario y su clave en los archivos de configuración de Apache. . . if(count($_GET) != 0){ $pParametros = $_GET. $videoteca->close()... quizá necesite echar un vistazo al apartado 7. ejecutar la consulta y cerrar la conexión: .... descripcion )VALUES( '$sNombre'.. $videoteca = new mysqli( ''. exit(). if($resultado == FALSE){ echo('Error en la consulta. exit(). CONSULTA.').. ''. echo($videoteca->error).6 del capítulo 7. Ahora sólo tenemos que establecer la conexión con la base de datos... '$sDescripcion' ). En concreto. }elseif(count($_POST) != 0){ . HTML incluido: <?php $pParametros = FALSE. cómo incluir el nombre del servidor MySQL. $sConsulta = <<<CONSULTA INSERT INTO genero( nombre. Nada más sencillo. if ($videoteca == FALSE){ echo('Error en la conexión.<hr/>'. } $resultado = $videoteca->query($sConsulta).').

'$sDescripcion' ). $videoteca->close(). } $resultado = $videoteca->query($sConsulta). } echo('Nuevo género añadido. } if($pParametros != FALSE){ $sNombre = $pParametros['nombre'].'). }else{ $sConsulta = <<<CONSULTA INSERT INTO genero( nombre. CONSULTA. if(($sNombre == '') or ($sDescripcion == '')){ $sMensaje = 'El nombre y la descripción '.<hr/>'). exit(). exit(). if ($videoteca == FALSE){ echo('Error en la conexión. descripcion )VALUES( '$sNombre'. 'videoteca'). echo($sMensaje). 'ser cadenas vacías.'). 'del nuevo género no pueden '. ''. ''. if($resultado == FALSE){ echo('Error en la consulta. $videoteca = new mysqli( ''.$pParametros = $_POST. } } ?> . $sDescripcion = $pParametros['descripcion']. echo($videoteca->error).'.

podrá comprobar que dispone de un género más: el que acaba de añadir gracias a nuestro formulario.<html> <head> <title>Nuevo género</title> </head> <body> <form name="frm_genero" method="get" action=""> <strong>Nombre:</strong><br> <input type="text" name="nombre"><br> <strong>Descripción:</strong><br> <input type="text" name="descripcion"><br> <input type="submit" value="Guardar"> </form> </body> </html> La figura 8. Pruebe a cargarla ahora. Nuevo género añadido En el capítulo anterior creamos una página que nos permitía ver la lista de géneros disponibles en nuestra base de datos.13 muestra el aspecto de esta página tras añadir una nueva categoría a la base de datos. Puede mejorar el funcionamiento de sus formularios añadiendo un nivel más de control. además de en el lado del servidor. que los valores que se van a enviar cumplen los criterios que necesita.13. En el URL se pueden ver los parámetros que se han pasado a la página. Figura 8. . verificando en el lado del cliente.

var sDescripcion = frm.descripcion. ¿qué nos interesa hacer con la página para dar de alta nuevos géneros? Comprobar. el formulario que contiene los valores que queremos comprobar.select(). } return(true). la variable frm es una referencia a document. Su sintaxis es muy similar a la de PHP (¿o deberíamos decir lo contrario?). al que asignamos el nombre frm_genero. frm.'). antes de enviar nada al servidor. lo normal es guardarlo en archivos independientes de la propia página. En primer lugar. Desde JavaScript dispone de una jerarquía de clases que le permite acceder a cualquier elemento o atributo de la página. } if(sDescripcion == ''){ alert('Falta la descripción. La siguiente función realiza la tarea que nos interesa: function comprobar_valores(){ var frm = document. Aunque puede incluir el código JavaScript en el mismo archivo PHP o HTML. return(false).select(). var sNombre = frm. En concreto. así que podremos acceder a él .frm_genero. PHP y SQL. } Antes de ver cómo insertar este código en su página. vamos a por otro lenguaje más: JavaScript. que se han introducido tanto un nombre como una descripción para el género. De esta forma evitaremos más de una llamada errónea a la página. ajustándose a los parámetros que usted decida.value. Dentro de él está nuestro formulario.nombre. El elemento que comienza la jerarquía es document y representa a la página Web. frm. Como puede que a alguien le parezca poco. veamos qué hace.nombre.value.Control en el lado del cliente Este libro es como una torre de Babel: hasta ahora hablamos HTML.frm_genero. Ahora mismo sólo nos interesan los formularios y los valores de sus elementos.'). return(false). if(sNombre == ''){ alert('Falta el nombre.descripcion. JavaScript es un lenguaje que permite comprobar que los valores que los clientes intentan enviar en los formularios son correctos.

Lo guardamos en sendas variables..js"> <!---> </script> </head> <body> <form name="frm_genero" method="get" action=""> <strong>Nombre:</strong><br> <input type="text" name="nombre"><br> <strong>Descripción:</strong><br> <input type="text" name="descripcion"><br> <input type="submit" value="Guardar"> .descripcion el cuadro de texto para la descripción.frm_genero. De igual forma. de forma que la parte HTML de la página genero.nombre será el cuadro de texto para el nombre.js"> <!---> </script> . <script language="javascript" src="genero. mostramos un mensaje al respecto y seleccionamos el cuadro de texto que corresponda. De ambos cuadros de texto nos interesa su valor.. accedemos a los elementos del formulario por su nombre: frm. Si una de ellas está vacía. Posteriormente comprobamos que no estén vacías. ¿cómo asociamos este código a la página PHP? Con una sencilla línea: .. Esta instrucción debe ir antes del fin la etiqueta <head>.php debe quedar así: <html> <head> <title>Nuevo género</title> <script language="javascript" src="genero. comparando su valor con una cadena vacía. y frm. Ahora..mediante document.

.. Durante este capítulo ha visto una colección de diferentes tecnologías trabajando juntas para conseguir el mismo resultado: que desde una página Web. El mayor esfuerzo debe ponerse en asegurar que la información que el cliente envía cumpla los criterios que buscamos. Figura 8. Si todos los valores necesarios han sido introducidos. pero . el cliente Web llamará a la función.</form> </body> </html> Ahora sólo tenemos que asociar la función comprobar_valores() al botón Guardar .. Sin descripción. el envío del formulario se cancela. para que cuando se haga clic en dicho botón el cliente Web intente ejecutarla. como la función devuelve false. <input type="submit" value="Guardar" onClick="return comprobar_valores()"> .14 muestra lo que ocurriría si intentásemos crear un nuevo género sin descripción asociada. que se lanza cada vez que se hace clic sobre dicho botón. La figura 8. El código de la etiqueta del botón sería el siguiente: . el formulario se enviará a la página de destino. no hay género Truco: ¿Quiere acceder y manipular aún más fácilmente los elementos de los formularios desde el código JavaScript? Eche un vistazo a jQuery: http://jquery. En ese caso. Pero si no se cumple algún requisito. La existencia del campo es el primer paso. Cada vez que se haga clic.. Para ello utilizamos el evento onClick del botón. la función devolverá true. un usuario pueda modificar valores de una base de datos.14.com/.

buscamos. un valor numérico o una dirección de correo electrónico con el formato correcto. La existencia del campo es el primer paso. . Si pide al cliente que introduzca una fecha. respectivamente. pero no el único. un precio o una dirección de correo electrónico en algún campo del formulario habrá de comprobar que se trata de una fecha razonable.

el problema no está en que ocurra un error en una de sus páginas sino en no saber tratarlo adecuadamente. . bajo cualquier circunstancia. a veces. no lo es del todo. Pero como hemos dicho. Y aprenderá a utilizar de forma conjunta la gestión de errores de PHP y MySQL para sacarles el mayor partido. las páginas PHP que hagamos deben devolver información de las bases de datos: por ejemplo. Y. aunque es cierto. cuando logramos que un programa se comporte de la forma esperada. en nuestro caso. PHP y los errores Incluso antes de saber nada sobre la gestión de errores de PHP ya nos estamos aprovechando de ella. Los programadores tendemos a pensar que.1. MySQL también proporciona medios para informar sobre los errores que se produzcan y profundizar en las causas de los mismos. a veces. Un programa sólo puede darse por bueno cuando su comportamiento es el adecuado. También verá cómo MySQL informa de los errores que ocurren. Las herramientas que proporciona PHP para la gestión de errores son muchas y muy variadas. Porque. nuestro trabajo está hecho. Concretando. las tareas más importantes son relegadas a un segundo plano.9 Gestión de errores Es curioso como. ¿Recuerda cómo terminamos el capítulo 7? El comportamiento de la página que mostraba la lista de los géneros disponibles fallaba miserablemente cuando el servidor de bases de datos no estaba funcionando. Aquellos que intentasen consultar el listado en ese momento se encontrarían con algo parecido a lo que se puede ver en la figura 9. De igual forma. bueno. una lista de registros. así como cuando la consulta que se esté intentando ejecutar no sea correcta tanto porque los elementos involucrados en ella no existan como porque esté mal construida. la página debe comportarse adecuadamente bajo cualquier circunstancia: cuando el servidor de bases de datos no esté funcionando debe avisar de ello. Durante este capítulo verá cómo configurar PHP para que su comportamiento frente a los errores sea el que usted desee.

tal y como nos la muestra la función antes mencionada. pero ahora nos vamos a fijar en otros valores. mientras que la tercera (Master Value) determina el valor global de esa opción. Figura 9. La primera (Directive) es el nombre de la opción de configuración. La segunda (Local Value) es el valor de esa opción de configuración para la zona de la Web en la que se encuentra la página. La figura 9.2. En ese capítulo consultábamos los parámetros de configuración de PHP con una página en la que llamábamos a la función phpinfo(). sólo indicando la base de datos predeterminada. No hay servidor de bases de datos ¿Qué determina la forma en la que se presentan estos mensajes de error? La configuración de PHP.1. Configuración para los errores Como puede ver. Not a: Recuerde del séptimo capítulo que puede tener una configuración .Figura 9. el que se aplica por defecto a todas las zonas de Web. En su apartado 7.2 muestra los valores que más nos interesan de la sección PHP Core de la configuración de PHP. existen tres columnas.6 explicábamos cómo modificar la configuración de PHP para que pudiésemos conectar con el servidor de bases de datos sin especificar ni su nombre. Vamos a repetir la jugada. Configuración Situémonos de nuevo en el capítulo 7. ni el nombre del usuario ni su contraseña.

2 se puede observar que estos mensajes están activos.3..6. Not a: La ruta de la carpeta en el fragmento de configuración de Apache. Veamos el impacto que desactivar esta opción tiene sobre los mensajes de error. En concreto. Cree una carpeta llamada errores dentro de esa carpeta y. como pretendíamos. En la figura 9. Figura 9. algo que puede verse en la figura 9..deny Allow from all php_admin_value display_errors "0" </Directory> . Tras reiniciar el servidor Apache.1. Más detalles al respecto en el apartado 7. Suponga que está trabajando en la ruta predeterminada de Apache. la carpeta htdocs. Son estos valores los que determinan cómo se comportarán nuestras aplicaciones en caso de que ocurra un error. deberá añadir las siguientes líneas al archivo de configuración de Apache: . Dependiendo de la ubicación de la página PHP dentro del árbol de directorios del servidor se aplicará una configuración u otra. Ahora vamos a editar el archivo de configuración de Apache para que pueda modificar los valores de configuración de PHP de esa carpeta.5.1? Si intenta cargarla cuando ..3. display_errors Dependiendo del valor de esta variable. ponga un archivo PHP que llame a la función phpinfo(). se corresponde con un sistema Windows. Veamos para qué sirve cada uno de ellos. los errores que se provoquen en nuestras páginas producirán mensajes o no. como ya hicimos en el capítulo 7. como es obvio. dentro de ella. si carga la página que muestra las opciones de configuración de PHP podrá comprobar que ahora el valor local de display_errors es Off. <Directory "C:/xampp/htdocs/errores"> Options Indexes FollowSymlinks AllowOverride None Order allow. Desactivamos display_errors ¿Qué efecto tendrá este cambio en la página que pudimos ver en la figura 9.diferente para algunas de las carpetas del servidor de páginas Web que utilice. como pudo comprobar en la figura 9..

Pero. $fila[0].MySQL esté detenido podrá ver algo similar a lo que muestra la figura 9. si ha fallado la conexión. ¡un momento! Aquí hay algo que no cuadra. $fila[1]."? Algo no es del todo correcto.4. print_r($resultado->fetch_field()).'). 'clave'.'). if ($videoteca->errno != 0){ echo('Error en la conexión. $videoteca->close().4. Controlamos los mensajes de error La conclusión: durante el proceso de desarrollo. 'usuario'. esta opción de configuración debe estar activada. exit(). el código de esta página era el siguiente: <?php $videoteca = new mysqli( 'localhost'. mientras que durante su vida útil debe desactivarla y ser usted quien controle los mensajes de error. $fila[2] ). } while ($fila = $resultado->fetch_row()){ printf( "(%u) %s . } $resultado->close(). } $resultado = $videoteca->query( 'SELECT * FROM genero' ). 'videoteca' ). en el que esté probando el funcionamiento de sus páginas. . Figura 9. el mensaje de error que vemos es "Error en la consulta. Si recuerda.%s<br/>". ¿Cómo es que. if ($resultado == FALSE){ echo('Error en la consulta.

Estos errores no serán visibles a menos que el valor de esta opción de configuración sea On.?> ¿Por qué no se informa de un error en la conexión? Porque. En dicha página aparece. además. durante el proceso de carga de PHP en memoria. la instrucción new mysqli no ha logrado crear un ejemplar de la clase mysqli y. ?> . if (mysqli_connect_errno()){ echo('Error en la conexión. un enlace a la documentación de PHP donde se describe la forma de utilizar la función en la que se produjo el fallo. cuando se produce un error al llamar a una función PHP muestra un mensaje de error al respecto sólo si la opción display_errors está activa.. Lo correcto es utilizar una función para comprobar si hubo errores durante el proceso de conexión: .'). Con el servidor MySQL detenido y display_errors activa. Ahora sí. docref_ext y docref_root Como hemos visto.. } . como demuestra la figura 9. ahora que hemos modificado la comprobación de los errores de conexión podrá ver que sí obtiene la información correcta. Si prueba a cargar esta página.. se produzca algún error. Vamos a provocar un error. $videoteca->errno no contiene información alguna del código de error.5. por lo tanto.. al no llegar a realizarse. Figura 9. error en la conexión display_startup_errors No sólo se producen errores al cargar una página.5. exit(). cree una página con el siguiente código y ábrala: <?php $videoteca = mysqli_connect(). Es posible que.

net/manual/es/" . . Sin embargo..6. En él puede ver que dicho enlace apunta al servidor local..Y se produce un error como el que muestra la figura 9. el enlace será el que se puede ver en la figura 9. si hace clic sobre ese enlace no encontrará ayuda alguna porque esa página no existe.6.7.. Error en la conexión Las opciones de configuración docref_ext y docref_root permiten modificar la forma en la que se crean estos enlaces. php_admin_value docref_ext ". Ahora.6. Reinicie el servidor Web y vuelva a cargar la página de la figura 9. Figura 9.php" php_admin_value docref_root "http://php. El primero de ellos determina la extensión de las páginas a las que apuntan mientras que el segundo la ubicación de las mismas.. El cuadro de diálogo que acompaña a la figura es el resultante de hacer clic con el botón derecho sobre el enlace y seleccionar la opción Propiedades del menú desplegable que aparece. Añadamos dos líneas a la configuración de la carpeta errores en Apache: .

E_PARSE: En nuestro código hay algo que no sigue las reglas sintácticas de PHP. De lo contrario no podrá acceder a esta documentación. . Enlaces a la documentación Si hace clic sobre dicho enlace verá la documentación de la función mysqli_connect(). No se detiene la ejecución del programa. Las posibles constantes que se pueden combinar para asignar un valor a esta opción de configuración son las siguientes: E_ERROR: Errores fatales.7. Si lo desea. Contiene un valor numérico que determina el nivel de detalle de los mensajes de error. dichas cadenas aparecerán antes y después del mensaje de error. respectivamente. Deberá modificar la configuración de PHP adecuadamente. error_reporting Quizás una de las más importantes de las opciones de configuración relacionadas con la gestión de errores. Se detiene la ejecución del programa.Figura 9. A partir de ese momento. y en español. puede instalar la documentación en su propio servidor para poder consultarla en cualquier momento. Truco: Para aprovechar al máximo estas opciones de configuración es necesario que disponga de conexión a Internet mientras trabaja. E_WARNING: Errores no fatales. error_prepend_string y error_append_string Asocie una cadena de texto a estas opciones de configuración.

Le recomendamos que cambie ese valor por E_ALL & E_STRICT . Formato HTML desactivado La dirección de la página de la documentación describiendo la función en la que se produjo el error sigue estando ahí pero ya no como un enlace. está fuera del alcance de este libro. ignore_repeated_source . con lo que PHP le ayudará en sus programas todo lo que pueda. html_errors Sólo si esta opción de configuración está activa podrá ver los mensajes de error con formato HTML. ignore_repeated_errors Si activa esta opción y un mensaje de error se produce de forma consecutiva en varias ocasiones en la misma página PHP no se informará de él más que la primera vez.8. E_STRICT: Consejos dados por PHP acerca de cómo mejorar el código que escribimos.8. con enlaces a la documentación de PHP cuando sea necesario. está fuera del alcance de este libro. Figura 9. el valor de esta opción de configuración es E_ALL & ~E_NOTICE. E_CORE_ERROR: Error fatal ocurrido durante la carga de PHP en memoria. E_USER_WARNING: Advertencia generada por el programador mediante el uso de la función trigger_error(). E_RECOVERABLE_ERROR: Error fatal que quizá no dejó en un estado inutilizable al motor de PHP. salvo E_STRICT antes de la versión 5.4.0 de PHP. A partir de esa versión. E_ALL incluye a E_STRICT . E_USER_NOTICE: Aviso generado por el programador mediante el uso de la función trigger_error(). E_COMPILE_WARNING: Relacionado con Zend Script Engine. E_CORE_WARNING: Error no fatal ocurrido durante la carga de PHP en memoria. E_USER_ERROR: Error generado por el programador mediante el uso de la función trigger_error(). E_COMPILE_ERROR: Relacionado con Zend Script Engine. E_ALL: Todos los errores.E_NOTICE: Avisos sobre posibles fallos en nuestro código. Si está desactivada. los mensajes de error tendrán el aspecto que puede ver en la figura 9. Consejo: Por defecto.

podrá modificar el valor de error_log. Funciones PHP es. Si en lugar de la ruta de acceso a un archivo indica el valor syslog. Tras conocer las posibles opciones de configuración relacionadas con la gestión de errores. posiblemente. no se informará de él más que la primera vez. track_errors Si esta opción de configuración está activa. siempre podrá acceder en sus programas a la información del último error que se produjo a través de la variable $php_errormsg. los mensajes de error se guardarán en el log del sistema. error_log() Permite enviar un mensaje de error a cuatro destinos diferentes: al sistema de registro de PHP (ver sección dedicada a log_errors y error_log). Esta variable sólo contiene la descripción del error. log_errors_max_len Tamaño máximo de los mensajes que se almacenará en el registro de errores. report_memleaks Si en sus programas se produce algún problema relacionado con la gestión de memoria y esta opción de configuración está activa. nos centraremos en las más importantes. log_errors y error_log Si log_errors está activo. Existe un valor especial para esta opción de configuración.Si activa esta opción y un mensaje de error se produce de forma consecutiva en varias ocasiones. Si no se indica ningún valor no habrá límites de tamaño. a una dirección de . Es imprescindible que indique un archivo de este tipo una vez sus aplicaciones estén en funcionamiento para poder estudiar su comportamiento y localizar la causa de posibles errores. que en Windows es el registro de eventos (accesible a través del visor de eventos) y en Linux y Mac OS X es syslog. PHP informará de dicho problema. uno de los lenguajes de su clase que proporciona las funciones de gestión de errores más sencillas y útiles. sin importar si se produjo en la misma página o en otra. No son sólo las que vamos a ver. Este último le permite seleccionar un archivo en el que se guardará un registro de todos los errores que sus páginas PHP vayan mostrando. veamos qué funciones pone PHP a su disposición para gestionarlos.

". } . if (mysqli_connect_errno()){ echo('Error en la conexión. "From: Servidor en producción\n" ). Suponga también que. en caso de que esta página se intentase cargar tras enviar información con un formulario.. en este orden: el mensaje de error. aquel que le encargó su desarrollo.correo electrónico. Esta función acepta cuatro argumentos. las variables pasadas a la página. No se engañe: las aplicaciones pueden fallar. se le enviase un mensaje de error a su dirección de correo electrónico? Antes incluso de que el cliente le llamase por teléfono para. 1. Suponga que..com". por último. o cualquier otro detalle que pueda ayudarle a resolver el problema que provocó que se le enviase el mensaje de correo electrónico. por ejemplo. la lista de géneros. ¡y por correo electrónico! Volvamos a nuestro ejemplo. por cientos de razones diferentes. sería muy interesante incluir otra en el cuerpo del mensaje como.. instalada y funcionando en los sistemas de su cliente.. no se ha podido establecer una conexión con la base de datos. Truco: Además de esta información.'). usted tendría constancia de ello. ¿No sería fantástico que. decirle que lo que ha programado no sirve para nada. A veces. cuando algún fallo ocurriera en las aplicaciones que ha desarrollado. información asociada al tipo de destino. error_log( "No se pudo conectar con MySQL. el tipo de destino (cualquiera de los cuatro antes mencionados). incluso no es por su culpa. a un depurador de errores remoto o a un archivo (al final del cual se añade el mensaje). en lugar del código que informa sobre el error en la conexión. con el remitente Servidor en producción.com. efectivamente. tiene este otro: . "Subject: Error en la videoteca\n". "videoteca@example. el destino propiamente dicho y. continuamente conectada a Internet. indignado. Suponga que su aplicación está terminada. exit(). para que sepa de qué servidor le llega el mensaje. en caso de que sea necesario. Cada vez que se produzca un error al conectar con la base de datos le llegará un mensaje de correo electrónico a la dirección videoteca@example. y con el asunto describiendo qué es lo que ha pasado. . Se trata de una aplicación Web.

. echo($sMensaje).. . es decir. del que acabamos de hablar. 'ser cadenas vacías. trigger_error($sMensaje. Utilizar esta función modifica el parámetro de configuración error_reporting. Podríamos cambiar la llamada a la función echo() por una llamada a la función trigger_error(): ... $sDescripcion = pParametros['descripcion'].. 'del nuevo género no pueden '.'. E_USER_ERROR). desde el mismo código de una página. trigger_error() Utilice esta función cuando ocurra alguna circunstancia que PHP no entienda como error pero que usted desea que se trate como tal. mostraba un mensaje: . 'del nuevo género no pueden '. Cuando esta página no recibía el nombre del género o su descripción...error_reporting() Esta función permite modificar en tiempo de ejecución. }else{ .'. Por ejemplo. el nivel de detalle con el que se informará de los errores.. if($pParam != FALSE){ $sNombre = pParametros['nombre'].. 'ser cadenas vacías. if( ($sNombre == '') or ($sDescripcion == '') ){ $sMensaje = 'El nombre y la descripción '. recuerde el capítulo anterior. la página PHP que le permitía dar de alta nuevos géneros cinematográficos. $sMensaje = 'El nombre y la descripción '.

printf("<b>Archivo:</b> %s. 2. printf("<b>Descripción:</b> %s. La siguiente es una versión minimalista de una función de gestión de errores: function informar_error( $codigo.<br/>". $archivo). $archivo. . $linea). $codigo).El resultado.<br/>"). La descripción del error. printf("<b>Línea:</b> $s. puede solucionarlo ya que existe la posibilidad de que cree su propia rutina de gestión errores. set_error_handler() ¿No le gusta la información que PHP sobre los errores? No se preocupe. "videoteca@example. $linea ){ printf("Ha ocurrido un error. 3. como puede ver en la figura 9. en lugar de un simple mensaje. 4.<br/>". Si desea más información al respecto consulte la documentación de PHP. viene adornado como un mensaje de error de los que ya conocemos. 1. en este orden.<br/>". La línea en la que se produjo el error.". error_log( "Error. Error definido por el usuario Pero cuando quizá resulta más interesante informar sobre errores de este tipo es cuando definimos nuestras propias funciones para gestionarlos.9. representan: 1. La función de gestión de errores sólo tiene que ser capaz de recibir cuatro parámetros que. $descripcion). $descripcion.<br/>". El archivo PHP en el que se produjo el error. Not a: Existe un quinto argumento que puede utilizarse en este tipo de funciones pero su significado queda fuera del alcance de esta guía.9. El código del error. Figura 9. printf("<b>Código:</b> %s.com".

se envía un mensaje de correo electrónico con información al respecto: así que nos evitamos tener que añadir esa línea tras cada error que se produzca.10. Nosotros informamos del error Not a: Por otra parte. La variable $gestor_anterior contendrá lo necesario para poder restaurar el anterior gestor de errores cuando lo consideremos oportuno utilizando la función que veremos a continuación. además de informar sobre el error de forma diferente.. restore_error_handler ... "From: Servidor en producción\n" ). utilizar las instrucciones de inclusión que vimos durante el capítulo 4 y hacer la siguiente llamada al comienzo de la página: . En el ejemplo del apartado anterior se trataría de la variable $gestor_anterior. La única ventaja que nuestra función aporta sobre la predeterminada de PHP es que. } Si quiere que esta función informe sobre los errores que ocurran en sus páginas sólo tiene que colocarla en un lugar al que todas ellas tengan acceso. La figura 9. $gestor_anterior = set_error_handler("informar_error"). visualmente hablando."Subject: ". Excepciones La gestión de errores que hemos realizado hasta ahora es la más utilizada.10 muestra el aspecto de los mensajes de error utilizando nuestra función.$descripcion. Figura 9. Queda como ejercicio para el lector mejorarla. restore_error_handler() Llamando a esta función restauramos la función de gestión de errores que pasemos como parámetro. el resultado de utilizar esta función para informar sobre los errores es mucho más pobre."\n". .. podríamos hasta decir que es la .

. el código.. La principal ventana de utilizar bloques try y catch es que el código resultante está mucho más estructurado. el cliente de MySQL que utilice (como. MySQL y los errores Cada vez que ejecuta una consulta cuya sintaxis no es correcta o sobre unos datos inexistentes. El primero paso para utilizar excepciones consiste en localizar aquellos fragmentos de código susceptibles de fallo. Entre paréntesis.. catch (Exception $e) { echo 'Error: ' . que si no se utilizasen. por ejemplo. un objeto de tipo Exception que contiene toda la información que necesite mostrar para informar sobre el error como. La gestión de la posible excepción (es decir. Pero ¿qué podría hacer si le interesase conocer lo ocurrido hace unos días en un servidor de bases de datos MySQL? Para esos casos. $resultado = $videoteca->query( 'SELECT * FROM genero' ). try{ $resultado = $videoteca->query( 'SELECT * FROM genero' ). $e->getMessage() .clásica... '<br/>'... PHP ofrece la posibilidad de gestionarlos utilizando excepciones. } .. MySQL Query Browser o MySQLi) le informará sobre dichos errores. más organizado.. . Para controlar las excepciones que pudiesen tener lugar sólo es necesario incluir el código en cuestión en un bloque try: .. Un buen candidato podría ser el momento de realizar una consulta en una base de datos: .. del error) tiene lugar en el bloque catch definido a continuación del bloque try: . } . MySQL proporciona gran cantidad de datos en . por ejemplo. la línea o el archivo en el que tuvo lugar el error. igual que muchos otros lenguajes modernos.. Sin embargo.

Existen otros archivos de registro de los que no se hablará porque no le serán útiles por el momento. le hará falta incluir información que aparezca en estos archivos. Todas las conexiones que se establezcan con MySQL y las posteriores consultas quedan registradas aquí. dependiendo de si el servidor está instalado en Windows. además de durante su funcionamiento. 3. MySQL mantiene registros de su actividad en diferentes archivos: 1. El registro de consultas: O registro general. Esta ruta dependerá de cómo y dónde haya instalado MySQL. 2. El registro lento: Almacena información sobre aquellas consultas que tardan mucho tiempo en completarse. Linux o Mac OS X. El registro de errores será el que más utilice cuando comience a trabajar con MySQL. Puede encontrar más información sobre ellos en la documentación de MySQL. aunque también puede ser mysql. 4. La ubicación de este archivo variará. El nombre del archivo se compone del nombre del ordenador con la extensión err (linux. examine los archivos de registro. También registra las paradas y arranques del servicio. para localizar problemas en caso de que los tenga. El buscador de mensajes en los grupos de noticias http://groups. o aquellas que no utilizan índices. Not a: Si tiene algún problema utilizando MySQL y necesita buscar ayuda sobre el mismo. pero ¿y si le interesa saber qué pasó hace unos días? Para esos casos.com/ puede serle útil.err . Archivos de registro Las capacidades de administración de MySQL Administrator son suficientes si quiere saber qué esta pasando en el servidor en un preciso instante. se tratará de la carpeta data. A veces no bastará con la descripción del problema. El registro binario: Aquellas instrucciones que realicen algún cambio quedan registradas en este archivo. El registro de errores: Guarda información sobre los errores aparecidos durante el proceso de arranque o de parada de MySQL. Por lo general.err si el nombre del equipo fuese linux). MySQL proporciona gran cantidad de datos en sus archivos de registro (log en inglés). dentro de la ruta de instalación de MySQL. Examinar este archivo puede ayudarle a determinar por qué el servidor no se pone en marcha.sus archivos de registro (log en inglés). La ubicación del archivo de registro de errores se puede cambiar si le pasa al servidor el siguiente parámetro al arrancar: --log-error [= ruta] .google.

La figura 9.Fíjese en que la ruta del archivo es opcional. Éste se diferencia del resto en que no es posible su examen directo. el mensaje. al contrario que los dos anteriores.12 muestra el resultado de intentar leer directamente el contenido de un archivo de registro binario . dentro de la carpeta en la que MySQL esté instalado. El tercer archivo de registro que puede resultarle interesante es el binario. por ejemplo durante la conexión de algún programa con el servidor de bases de datos. Contenido del registro de errores Cada línea del archivo de registro comienza con un número de seis dígitos que representa la fecha con el formato AAMMDD (año. Para activar este archivo de registro pase el siguiente parámetro al servidor durante el arranque: --log-bin [= ruta] Para examinar un archivo de registro binario debe hacer uso de la utilidad mysqlbinlog. le pasa al servidor el parámetro: --log [= ruta] Este archivo de registro es especialmente útil si conoce la existencia de algún problema. La figura 9.11 muestra el contenido típico del archivo de registro de errores de un servidor MySQL instalado en Mac OS X. Para que le muestre el contenido de un archivo de registro binario debe pasarle su ruta como argumento. mes y día). Figura 9. con un editor de texto. por último. Si pasa el parámetro sin ella estará indicando que quiere activar el registro de errores pero deja la decisión del nombre del archivo a MySQL. que se encuentra en la carpeta bin. pero no dispone de suficiente información para solucionarlo. puede seleccionar su ubicación si.exe. A continuación la hora en la que se produjo en mensaje y. en el momento de arrancar. En cuanto al registro de consultas.11.

Además de suponer un posible problema para el mismo servidor. Figura 9. estas tablas no se están utilizando. Tras el repaso a los archivos de registro que hicimos en el apartado anterior. como si estuviese ejecutando instrucciones SQL: FLUSH LOGS. en lugar de en archivos. así que estarán vacías.13. Archivos de registro en tablas MySQL permite guardar las entradas del registro en tablas. Figura 9. la más evidente salta a la vista: resulta mucho más sencillo buscar información en la tabla de una base de datos que en un archivo de texto.12. el tamaño de los archivos de registro puede llegar a ser excesivo. Se trata de algo muy interesante por varias razones.exe. Ya dispone de dos tablas de registro en su servidor MySQL. Los archivos de registro binario utilizan una extensión compuesta de varios dígitos: mayor número. Los datos de cada línea del archivo de registro se desgajan. como puede ver en la figura 9. vacías . su tarea como administrador se verá dificultada: trabajar con archivos demasiado extensos puede ser un problema. Puede obligar a MySQL a crear nuevos archivos de registro utilizando la siguiente instrucción. que puede quedarse sin espacio en disco. archivo más reciente. dentro de la base de datos mysql: general_log y slow_log. Archivo de registro binario Si el número de operaciones realizadas en su servidor de bases de datos es muy grande. yendo cada uno a una columna de la tabla correspondiente.13. Por defecto. Tablas de registro.recién creado. en lugar de leerlo utilizando mysqlbinlog. por lo que pueda pasar. Not a: Le recomendamos que realice esta operación de forma periódica y haga una copia de seguridad de los archivos de registro.

TABLE o NONE . Para ello ejecute la siguiente consulta: SHOW VARIABLES LIKE 'log_output'. En la tabla slow_log se guardan las entradas del registro lento. esta información se puede guardar simultáneamente en archivos y tablas utilizando el parámetro --log-output=FILE. en archivos o en tablas.TABLE . o registro general.15. ahora en tablas Aunque hayamos configurado MySQL para que guarde el registro en tablas. que se pasa como parámetro durante el arranque del servidor (--logoutput ). La figura 9. Ahora bien. Antes de nada tenemos que saber dónde guarda MySQL los datos de registro. El tercero desactiva la generación de información de registro. Registro en archivos La opción de configuración log_output . El valor de la opción de configuración cambiará y MySQL la tendrá en cuenta de inmediato. En la figura 9. Si lo desea. El registro. Pero.15 puede ver cómo hemos cambiado el valor de esta opción y la posterior consulta que demuestra que el cambio ha tenido lugar. Con el primero (--log-output=FILE ) se utilizarán archivos para el registro. Figura 9. es posible activarlos utilizando la misma técnica que acaba de ver. nos basta con utilizar la siguiente sentencia: SET GLOBAL log_output='TABLE'.La tabla general_log se utiliza para guardar las entradas del registro de consultas. mientras que con el segundo se utilizarán tablas. Así que comencemos comprobando si el registro general está activo: . estos registros se activan a través de parámetros de inicio de MySQL. no es necesario reiniciar el servidor para empezar a utilizar el registro en tablas. como ya sospecha.14 muestra el resultado de realizar esta operación en un servidor MySQL con la configuración por defecto: la información de registro se guarda en archivos. Como vimos anteriormente. Figura 9.14. puede tomar tres valores: FILE . recordemos que sólo dos de ellos se ven afectados: el general y lento.

Figura 9.SHOW VARIABLES LIKE 'general_log'. La figura 9.17. realizamos la consulta de los datos de la tabla en cuestión. Activación del registro general A partir de este momento. muestra. Para comprobarlo. precisamente. Si el valor de esta opción de configuración es OFF significará que está desactivado.16 muestra el resultado de llevar a cabo estas dos operaciones. Utilice la siguiente sentencia para activarlo: SET GLOBAL general_log='ON'. Contenido de la tabla de registro Cada registro tiene 6 columnas: event_time: ¿Cuándo tuvo lugar el evento registrado? . en la 10. con el registro en tablas activo y el registro general en funcionamiento. las consultas que hemos estado realizando: en la fila 7 pedimos que se nos mostrase el valor de la variable general_log. en la figura 9.17. en la 8 seleccionamos la base de datos que aparece en la fila 9 (mysql) y. la tabla general_log comenzará a recibir datos de MySQL. realice la siguiente consulta: USE mysql. Figura 9. SELECT * FROM general_log\G El resultado.16.

por citar sólo algunos ejemplos. además. filtrando los registros por servidor. por defecto. Puede comprobarlo si intenta conectarse con el servidor de MySQL proporcionando una contraseña incorrecta o ejecutando una consulta de selección sin especificar una base de datos. command_type: Tipo de orden. Figura 9. Configure los servidores a su cargo para que guarden sus registros en las tablas de uno de ellos. la figura 9. En el caso de una consulta será la consulta en sí. ya sabe dónde encontrar la descripción del mismo. Si se produce un error. server_id: Identificador del servidor. sólo tiene que utilizar un parámetro en el arranque del servidor: --language=spanish Para pasar dicho parámetro durante el inicio del servicio debe recordar lo aprendido durante el capítulo dedicado a la administración de MySQL. En concreto. ¿No le gustaría. La figura 9. Al guardar la información de registro en tablas resulta sencillo obtener la lista de operaciones realizadas a lo largo de un día.user_host: ¿Quién generó el evento en cuestión? thread_id: Identificador del subproceso.19 muestra el aspecto de las propiedades del servicio al incluir dicho parámetro. poder entender esos mensajes de error.18 es una buena muestra de ello. una consulta (Query) o la selección de una base de datos (Init DB). Por ejemplo. . o la lista de todas las consultas. Así sólo tendrá que consultar esa tabla. Mensaje de error en inglés Para cambiarlo. argument: Parámetros pasados a la orden. o desde cierto equipo conocida su IP. en caso de que no sepa inglés? Idioma de los errores En este apartado describiremos la solución a un problema que seguramente habrá notado desde que comenzó a trabajar con MySQL: los mensajes de error no aparecen. Una de las ventajas de mantener los registros en tablas es que podemos guardar información de diferentes servidores en la misma ubicación. Otra ventaja: podríamos utilizar desencadenadores para que MySQL realizase ciertas tareas en caso de que se insertasen ciertos valores en la tabla de registro. en español.18. por ejemplo.

Gracias a ello le será más sencillo responder a estos errores en sus programas de forma sistemática en caso de que se produzcan.19. existe una excepción a esta regla. Para esta eventualidad dispone de otras dos funciones. MySQLi y los errores La gestión de los errores en MySQLi sigue unas pautas muy sencillas. Prueba de ello es la figura 9. Como ya sabe.18. Mensaje de error en español Como puede comprobar si compara la figura 9. que devuelven el código del error y su descripción. mysqli_connect_errno() y mysqli_connect_error(). expondrán el código del mismo y su descripción. independientemente del idioma en el que se muestren los mensajes de error el código es el mismo (en este caso. respectivamente. no podrá utilizar las propiedades errno y error de la clase. puesto que no se habrá podido crear.18 con la 9. el 1046). . respectivamente.20.20. Figura 9. en caso de error. Si está utilizando la versión orientada a objetos de la misma. en la que puede ver el resultado de ejecutar la misma consulta con la que obtuvimos el mensaje de error de la figura 9. una consulta de selección sin indicar sobre qué base de datos. cada objeto con el que esté trabajando dispondrá de una pareja de propiedades que.Figura 9.20. Para obtener mensajes en español Una vez reinicie el servicio podrá comprobar que los mensajes de error del servidor aparecen en español. En el caso de que el error se produzca al intentar establecer una conexión con un servidor de bases de datos. Se trata de errno y error .

puesto que ya las hemos utilizado en numerosas ocasiones a lo largo del libro. Estas dos funciones necesitan una referencia a la variable con la que se realizó la operación que generó el error. .respectivamente. podrá utilizar las funciones mysqli_errno() y mysqli_error(). para sacar el mayor partido de ellas utilícelas conjuntamente con todas las herramientas de gestión de errores que haya visto a lo largo de este capítulo. En caso de que esté trabajando con la versión funcional de esta biblioteca. un gestor de conexión. De cómo utilizar estas funciones poco podemos contar. Sin embargo. el valor obtenido tras establecer una conexión con una base de datos de MySQL. Por ejemplo.

El proceso de unir las dos partes del trabajo no resulta demasiado complejo: copiamos un poco de código PHP en una página HTML. un bucle allá. . Las aplicaciones que hemos desarrollado hasta ahora. En este proyecto. Hasta ahora hemos apilado un buen montón de tecnologías: un servidor de bases de datos MySQL. ¿Qué es Smarty? Smarty es una capa más dentro de nuestra particular torre de Babel. sólo dejaban entrever uno de los problemas que entraña la programación con PHP: la mezcla de la lógica con la representación.10 Plantillas Si la calidad de un lenguaje de programación tuviese que medirse por la utilidad de las herramientas desarrolladas con él. Somos nosotros los que tenemos que volver a modificar sus páginas HTML para incluir el código PHP en ellas. la nota de PHP sería de las más altas. por su sencillez. PHP. HTML y JavaScript.1. tras los cambios que hayan realizado. tiene otra opción mucho más interesante y útil: las plantillas de Smarty. usted está al cargo de la parte de la programación (lo que se conoce como la lógica de la aplicación) pero no del diseño de las páginas (la representación). y cambiamos la extensión de las páginas HTML por PHP. Aunque existen herramientas que le permiten localizar diferencias entre archivos y mezclar sólo aquellas partes que le interesen. Suponga que está desarrollando una aplicación para una empresa. Por lo general. ya sea en la parte del diseño o en la parte de la programación. El verdadero problema viene cuando hemos de hacer un cambio. Smarty podría situarse entre PHP y HTML. así que siguen trabajando con su diseño. un servidor de páginas Web. unas variables acá. los diseñadores no tienen noción alguna sobre PHP. Así una y otra vez. Como puede ver en la figura 10.

¿Qué hora es? HTML y PHP entremezclados en la misma línea. Aún no lo hemos instalado (lo haremos en el siguiente apartado). Lo mejor para entender lo que estamos diciendo es verlo en funcionamiento.2. vamos a retomar el primer ejemplo que vimos en el capítulo 2. un archivo que. Una sola línea de código cuyo resultado variaba en función de la hora a la que la página se cargase. Con Smarty. es interesante que sepa. El resultado de cargar esa página puede verse en la figura 10. antes de nada. por lo general. lo que se puede conseguir con Smarty. tiene la extensión TPL (template. Para nuestro ejemplo.1. ni código HTML en las páginas PHP. plantilla). pero podemos dejarlo libre de código PHP. Sin embargo. Un pequeño ejemplo Este ejemplo le mostrará de qué es capaz Smarty. ¿Dónde está Smarty? La principal misión de Smarty es aislar la lógica de la representación de las páginas. Esto permite que el equipo de desarrollo pueda trabajar de forma independiente al equipo de diseño. aquel que mostraba la hora. De hecho. El código de esa página era el siguiente: La hora es: <?= date("H:i:s") ?>. tendríamos dos archivos: el PHP y una plantilla con el diseño correspondiente. Figura 10. así que aún queda un poco para que pueda poner en funcionamiento lo que vamos a ver. Poco diseño hay en esta página.Figura 10. Se trata de algo muy sencillo. El resultado: no hay código PHP en las páginas HTML. podría ser el siguiente: .2.

date("H:i:s")). Hablando claro: una vez tenga el programa que recupera la lista de géneros. $smarty = new Smarty. le toca al programador. Y ahora.3. Plantilla sin aplicar Un diseñador podría trabajar con este archivo. que utilizaremos para llevar a cabo la magia.La hora es: {$hora}. Seguro que está impaciente por empezar a utilizar esta herramienta en sus páginas. Una de las más importantes es que podrá cambiar el aspecto de las páginas sin que cambie la lógica del programa. El resultado será idéntico al que vimos en la figura 10. Si guardase ese archivo con el nombre smarty. Instalación El primer paso para instalar Smarty es descargarlo desde su página Web: .php').php. Sólo tiene que crear un ejemplar de dicha clase y utilizar el método assign() para crear la variable $hora que la plantilla utiliza para mostrar la hora.tpl'). No es extraño. $smarty->display('smarty. Además de la ventaja que supone separar el diseño de la lógica en sus programas.class. $smarty->assign('hora'. Figura 10. con tal de que cumpla una condición: incluir {$hora} donde deba ir la hora. ?> El primer requisito: tener acceso al archivo Smarty. podrá disponer de varios diseños diferentes para la página únicamente cambiando el nombre de la plantilla que quiera utilizar. El código de la página PHP sería el siguiente: <?php include('Smarty. existen muchas otras.tpl y lo intentase cargar en un cliente Web podría ver algo parecido a lo que muestra la figura 10. añadiendo lo que le plazca.3.class.2. En este archivo está la descripción de la clase Smarty. El método display() se encarga de localizar la ubicación de dicha variable en la plantilla y mostrar el resultado de la sustitución.

limitando su ámbito a una carpeta en particular. se trata de un archivo con la extensión tar. por si acaso: http://smarty. Por lo general. La parte final. aunque también está disponible una versión en formato zip. o en Apache. para que estén disponibles de forma global. Esta ruta será diferente dependiendo del sistema operativo que utilice.http://smarty. Posteriormente.net/download.gz es muy frecuente en sistemas Unix.4.net/ Localice la página de descarga en la Web de Smarty. como en la figura 10. Figura 10. si no utiliza XAMPP tendrá que guardar la carpeta de Smarty en otra ubicación. Existe una variable de configuración llamada include_path. indica que el archivo ha sido comprimido con gzip. . Debido a la naturaleza de la Web. tar y gunzip (disponibles casi con total seguridad en su distribución de Linux) o Stuffit (http://my. gz . Herramientas como 7-Zip (http://7-zip. estas opciones de configuración pueden incluirse en el archivo php. Not a: Esto es para aquellos que utilicen Windows. mientras que t ar indica que se trata de un paquete de archivos.org/).4. En este caso vamos a copiarla dentro de la carpeta en la que XAMPP se haya instalado. Obviamente. no es seguro que éste sea enlace del que descargar Smarty cuando lea estas líneas pero.smithmicro.gz.php Descargue la última versión estable. El contenido de esa carpeta temporal será otra con el nombre de la versión actual de Smarty dentro de la que podrá ver una serie de archivos y carpetas. modifique la configuración de PHP para que sepa dónde encontrar a Smarty. Los archivos de Smarty El proceso de instalación es tan sencillo como colocar esta carpeta donde desee. La extensión t ar.ini.com/mac/stuffit/) le ayudarán a extraer el contenido del archivo en una carpeta temporal. Como ya sabe por capítulos anteriores.

Figura 10. La prueba más sencilla para saber si Smarty está correctamente instalado es crear una página PHP dentro de la carpeta plantillas. La segunda. En esa variable debe incluir dos carpetas. las rutas a incluir se separan con punto y coma (. <Directory "C:/xampp/htdocs/plantillas"> Options Indexes FollowSymlinks AllowOverride None Order allow. ). que se encuentra en el interior de htdocs.5.Vamos a optar por la segunda opción. ?> El valor de la variable include_path puede verse en la figura 10. aquella en la que haya instalado Smarty. Al reiniciar Apache podrá ver las opciones de configuración de PHP en la carpeta plantillas utilizando la función phpinfo() dentro de un archivo PHP con un contenido como éste. que ya vimos en anteriores capítulos: <?php phpinfo(). Para ello. La configuración de Apache para la carpeta plantillas podría ser algo así: .. El nombre de esta carpeta será plantillas. la carpeta htdocs.php'). incluya una directiva php_admin_value con la que asignar un valor a la opción de configuración include_path. La primera.. En el resto de sistemas operativos.deny Allow from all php_admin_value include_path \ "C:/xampp/smarty/libs. vamos a crear una nueva carpeta dentro de la predeterminada de Apache. .class.. con dos puntos (: )..5.C:/xampp/htdocs/plantillas" </Directory> . La ruta de Smarty Not a: En Windows. Modifique entonces la configuración de Apache para que las páginas PHP que estén en esa carpeta sepan dónde encontrar a Smarty. Como ya hicimos en el capítulo anterior y en el 7. la carpeta en la que vaya a poner las plantillas. con el siguiente código: <?php require('Smarty.

el código de dicha página es el siguiente: <?php $videoteca = new mysqli( ''.require('Smarty. if ($resultado == FALSE){ echo('Error en la consulta. todo ha ido bien. Una posible solución. En caso contrario. } $resultado = $videoteca->query( 'SELECT * FROM genero' ).class. lo más seguro es que PHP no haya sido capaz de encontrar los archivos necesarios. ''. $fila[1].%s<br/>". ''. si no localiza el problema.php' ). exit(). $fila[0].php').'). ?> Y ahora que tiene Smarty en su sistema. } while ($fila = $resultado->fetch_row()){ printf( "(%u) %s . vamos a retomar la página que muestra el listado de géneros. Tras lo visto en los capítulos siguientes a ese. ?> Si al cargar esta página no se produce ningún error. 'videoteca'). . Revise la configuración y vuelva a cargar la página.'). $smarty = new Smarty.class. es indicar la ruta completa del archivo requerido: <?php require( 'C:/xampp/smarty/libs/Smarty. Lista de géneros En el capítulo 7 vimos cómo cargar la lista de géneros existentes en nuestra base de datos. if (mysqli_connect_errno() != 0){ echo('Error en la conexión. $smarty = new Smarty. $fila[2] ).

dentro de la carpeta plantillas. En este caso. esta es la plantilla: <html> <head> <title>Smarty . la segunda es para uso interno de Smarty. En la primera guarde los archivos con la extensión TPL . Es ahí donde tendremos que utilizar Smarty. La plantilla De golpe. .id}) {$generos[i]. encargado de representar la información de los géneros. Gracias a ellos puede realizar iteraciones. y en cada iteración se referirá a cada elemento de la matriz con el nombre i.tpl.géneros</title> </head> <body> {section name=i loop=$generos} ({$generos[i].).nombre} {$generos[i]. ¿Y qué es lo que hace esta plantilla? Primero fíjese en los elementos {section}. Olvidando los mensajes que envíe en caso de error en la conexión o la consulta. Smarty permite definir secciones de código en las que iterar por algunas de las variables que pase a través del método assign().descripcion}<br/> {/section} </body> </html> Debe guardarla en la carpeta templates. } $resultado->close(). Vamos a comenzar haciendo algo sencillo: lograr que el aspecto de la página sea el mismo que tenía sin utilizar Smarty. $videoteca->close(). con el nombre generos.php. el punto que tendríamos que modificar para cambiar el aspecto de los datos mostrados será el bucle while. En esa misma carpeta necesitará otras dos: templates y templates_c. Se trata de una matriz que contendrá la lista de géneros disponible. no hay dolor. dentro de la carpeta plantillas que creó anteriormente. ?> Analice el código PHP anterior. el nombre de la variable es $generos. Guarde el código anterior en un archivo llamado generos.

$smarty->display('generos. $videoteca->close(). $smarty = new Smarty. Esto en cuanto a la plantilla pero. salvo por el uso de la instrucción include. $generos). mientras que el atributo name le da el índice del elemento actual. La primera diferencia la encontramos en este bucle. se dedica a guardarlos todos en una matriz. ?> Hasta que llegamos al bucle while. pero utilizando Smarty para ello: <?php include('Smarty. exit(). todo es más o menos igual que antes de utilizar Smarty. } $resultado = $videoteca->query( 'SELECT * FROM genero' ).').php'). ¿cómo queda la página PHP? La página PHP El siguiente es el código PHP de la página que muestra la lista de géneros. que en lugar de mostrar los detalles de cada género. while ($fila = $resultado->fetch_assoc()){ array_push($generos.class. 'videoteca'). $smarty->assign('generos'.id El atributo loop de la sección determina sobre qué variable va a iterar. ''. if ($resultado == FALSE){ echo('Error en la consulta.Dentro del bucle se accede al identificador del género así: $genero[i].tpl').'). ''. . $videoteca = new mysqli( ''. if (mysqli_connect_errno() != 0) { echo('Error en la conexión. } $generos = array(). $fila). } $resultado->close().

como texto.. El resultado es indistinguible del obtenido sin Smarty. pase ese nombre de plantilla al método display(). ''.. que tenemos en una matriz y llamamos al método display() para que la magia tenga lugar.6. .. . todo seguirá funcionando correctamente. vamos a crear una nueva plantilla. Ahí empieza la diferencia. como antes. Algo así: . Géneros. Entonces. lo hará dentro de una tabla. 'videoteca').class. Si carga la página tal y cual. Esta plantilla tendría el siguiente código: <html> . le pasamos la lista de géneros. Creamos un ejemplar de la clase Smarty. Va a recibir el nombre de la plantilla a través de la URL.Tras este bucle.6.. como puede verse en la figura 10.. Ahora. if($plantilla == ''){ $plantilla = 'generos. Otra plantilla Haga un pequeño cambio en la página PHP que muestra los géneros utilizando Smarty.. include('Smarty. } $videoteca = new mysqli( ''. Veamos lo sencillo que resulta cambiar el aspecto de una página. ''. $smarty->display($plantilla).tpl'. con Smarty Pero sí que hay una importante diferencia. Figura 10. En lugar de mostrar la lista de géneros tal cual. se cierra tanto el resultado de la consulta como la conexión con la base de datos.php'). Si no recibe ningún nombre se utilizará uno predeterminado. basada en la anterior. $plantilla = $_GET['plantilla'].

7. varias plantillas . La magia vuelve a ocurrir cuando carga la página pasando un valor para el nombre de la plantilla. abierto ante nosotros. Un mundo de posibilidades.géneros</title> </head> <body> <table border="1"> <tr> <th>Id</th> <th>Nombre</th> <th>Descripción</th> </tr> {section name=i loop=$generos} <tr> <td>{$generos[i].id}</td> <td>{$generos[i]. como puede verse en la figura 10.7.descripcion}</td> </tr> {/section} </table> </body> </html> Guarde esta plantilla con el nombre tabla.<html> <head> <title>Smarty . Mismo PHP.tpl dentro de la carpeta templates que creó anteriormente.nombre}</td> <td>{$generos[i]. Figura 10.

A partir de ese momento veremos procedimientos almacenados más complejos. Este capítulo sirve como presentación de los procedimientos almacenados. La sintaxis será explicada en apartados posteriores. Empezaremos creando una base de datos con una sola tabla. del resto del libro. Aunque no es recomendable. También veremos cómo crear funciones almacenadas. de alguna manera. en los que se tratan en detalle las más importantes características de MySQL. La ausencia de los mismos en versiones anteriores a la 5 suponía una traba para el desarrollo de algunas aplicaciones. gracias a su empleo se puede lograr cierto nivel de independencia entre la base de datos y las aplicaciones que hacen uso de ella. Como comprobará. las diferencias existentes entre ambos no son demasiadas. Supondremos que el lector tiene ciertas nociones básicas tanto sobre el funcionamiento del servidor de bases de datos MySQL como sobre las herramientas necesarias para trabajar con él. quizá. aunque también podrá utilizar la base de datos completa. Además. Introducción A lo largo de los capítulos que preceden a éste ha podido comprobar cómo evoluciona una base de datos. Base de datos reducida . consideradas por muchos como una variedad de procedimientos almacenados. deberá conocer el lenguaje SQL. Para que pueda leerse independientemente del resto del libro utilizaremos un subconjunto de la base de datos de ejemplo desarrollada en capítulos anteriores. esto ha dejado de ser una excusa. Por fortuna. permitiendo agruparlos bajo un nombre común. Los procedimientos almacenados facilitan la ejecución de conjuntos de instrucciones SQL.11 Procedimientos almacenados La posibilidad de utilizar procedimientos almacenados en MySQL es. una de las características más esperadas. que utilizaremos para probar el funcionamiento de un sencillo procedimiento almacenado de ejemplo. razón por la que muchos decidían utilizar otros sistemas gestores de bases de datos. Además. para hacerlo posible es necesario que dichos capítulos sean independientes. partiendo de una sencilla idea que se va complicando a medida que se convierte en realidad. Quizá algunos lectores de este libro hayan acudido directamente a los capítulos finales (como éste). si lo desea.

nombre VARCHAR(64) NOT NULL. vamos a trabajar con una versión muy reducida de la misma. Una vez disponga de la base de datos es necesario crear la tabla que contendrá los detalles de los actores. En lo que a este capítulo respecta. Las siguientes instrucciones cumplen tal misión: USE videoteca. De hecho. DROP TABLE IF EXISTS actor. Creación Para crear la base de datos con la que trabajaremos en este capítulo sólo es necesario dar las siguientes órdenes a MySQL: DROP DATABASE IF EXISTS videoteca. CREATE TABLE actor ( id INT NOT NULL AUTO_INCREMENT. las instrucciones anteriores la borrarán junto con su contenido. .1. En los siguientes dos apartados crearemos la base de datos de prueba e insertaremos algunos registros en su única tabla.1. Figura 11. Puede ver un diagrama de la misma en la figura 11. CREATE DATABASE videoteca.Seguramente ya esté familiarizado con la base de datos que hemos creado a lo largo de este libro. la base de datos que utilizaremos sólo contendrá la tabla actor . Diagrama de la videoteca En la única tabla de esta base de datos insertaremos los mínimos registros necesarios para poder obtener resultados interesantes con los procedimientos almacenados que crearemos en este capítulo. Advert encia: Tenga cuidado: si ya dispone de una base de datos con ese nombre.

INSERT INTO actor(nombre. la lista de actores almacenados en la tabla actor . 'nm0000148'). Está realizado con MySQL Workbench.2 muestra un diagrama de la tabla que acaba de crear. Subconjunto de la videoteca Inserción El último paso consiste en insertar algunos registros en la tabla actor de la base de datos que acabamos de crear para poder trabajar con ellos. apellidos VARCHAR(64) NOT NULL. apellidos.nombre VARCHAR(64) NOT NULL. Fíjese en cómo está construido el nombre del procedimiento almacenado. 'Crowe'. El siguiente código crea un procedimiento almacenado de tales características: USE videoteca. 'Ford'. Un sencillo ejemplo Una de las tareas más simples que se pueden realizar utilizando procedimientos almacenados es recuperar información. 'nm0000128'). imdb VARCHAR(32) NOT NULL DEFAULT ''. CREATE PROCEDURE pa_actores_lista() SELECT * FROM actor. Utilice las siguientes instrucciones: USE videoteca. apellidos. Figura 11. La figura 11.2. imdb) VALUES('Harrison'. Tras crear esta versión reducida de la base de datos desarrollada durante los capítulos anteriores estamos en disposición de comenzar a trabajar con procedimientos almacenados. Como separador de palabras hemos utilizado el guión bajo (_). Por ejemplo. PRIMARY KEY(id) ) ENGINE = InnoDB. lo más parecido a un espacio que nos permiten las normas de MySQL para los . imdb) VALUES('Russell'. INSERT INTO actor(nombre.

Ejecute el procedimiento almacenado utilizando las siguientes instrucciones: USE videoteca. pero no así el resto. Ya conoce la misión de la primera línea del listado anterior: indicar la base de datos con la que queremos trabajar. El resto del nombre intenta definir claramente la finalidad del procedimiento almacenado. Posteriormente nos centraremos en la sintaxis necesaria para crear procedimientos almacenados. La siguiente. Figura 11. se trata de una simple consulta de selección. De hecho. ejecutar el procedimiento almacenado devuelve el mismo resultado . El nombre comienza con pa. Lo que diferencia las instrucciones anteriores de una consulta de selección es. precisamente. le será desconocida.4 muestra el resultado devuelto por el procedimiento almacenado que acabamos de crear. La figura 11. las iniciales de procedimiento almacenado. Lista de actores Como puede comprobar si lo desea.3 muestra la respuesta que MySQL debería dar. que comienza con la instrucción CREATE PROCEDURE . ejecute las instrucciones anteriores como si estuviese ejecutando cualquier otro conjunto de instrucciones. La figura 11. Figura 11. CALL pa_actores_lista(). Se podría decir que dicha línea le da al servidor de bases de datos la siguiente orden: "Ahora te voy a mostrar una serie de instrucciones SQL. guárdalas con el nombre pa_actores_lista porque luego las voy a necesitar".3. Creación del primer ejemplo Ha llegado el momento de obtener los frutos del trabajo realizado hasta ahora. Se trata de una elección personal que depende de las preferencias de cada uno.4. Para crear el procedimiento almacenado.nombres. Así es posible diferenciarlo claramente de una tabla. la instrucción CREATE PROCEDURE .

existe una muy obvia: quien ejecute este procedimiento almacenado no necesita saber nada en absoluto sobre la estructura de la base de datos. ¿Y por qué supone esta división una ventaja? Porque ofrece la posibilidad de trabajar con dos equipos. SELECT * FROM actor. no sería necesario que conociesen la estructura de la base de datos. Para incorporar la información obtenida a partir de la base de datos. Not a: Esta independencia entre equipos tiene ventajas añadidas. este equipo nunca utilizaría consultas. El conjunto de procedimientos almacenados creados para recuperar información de esa base de datos sería la parte lógica. Por lo tanto. Se podría decir que hemos divido la base de datos en dos partes: una estructural y otra lógica. Por ejemplo. siempre y cuando los procedimientos almacenados sigan devolviendo los mismos datos. Así que podría existir un equipo dedicado al mantenimiento de la base de datos. Como ya hemos visto. diseñando tablas. y así para cada caso. Y. Para poder sacarles todo su . sólo procedimientos almacenados. Sintaxis Las posibilidades ofrecidas por el uso de los procedimientos almacenados van mucho más allá de lo visto en el ejemplo anterior. Suponga que esta base de datos va a ser el núcleo de un sitio Web dedicada al cine y que sus páginas estarán escritas usando el lenguaje PHP. la posibilidad de modificar el diseño de la base de datos sin por ello tener que modificar las páginas PHP. ¿por qué utilizar procedimientos almacenados? Aunque existen muchas otras ventajas. La parte estructural estaría compuesta tanto por el diseño de la base de datos como por los registros almacenados en las tablas. sólo tendrían que llamar a un determinado procedimiento almacenado para obtener la lista de actores. por otro lado. el equipo dedicado a la creación de las páginas PHP. un tercero les mostraría la lista de películas protagonizadas por dicho actor. este lenguaje dispone de las herramientas necesarias para comunicarse con MySQL. definiendo sus campos y creando los procedimientos almacenados que devuelvan información a partir de los datos contenidos en la base de datos. Esas páginas serán el cliente de la base de datos.que esta consulta: USE videoteca. otro les proporcionaría todos los detalles del mismo. Entonces.

necesitará almacenarlos en algún lugar. mientras que la segunda es el cuerpo del procedimiento. Una variable es ese lugar. El lenguaje SQL es un lenguaje de programación. precisamente lo que veremos a partir de ahora. Si fuese necesario.. En ellas se guardarán aquellos valores que haya que consultar o modificar posteriormente. El siguiente ejemplo calcula y muestra el número de registros de la tabla actor : USE videoteca. puede recibir una serie de parámetros (más al respecto en el apartado “Funciones almacenadas”. Este espacio se encuentra en la memoria . Figura 11. CREATE PROCEDURE pa_actores_cantidad() SELECT COUNT(*) FROM actor.5. En la jerga de los programadores. [. Número de actores Variables Los datos no son etéreos y. La primera línea que se puede ver en la definición de la sintaxis del procedimiento almacenado se conoce como cabecera. reservar el espacio necesario para guardar dichos valores se conoce como declarar una variable.]) instrucciones Tras las palabras reservadas CREATE PROCEDURE se incluye el nombre del procedimiento almacenado..5. Creación La sintaxis de la instrucción para la creación de procedimientos almacenados en MySQL es la siguiente: CREATE PROCEDURE nombre_pa ([parámetro. El resultado de ejecutar este procedimiento almacenado puede verse en la figura 11.visto en el ejemplo anterior. El procedimiento almacenado estará completo cuando se incluyan las instrucciones asociadas al mismo. más adelante). en ocasiones. Para poder sacarles todo su jugo es necesario conocer cómo construirlos correctamente.

. . SELECT . .. acuda a la sección 6 del capítulo 3. Por ejemplo... DECLARE actores INT.. Incluya a continuación el tipo de datos de dicha variable. es posible declarar la variable actores para que su valor inicial sea 0: . Existen dos formas de asignar un valor a una variable tras su creación: Directamente: Utilizando la palabra reservada SET . el valor almacenado en una variable es NULL . Así.. Inicialmente.] tipo [DEFAULT valor_predeterminado] La palabra reservada DECLARE va seguida del nombre de la variable que se quiera declarar.. Por ejemplo. la naturaleza de los datos que contendrá. . DECLARE actores INT DEFAULT 0. Tomando su valor de una consulta: Utilizando la pal abra INTO en una consulta de selección. Para declarar una variable es necesario seguir la siguiente sintaxis: DECLARE nombre_variable[. El primer paso consiste en asignar un valor inicial a las variables que cree. . algo que se logra gracias a la palabra reservada DEFAULT ..principal del ordenador.. Así. podría asignarse el valor 0 a la variable tras declararla: . que se incluye en la sintaxis de DECLARE .. Consejo: Si quiere refrescar sus conocimientos sobre los tipos de datos.. DECLARE actores INT.. en la RAM... SET actores = 0. DECLARE actores INT. “Tipos de datos”. En ella se hace un repaso de los más importantes ofrecidos por MySQL.. la siguiente consulta recupera el número de registros en la tabla actor y guarda el valor en la variable actores: . la siguiente instrucción sirve para crear una variable de tipo entero llamada actores: . es decir.. es decir.

es posible incluir tantas instrucciones como sea necesario. Sin embargo. como tal. En lugar de ejecutar directamente la consulta. Delimitadores Ya sabe que cuando se escribe una sentencia SQL es necesario utilizar punto y coma (.. se utiliza una variable en la que se almacena el resultado de la consulta.SELECT COUNT(*) INTO actores FROM actor. SELECT actores. Es la posibilidad de realizar las mismas tareas de diferentes . CREATE PROCEDURE pa_actores_cantidad2() BEGIN DECLARE actores INT DEFAULT 0. fíjese en esta versión del procedimiento almacenado visto anteriormente. El cuerpo de los procedimientos almacenados que hemos visto hasta ahora está compuesto de una sola sentencia SQL. caso que hasta ahora no se ha dado. cuya misión era devolver el número de registros en la tabla actor : USE videoteca. Aparece aquí un problema: ¿cómo diferenciar entre el punto y coma que finaliza una sentencia perteneciente al cuerpo del procedimiento almacenado y el que marca el final del mismo? Por ejemplo. Por otra parte. END. necesita el empleo de dicho delimitador.. se devuelve dicho valor. SELECT COUNT(*) INTO actores FROM actor.) para indicar dónde acaba. la misma norma ha de seguirse en el cuerpo del procedimiento almacenado si éste está compuesto por más de una sentencia SQL. Puede comprobar que los dos procedimientos almacenados creados hasta ahora cumplen dicha norma. La sentencia de creación de un procedimiento almacenado también es SQL y. A continuación. . En lo que resta de capítulo podrá encontrar varios ejemplos del uso de variables en procedimientos almacenados.

tras la instrucción END. se crea el procedimiento almacenado y. Antes de comenzar la creación del procedimiento almacenado se declara el nuevo delimitador. corregido para que sea correcto: USE videoteca. La figura 11. DELIMITER // CREATE PROCEDURE pa_actores_cantidad2() BEGIN DECLARE actores INT. estableciendo como delimitador el punto y coma. Aunque existe la posibilidad de utilizar prácticamente cualquier delimitador en la documentación de MySQL se utilizan dos barras inclinadas (//). se deja todo como estaba.6 muestra la respuesta del cliente de MySQL al ejecutar las instrucciones de creación del procedimiento almacenado y una posterior llamada al mismo. . La solución a este conflicto es relativamente simple: definir un delimitador diferente para los procedimientos almacenados. se utiliza el delimitador declarado anteriormente. Para ello se utiliza la palabra clave DELIMITER. ya que no es capaz de diferenciar entre el punto y coma que termina una sentencia SQL interior y el que termina el procedimiento almacenado. SELECT COUNT(*) FROM actor INTO actores. Para terminar. Si intenta crear el procedimiento almacenado anterior MySQL le mostrará varios mensajes de error. END // DELIMITER . SELECT actores.formas lo que hace tan interesante utilizar este tipo de tecnologías. A continuación. El siguiente es el código del procedimiento almacenado anterior. seguida de la secuencia de caracteres marcará el final del procedimiento almacenado.

el encabezado es actores. los corchetes indican una opción. el número mostrado bajo dicho texto es el resultado de esa instrucción. De forma predeterminada. es decir. Uso de delimitadores Fíjese en la diferente respuesta obtenida al utilizar los procedimientos almacenados que devuelven el número de registros en la tabla actor . Efectivamente.6. por lo que no es obligatorio incluir los valores IN o OUT . el parámetro será de tipo IN. en la figura 11. es decir. En primer lugar. los parámetros de entrada. Not a: Como ya sabe. puesto que lo que se está seleccionando es el valor de la variable así llamada. es necesario describir la sintaxis de estos parámetros: [ IN | OUT ] nombre_parámetro tipo El significado de las palabras reservadas IN y OUT es el siguiente: IN : El parámetro es de entrada. es decir. el tipo de . si no se indica nada. El primero de ellos. Ese valor sólo se utilizará para proporcionar información al procedimiento almacenado. para informar de un valor obtenido al ejecutar el procedimiento almacenado. se está pasando un valor desde la instrucción de llamada. nada mejor que un ejemplo sobre la utilización de cada tipo de parámetro para comprender su funcionamiento. para comunicarse con el exterior. existe la posibilidad de declarar una serie de parámetros asociados.5. Sin embargo.6. OUT : Se trata de un parámetro de salida. en la figura 11. Como el movimiento se demuestra andando. Parámetros Como pudo verse en la descripción de la sintaxis de los procedimientos almacenados. A su vez.Figura 11. encabeza el resultado con COUNT(*).

además de la lista de actores.7. El siguiente código sirve para crear un procedimiento almacenado que muestra la lista de actores cuyo nombre comienza con una determinada letra: USE videoteca.7 muestra el resultado de ejecutar esta consulta.parámetro predeterminado. necesita guardar en una variable de salida el número de actores localizados. Es decir. DELIMITER // CREATE PROCEDURE pa_actores_buscar2( IN letra CHAR(2). Si quisiese localizar todos los actores cuyo nombre comienza con la letra h debería ejecutar este procedimiento almacenado así: CALL pa_actores_buscar('h%'). ha de utilizarse una variable de tipo OUT : USE videoteca. CREATE PROCEDURE pa_actores_buscar(letra CHAR(2)) SELECT * FROM actor WHERE nombre LIKE letra. Búsqueda de actores Suponga que. La figura 11. SELECT COUNT(*) INTO . OUT actores INT ) BEGIN SELECT * FROM actor WHERE nombre LIKE letra. Figura 11.

Así. MySQL también dispone de lo que podríamos llamar un pariente muy cercano de los procedimientos almacenados (prácticamente un hermano): las funciones almacenadas. @cantidad). fíjese en que el segundo comienza con el carácter @ (arroba). cuya existencia se limita al tiempo que permanezca conectado con MySQL.8 puede ver la respuesta de MySQL tanto a la llamada al procedimiento almacenado como al acceso al valor de @cantidad. INOUT .actores FROM actor WHERE nombre LIKE letra. Figura 11. Para más información consulte la documentación de MySQL. Utilice este símbolo para crear variables de sesión. Sin embargo. conocido por su presencia en las direcciones de correo electrónico. END // DELIMITER . Valor de la variable de salida Not a: Existe un tercer tipo de parámetro. Funciones almacenadas La sintaxis de las funciones almacenadas es . En la figura 11.8. como se indica en el primer parámetro. CALL pa_actores_buscar2('h%'. La llamada a este procedimiento almacenado es como sigue: USE videoteca. que queda fuera de los objetivos de este capítulo. tras la llamada al procedimiento almacenado de búsqueda es posible obtener el número de resultados obtenidos de la siguiente forma: SELECT @cantidad. También se buscan aquellos actores cuyo nombre comience con la letra h.

SELECT COUNT(*) INTO actores FROM actor.prácticamente la misma que la de los procedimientos almacenados: CREATE FUNCTION nombre_fa ([parámetro. Considere esta versión modificada del procedimiento almacenado que mostraba el número de registros presentes en la tabla de actores: USE videoteca.9. [. Es posible utilizar las funciones dentro de consultas SQL.]) RETURNS tipo instrucciones A diferencia de los procedimientos. END // DELIMITER . RETURN actores. Figura 11. Las funciones almacenadas proporcionan una forma diferente de realizar una misma tarea.9.. como puede ver en la siguiente: USE videoteca. SELECT fa_actores_cantidad(). los de entrada (IN ). Al encabezado de la función se añade la palabra clave RETURNS seguida del tipo de datos del valor devuelto.. DELIMITER // CREATE FUNCTION fa_actores_cantidad() RETURNS INT BEGIN DECLARE actores INT. Función almacenada . las funciones sólo pueden utilizar un tipo de parámetros. El resultado de ejecutar la anterior consulta puede verse en la figura 11.

el prefijo seleccionado para los nombres de las funciones almacenadas es fa . una elección personal. de manera que ahora el resultado se ordene alfabéticamente. A continuación. se localice algún error en el código del mismo o se quiera modificar su funcionamiento. cuando la definición de la sintaxis de una determinada operación incluya la palabra reservada PROCEDURE . recuerde que debe cambiarla por FUNCTION si va a trabajar con una función en lugar de con un procedimiento. Eliminación Es posible que. Deberá ejecutar las siguientes instrucciones: USE videoteca. Así. Utilización desde PHP La forma en la que puede utilizar procedimientos almacenados en sus páginas PHP es prácticamente idéntica a la que ya conoce para la ejecución de consultas. Por ejemplo. primero por apellidos y luego por nombre. vuelva a crear el procedimiento almacenado añadiendo las modificaciones que considere necesarias. Vamos a aprovechar el procedimiento almacenado con el que terminó el apartado anterior para mostrar la lista de intérpretes de la base de datos. CREATE PROCEDURE pa_actores_lista() SELECT * FROM actor ORDER BY apellidos. suponga que quiere cambiar el procedimiento almacenado que devuelve la lista de actores. DROP PROCEDURE IF EXISTS pa_actores_lista. En esas ocasiones puede eliminar el procedimiento almacenado utilizando orden DROP . Éste es el código necesario: <?php . De nuevo. en los siguientes apartados nos referiremos a ambos como procedimientos almacenados. Para evitar un error en caso de que el procedimiento almacenado no exista puede añadir las palabras reservadas IF EXISTS. nombre. a diferencia de los procedimientos almacenados.Not a: Fíjese en que. tras crear un procedimiento almacenado. A pesar de las diferencias existentes entre los procedimientos y las funciones almacenadas.

$fila[1]. ''. 'videoteca' ).10 muestra el resultado del programa anterior. Figura 11. ?> Como puede comprobar. exit(). sólo debe pasar la instrucción CALL pa_actores_lista() al método query() y trabajar con el resultado como si de una consulta normal y corriente se tratase. 'root'. .$videoteca = new mysqli( 'localhost'. $fila[0]. if ($resultado == FALSE){ echo('Error en la consulta. $fila[2].'). simplificando la ejecución de tareas frecuentes como el acceso o la modificación del contenido de las tablas de una base de datos. $videoteca->close(). Gracias a ellos es posible agrupar varias sentencias SQL bajo un mismo nombre. Procedimientos almacenados y PHP A lo largo de este capítulo hemos visto los conceptos básicos necesarios para trabajar con procedimientos almacenados. } while ($fila = $resultado->fetch_row()){ printf( "(%u) %s %s: %s<br/>". if ($videoteca->errno != 0) { echo('Error en la conexión. $fila[3] ). La figura 11. } $resultado->close().').10. } $resultado = $videoteca->query( 'CALL pa_actores_lista()' ).

mysql. sin entrar en detalles. Sin embargo.com/doc/mysql/en/create-procedure. Si desea ampliar sus conocimientos sobre procedimientos almacenados.html Quizá encuentre interesante el siguiente artículo. también publicado en la Web de MySQL: http://dev. Incluso ha visto. Obviamente. le recomendamos que visite la página de la documentación de MySQL dedicada a los mismos: http://dev. también cómo utilizarlos.com/tech-resources/articles/mysqlstoredprocedures. este capítulo es sólo el comienzo. modificar y eliminar procedimientos almacenados.mysql.html .Ahora sabe cómo crear. que estos procedimientos almacenados pueden utilizarse desde lenguajes de programación como PHP.

Por lo tanto. las características ofrecidas por los desencadenadores son limitadas. manteniendo sincronizados los datos que se requieran. una actualización o un borrado. es posible que muchos lectores tengan la tentación de leer estas páginas sin pasar por los capítulos anteriores. Si lo desea. Como se reconoce en la documentación de MySQL. El simple hecho de que sea posible utilizarlos deja prever que. las capacidades de los desencadenadores irán aumentando. supondremos que el lector tiene ciertas nociones básicas tanto sobre el funcionamiento del servidor de bases de datos MySQL como de las herramientas necesarias para trabajar con él. También es posible asociar un desencadenador a una operación de actualización. de manera que una modificación de los datos de una determinada tabla active de forma automática una actualización en otra tabla. De nuevo. algo que no disminuye la utilidad de los mismos. Introducción Al igual que en el capítulo anterior. También conocidos por su nombre en inglés (triggers). este capítulo trata una de las más importantes características de MySQL. deteniendo la operación en caso de que se detecte alguna incongruencia. Y sólo se han enumerado algunas de las posibilidades que ofrece esta interesante característica de MySQL. Así. deberá conocer el lenguaje SQL. este capítulo pretende ser lo más independiente del resto del libro que sea posible. Se pueden crear desencadenadores que se activen antes o después de una inserción. dedicado a los procedimientos almacenados. Además. Si no cumple alguno de estos requisitos lo más razonable es que lea este libro como debe. los desencadenadores permiten realizar tareas de forma automática cuando una determinada circunstancia tiene lugar. Para facilitarles las cosas. con los desencadenadores se puede verificar que los valores que se intenta insertar en una tabla cumplen unas determinadas condiciones.12 Desencadenadores Este capítulo está dedicado a otra de las importantes características de MySQL: los desencadenadores. desde el principio. poco a poco. puede utilizar desencadenadores para realizar borrados en cascada: el borrado de un determinado registro en una tabla tiene como consecuencia el borrado de otros registros en otras tablas. .

Anteriormente. Sólo por si acaso. en minúsculas y separados por un guión bajo (_).com/harrison_ford/ Aviso: En esa dirección no va a encontrar nada relacionado con el cine. Esta tabla estará relacionada con la tabla actor gracias al identificador numérico. Se trata de una persona con las ideas muy claras y ha encontrado lo que cree que es una incongruencia en el diseño de la tabla actor. quieren que ese nombre se utilice en las direcciones Web de su propia página dedicada al cine: una por cada actor. compuesto por el nombre y los apellidos del actor.1 muestra el aspecto de las dos tablas que contendrán los datos de cada actor. En lo que respecta a este capítulo. existe un nuevo requisito solicitado por la empresa que está pagando el desarrollo de la base de datos: se debe crear un nuevo campo. le recomendamos que acuda a ella si quiere saber más al respecto. así que ha decidido crear una nueva tabla en la que guardar ambos. El diseñador ha considerado que el nuevo campo y el campo imdb tienen aspectos en común. con más experiencia.example. los detalles de Harrison Ford estarían en la dirección: http://www. se trata de un simple ejemplo. La figura 12. La primera de ellas. Así. llamada actor. . se ha hecho cargo de videoteca. contiene un identificador numérico único para cada actor . sino con una fuente de información externa. Aquí comienza un pequeño cambio. dicha base de datos está compuesta por dos tablas. Imagine que un nuevo diseñador de bases de datos. esta tabla sólo debe contener datos sobre el actor y el campo imdb no está relacionado con él. A su modo de ver. esta tabla también contenía un campo llamado imdb: el identificador que IMDb (http://imdb. La sección homónima del capítulo anterior muestra más detalles sobre la misma. Por lo visto. Además. su nombre y sus apellidos. El nombre de la tabla será actor_ext . para proporcionar una forma de acceder a la información de dicha Web desde los programas que desarrolle.Base de datos reducida Durante este capítulo trabajaremos con una versión reducida y ligeramente modificada de la base de datos creada a lo largo de los capítulos anteriores de este libro. Por lo visto ext viene de externo y hace referencia a que los datos que la tabla contiene son externos al actor.com/) asigna a cada actor.

CREATE DATABASE videoteca. carpeta) . como hay dos.1. es necesario crear la base de datos: DROP DATABASE IF EXISTS videoteca. En primer lugar. CREATE TABLE actor_ext ( idactor INT NOT NULL. Inserción Por último. INSERT INTO actor(nombre. CREATE TABLE actor ( id INT NOT NULL AUTO_INCREMENT. Para conservarla sólo tiene que cambiar el nombre de la base de datos videot eca en las líneas anteriores por otro que sea de su agrado y acordarse de seguir utilizándolo durante el resto del capítulo. Advert encia: Sea cauto. será necesario realizar una inserción por cada tabla: USE videoteca. cree las tablas de la base de datos utilizando las siguientes instrucciones: USE videoteca. PRIMARY KEY(idactor). si ha seguido los ejemplos de todo el libro ya tendrá una base de datos con ese nombre. apellidos) VALUES('Russell'. 'Crowe'). nombre VARCHAR(64) NOT NULL. imdb. INSERT INTO actor_ext(idactor. imdb VARCHAR(32) NOT NULL. A continuación. apellidos VARCHAR(64) NOT NULL. Diseño de la base de datos Creación A continuación veremos qué instrucciones son necesarias para crear tanto la base de datos reducida como las tablas que contiene. PRIMARY KEY(id) ) ENGINE = InnoDB. apellidos) VALUES('Harrison'. En este caso. INSERT INTO actor(nombre. Además. carpeta VARCHAR(255) NOT NULL. inserte algunos valores en las tablas. insertaremos algunos registros de ejemplo para que la base de datos disponga de contenido con el que trabajar.Figura 12. FOREIGN KEY(idactor) REFERENCES actor(id) ) ENGINE = InnoDB. INDEX ae_FK(idactor). 'Ford').

Sintaxis Siguiendo la costumbre.INSERT INTO actor_ext(idactor. Se utiliza para determinar si las instrucciones asociadas al desencadenador se ejecutarán antes o después de la operación que lo activó. imdb. carpeta) VALUES(2. El valor de idactor es el del campo id de la tabla actor tras guardar el registro. carpeta) VALUES(1. UPDATE o DELETE . nombre se refiere al nombre del desencadenador que desea eliminar. Las palabras que están en minúsculas son las que necesitan explicación: nombre: Es el nombre que recibe el desencadenador. Creación Para crear desencadenadores es necesario seguir la siguiente sintaxis: CREATE TRIGGER nombre momento evento ON tabla FOR EACH ROW instrucciones. antes de los ejemplos veremos la sintaxis de las instrucciones relacionadas con los desencadenadores. 'nm0000148'. tabla: Nombre de la tabla con la que estará asociado el desencadenador. 'russell_crowe'). 'harrison_ford'). Lógicamente. imdb. Eliminación Para eliminar un desencadenador debe seguir la siguiente sintaxis: DROP TRIGGER nombre. como en los procedimientos almacenados. aquel por el que nos referiremos a él cuando queramos utilizarlo. si desea que el desencadenador tenga asociada más de una orden. Ejemplos . evento: Indique aquí el tipo de instrucción que activará el desencadenador. INSERT INTO actor_ext(idactor. momento: Puede tomar los valores BEFORE (antes) o AFTER (después). los valores necesarios para realizar las inserciones en la tabla actor_ext han sido tomados de la tabla actor . Se puede tratar de INSERT . Como es lógico. instrucciones: Utilice BEGIN y END. 'nm0000128'. Al tratarse de un campo de incremento automático no es posible conocer su antes de realizar la inserción.

. Inserción ¿Recuerda que. ¿qué operación activa el desencadenador? Una inserción. creará el registro correspondiente en la tabla actor_ext . fue necesario comprobar qué identificador se asignó al registro de cada actor para así mantener la integridad referencial. Ahora crearemos un desencadenador que.Por fin. automáticamente. a falta de las instrucciones asociadas: . En el caso que nos ocupa. se trata de una de las infinitas posibilidades existentes.. las instrucciones deberán ejecutarse después. Pregúntese a qué tabla debe estar asociado el desencadenador. Incluya el nombre de esa tabla como parte del nombre del desencadenador. nos vamos a poner manos a la obra. En los siguientes apartados comprobaremos lo útiles que pueden llegar a ser los desencadenadores. Obviamente. para realizar la inserción de los registros correspondientes en la tabla actor_ext . Por lo tanto. podríamos llamar dc_actor_insertar a este desencadenador. Sólo resta escribir las instrucciones asociadas al . tanto en las tareas de inserción y actualización como en las de borrado. seleccione la que más apropiada considere. La única ventaja de este sistema es que permite diferenciar de un vistazo entre un desencadenador y otros objetos de la base de datos.. cuando dicho identificador ya exista. así como saber qué tarea realiza. es necesario conocer el valor que toma el identificador del actor recién insertado. Las instrucciones asociadas se ejecutarán cuando se inserte un nuevo registro en la tabla actor . El siguiente sería el encabezado del desencadenador que estamos creando. CREATE TRIGGER dc_actor_insertar AFTER INSERT ON actor . anteriormente. tras la inserción de un nuevo actor en su tabla. Por último. Ahora.. para diferenciar un desencadenador de cualquier otro objeto de la base de datos añadiremos el prefijo dc a su nombre. por lo tanto. insertamos algunos registros en la tabla actor ? Después. insertando el valor adecuado en el campo carpeta. Incluya también el nombre de esa operación como parte del nombre del desencadenador. tras no pocas páginas introductorias. En primer lugar hemos de seleccionar el nombre del desencadenador. Tras seleccionar el nombre del desencadenador y saber a qué tabla y operación está asociado debemos determinar si las instrucciones asociadas al mismo se ejecutarán antes o después del evento que activó el desencadenador.

. El cuerpo del desencadenador sería el siguiente: . La declaración de la variable nuevo_carpeta es la primera acción que lleva a cabo el desencadenador. END . En segundo lugar.. Puede acceder a todos los valores de la operación que provocó la activación del desencadenador gracias al alias NEW.id. fruto de la concatenación del nombre y los apellidos. SET nuevo_carpeta = CONCAT( LOWER(NEW. es necesario obtener el identificador del actor recién insertado. El código completo de este desencadenador es el siguiente: USE videoteca. De nuevo. nuevo_carpeta). En ella se almacenará el nombre de la carpeta asociada al actor.apellidos) ). DELIMITER // CREATE TRIGGER dc_actor_insertar AFTER INSERT ON actor FOR EACH ROW BEGIN DECLARE nuevo_carpeta VARCHAR(255). INSERT INTO actor_ext(idactor.desencadenador. es posible acceder a dicho valor escribiendo NEW. SET nuevo_carpeta = CONCAT( LOWER(NEW.. en minúsculas. hay que concatenar el nombre y los apellidos del actor. se inserta una cadena vacía en el campo correspondiente. . ''. Fíjese en que. carpeta) VALUES(NEW. Por lo tanto.apellidos) ).id. DECLARE nuevo_carpeta VARCHAR(255). '_'. carpeta) VALUES(NEW. INSERT INTO actor_ext(idactor.nombre). LOWER(NEW.id. como no se dispone del identificador imdb. con un guión bajo como separador. nuevo_carpeta). En primer lugar. '_'.nombre). ''. La inserción se realiza utilizando dicha variable. imdb. LOWER(NEW. imdb.. es posible utilizar el alias NEW para tal fin.

insertando el identificador imdb donde corresponda. el desencadenador asociado creará el registro correspondiente en la tabla act or_ext . Es un error cometido a propósito para aprovechar las posibilidades de los desencadenadores en operaciones de actualización. apellidos) VALUES('Tim'. Inserte ahora un nuevo actor en la tabla actor : USE videoteca. Not a: Más sobre variables y delimitadores en el capítulo 11.2.'Robins'). Sólo quedaría actualizar esta última tabla. La figura 12. Suponga que se ha dado cuenta del error y lo intenta subsanar. existía un error en el nombre del actor que se insertó en la sección anterior: su apellido se escribe Robbins y no Robins. Este procedimiento almacenado realizará la inserción del nombre y el apellido en la tabla actor. INSERT INTO actor(nombre. Actualización Como puede que ya haya notado. Para ello.2 muestra el resultado de realizar la inserción de un nuevo actor en la tabla actor y una posterior consulta a la tabla actor_ext . Como consecuencia. Figura 12. UPDATE actor SET .// DELIMITER . así como su identificador imdb. Desencadenador en acción Not a: Como ejercicio para el lector se deja la creación de un procedimiento almacenado que reciba como parámetros el nombre y los apellidos del actor. dedicado a procedimientos almacenados. tendría que utilizar las siguientes instrucciones (no lo haga todavía): USE videoteca.

así que sería necesario realizar otra actualización (tampoco la haga ahora): USE videoteca. LOWER(NEW. ¿No sería mejor que esta segunda actualización se realizase de forma automática? A fin de cuentas. Podrá comprobar que.nombre). de forma automática. el valor . realice la operación de modificación en la tabla actor . UPDATE actor_ext SET carpeta = nuevo_carpeta WHERE idactor = NEW. DELIMITER // CREATE TRIGGER dc_actor_actualizar AFTER UPDATE ON actor FOR EACH ROW BEGIN DECLARE nuevo_carpeta VARCHAR(255). END // DELIMITER . '_'. SET nuevo_carpeta = CONCAT( LOWER(NEW.apellidos) ). Se han seguido los mismos razonamientos que con el desencadenador de inserción para seleccionar su nombre: USE videoteca. El siguiente es el código del desencadenador asociado con las actualizaciones de la tabla actor . no en actor_ext . UPDATE actor_ext SET carpeta = 'tim_robbins' WHERE idactor = 3. Ahora sí. esto sólo subsanaría el error en la tabla actor .id. ya sabe las operaciones que debe realizar porque las utiliza en el desencadenador de inserción. Pero claro.SET apellidos = 'Robbins' WHERE id = 3.

todos los desencadenadores que hemos visto se ejecutaban tras la acción que los activaba.id. Supongamos que queremos eliminar a uno de los actores de la base de datos. ¿Por qué antes y no después? Porque la tabla actor_ext tiene un campo. No es posible eliminar el registro de la tabla actor sin antes eliminar el asociado de la tabla actor_ext . Vamos a crear un desencadenador que se active al intentar un borrado en la tabla de actores y. El ejemplo que veremos en este apartado ejecuta las instrucciones asociadas antes. END . Para eliminarlo es necesario borrar tanto el registro asociado en la tabla actor_ext como el de la tabla actor . Pero. Obtendrá un error como el que se puede ver en la figura 12.3. idactor . Error al borrar El siguiente es el código de un desencadenador que se activa cuando se intenta eliminar un registro de la tabla actor : USE videoteca. Figura 12. DELETE FROM actor WHERE id = 3. Inténtelo si quiere: USE videoteca.del campo carpeta de la tabla actor_ext ha cambiado y su valor también es el correcto. no después. puede que prefiera automatizar el trabajo. Borrado Hasta ahora. por ejemplo. DELIMITER // CREATE TRIGGER dc_actor_eliminar BEFORE DELETE ON actor FOR EACH ROW BEGIN DELETE FROM actor_ext WHERE idactor = OLD. que está relacionado con el campo id de la tabla actor . antes de realizarlo. elimine el registro correspondiente en la tabla actor_ext .3. como ya sabe utilizar desencadenadores. el que se insertó en el apartado anterior.

los desencadenadores no ralentizan el funcionamiento global de la base de datos. su base de datos será tan rápida como si no estuviesen presentes. En resumen: sus operaciones de selección tendrán el mismo rendimiento con y sin desencadenadores. En este capítulo ha aprendido a utilizar desencadenadores. el identificador del registro que se está intentado eliminar es OLD.// DELIMITER . Tras crear el desencadenador podrá comprobar que la operación de borrado ya no provoca error alguno. Utilizar desencadenadores en exceso puede complicar las operaciones de mantenimiento de la base de datos si su funcionamiento o existencia no está completamente documentado. Así. actualizaciones y borrados. tenga cuidado. Sin embargo. una de las interesantes características de MySQL que le permitirá automatizar tareas tediosas. si las operaciones que realiza no los activan. Contrariamente a lo que se piensa.id. Puede acceder a los campos de la tabla a la que está asociado el desencadenador mediante el alias OLD. añaden ciclos de proceso cuando están en funcionamiento pero. Lógicamente. como inserciones dependientes de claves de incremento automático. .

Dejando tecnicismos a un lado. Estará en su mano sacar el máximo partido de ellas en su trabajo. Figura 13. Puede pensar en las vistas como en tablas ficticias que toman sus datos de las tablas existentes. se presenta en su propio capítulo. el usuario no apreciará que haya habido cambio alguno en el diseño de la base de datos. Introducción Para trabajar en este capítulo aprovecharemos parte del trabajo realizado en el anterior. modificar y eliminar vistas. Las vistas le permitirán añadir una nueva capa a esas dos. Base de datos de trabajo Así pues. Cuando este capítulo termine tendrá en su poder el conocimiento necesario para utilizar tres de las técnicas más interesantes que MySQL pone en su poder. Cuando termine.1. Refresquemos la memoria de aquellos que ya hayan pasado por él con la figura 13. En los dos capítulos anteriores se presentaron los conceptos básicos necesarios para poder trabajar con procedimientos almacenados y desencadenadores. se puede decir que las vistas proporcionan control sobre los datos que desea recuperar y sobre la forma en la que los mismos se presentan. siga todos los pasos de dicho apartado si aún no lo ha hecho.13 Vistas Como su propio nombre deja al descubierto. dedicado a los desencadenadores. Utilizando la base de datos de ejemplo que vimos en el capítulo anterior. En este capítulo aprenderemos la sintaxis necesaria para crear. aumentando el valor de su base de datos. crearemos una vista que permitirá simular que la tabla que contiene los datos de los actores no fue dividida en ningún momento. Sintaxis . A todos los efectos. Se trata de una característica de MySQL que. En ella puede ver las dos únicas tablas que componen la base de datos. dada su importancia.1. vuelva aquí y continúe leyendo. las vistas permiten modificar la forma en la que los datos son presentados. Todo lo necesario para disponer de una base de datos con la que poder hacer pruebas está en la sección 1 del capítulo 12.

Entre corchetes. Modificación Si desea realizar algún cambio en una vista ya existente tiene dos opciones: utilizar CREATE OR REPLACE VIEW (como acabamos de ver) o ALTER VIEW. Eliminación Cuando no necesite seguir utilizando una determinada vista puede eliminarla utilizando DROP VIEW: DROP VIEW [IF EXISTS] nombre. OR REPLACE . Creación Para crear vistas en sus bases de datos debe seguir la siguiente sintaxis: CREATE [OR REPLACE] VIEW nombre AS consulta. Si. al crear la vista. Creación Es posible que alguno de los usuarios de la base de datos necesite obtener la misma información que antes de la división de la tabla actor . El resto de la vista estará compuesto por una consulta de selección. incluya IF EXISTS. eso puede lograrse con la siguiente consulta: . En la sección 3 de este mismo capítulo veremos algunos ejemplos. Como ya sabrá. ésta será reemplazada con la nueva. son el resultado de dividir la tabla actor original. Ejemplos La base de datos con la que trabajaremos durante este capítulo está compuesta por dos tablas. Indique el nombre por el que desea referirse a la vista en nombre. dejando en una de ellas los datos pertenecientes al actor y moviendo a la otra los datos externos al mismo: el identificador de IMDb y el nombre de la carpeta de la Web en la que estará su página. La sintaxis de esta última es: ALTER VIEW nombre AS consulta. la instrucción de borrado sólo se ejecutará si la vista existe. Este último campo es de nueva aparición y fue creado en el capítulo anterior. Como ya sabe. modificación y borrado.Antes de comenzar a trabajar con vistas veremos la sintaxis de las diferentes operaciones que se pueden realizar con ellas: creación. De esa forma. Para evitar que el intento de borrado provoque un error si no existiese ninguna vista con ese nombre. utiliza esas palabras reservadas y ya existe una con el mismo nombre.

Por lo tanto. es posible realizar consultas de selección sobre ellas: USE videoteca. Al igual que con los procedimientos almacenados y los desencadenadores. Para estos usuarios podría crear una vista en la que los datos de las tablas actor y actor_ext se combinasen.2.idactor.USE videoteca. utilizaremos un prefijo que permita diferenciar las vistas del resto de objetos de la base de datos. El resultado de ejecutar la consulta anterior puede verse en la figura 13. dicho prefijo será v. a. .nombre.id.id = ae. El código necesario para crear dicha vista es el siguiente: USE videoteca.idactor.2. a aquellos con menos conocimientos de SQL.id = ae. comportándose como una sola tabla. Las vistas se comportan a todos los efectos como si fuesen tablas. a. CREATE VIEW v_actor AS SELECT a. ae.nombre. a.imdb FROM actor a JOIN actor_ext ae ON a. Figura 13. Datos de actores ¿No le parece interesante poder ocultar a algunos usuarios los detalles de la estructura de la base de datos? Por ejemplo. a. SELECT a.id. ae. En este caso.apellidos.apellidos.imdb FROM actor a JOIN actor_ext ae ON a.

Por ejemplo: USE videoteca. que se muestra en la figura 13.4. Podrá comprobar que el orden en el que se devuelven los registros ha cambiado.SELECT * FROM v_actor. nombre. como puede ver en la figura 13. .4. Figura 13.3 puede ver el resultado de crear la vista y realizar una consulta sobre ella. SELECT * FROM v_actor ORDER BY apellidos. en las consultas que sobre ella se realicen. Conflicto en el nombre Modificación Hasta tal punto las vistas se comportan como si de tablas se tratase que es posible incluir modificadores.3. Creación y uso de una vista Not a: No es posible asignar a una vista el nombre de un objeto ya existente en la base de datos. En la figura 13. MySQL le avisará de que ya existe una tabla con ese nombre. Pruebe a utilizar el nombre act or en la vista que acaba de crear.2. como los de ordenación. Fíjese en el resultado de ejecutar esta consulta. y compárelo con el obtenido en la figura 13.5. Figura 13.

Aunque también puede obtener el mismo resultado con las siguientes instrucciones: USE videoteca.imdb FROM actor a JOIN actor_ext ae ON a.nombre. a. disponemos de dos opciones: CREATE OR REPLACE VIEW y ALTER VIEW. nombre.id. ae. a. .Figura 13.idactor ORDER BY apellidos.apellidos. Para ello.id = ae. por la vista.id = ae. a. Orden en las vistas Pero también es posible modificar el orden en el que los registros son devueltos.idactor ORDER BY apellidos. El código necesario para modificar la vista utilizando la primera de las opciones es el siguiente: USE videoteca.id.apellidos. ae.5.imdb FROM actor a JOIN actor_ext ae ON a. directamente.nombre. ALTER VIEW v_actor AS SELECT a. sólo hay que modificar la consulta. nombre. CREATE OR REPLACE VIEW v_actor AS SELECT a. a. Como vimos en el apartado dedicado a la sintaxis de las operaciones relacionadas con la gestión de las vistas.

Éste es el código necesario para utilizar la vista que devuelve la lista de intérpretes ordenados por nombre que creamos en la sección anterior: <?php $videoteca = new mysqli( 'localhost'. } $resultado = $videoteca->query( 'CALL pa_actores_lista()' ). Por ejemplo. DROP VIEW v_actor. } .6 puede comprobar que ahora la vista devuelve los datos de los actores ordenados. Utilización desde PHP La forma en la que puede utilizar vistas en sus páginas PHP es prácticamente idéntica a la que ya conoce para la ejecución de consultas. exit(). las siguientes instrucciones eliminan la vista v_actor de la base de datos videoteca: USE videoteca.').6. if ($resultado == FALSE){ echo('Error en la consulta. 'videoteca' ). if ($videoteca->errno != 0) { echo('Error en la conexión. La vista ordena los datos Eliminación Cuando decida que no necesita una determinada vista puede eliminarla utilizando la instrucción DROP VIEW. Figura 13.En la figura 13.'). 'root'. ''. La eliminación de una vista no supone la eliminación de las tablas de las que obtenía los datos.

$videoteca->close(). Así. el uso de vistas también presenta inconvenientes. $fila[3] ). ?> Como puede comprobar. las vistas. Si el usuario utiliza las vistas que se le proporcionan sólo será necesario cambiar la forma en la que la vista trabaja para seguir proporcionando al usuario lo que espera. administradores y usuarios sabrán qué resultados pueden esperar de sus operaciones. La figura 13. la base de datos también tiene procedimientos almacenados y desencadenadores. la sobrecarga de trabajo que la gestión de las vistas puede suponer a los administradores de la base de datos. Entre ellos. } $resultado->close(). $fila[2].7 muestra el resultado del programa anterior. $fila[0]. sólo debe pasar la instrucción CALL pa_actores_lista() al método query() y trabajar con el resultado como si de una consulta normal y corriente se tratase. Sin embargo. Figura 13. debe tener especial cuidado en mantener completamente documentados todos los aspectos de la base de datos. Vistas y PHP Durante este capítulo ha aprendido a gestionar una de las características más interesantes de MySQL. $fila[1].7. además. Si. . Esto puede suponer una gran ventaja en aquellas ocasiones en las que sea necesario modificar la distribución de los campos dentro de las diferentes tablas.while ($fila = $resultado->fetch_row()){ printf( "(%u) %s %s: %s<br/>". Gracias a ellas puede ocultar la verdadera estructura de la base de datos a algunos de los usuarios de la misma.

¿qué aspecto tiene un documento XML? En realidad. no se trata de nada extraño. ¿Qué es XML? Al hablar de XML y MySQL nos debatimos entre la sencillez de unas siglas y la panacea universal. proceden del inglés eXtensible Markup Language (lenguaje extensible de marcas). sin formato.0"?> <reparto> <papel protagonista="si"> <personaje>Rick Deckard</personaje> . la utilización de XML con MySQL y PHP no resolverá todos nuestros problemas. cuya apariencia pueda ser modificada posteriormente. Veremos cómo obtener valores en formato XML desde la línea de órdenes.14 XML De un tiempo a esta parte las siglas XML se han hecho omnipresentes en el ámbito de la informática. Pero. por último. aprenderemos trabajar directamente con XML. extraer o modificar únicamente un fragmento. son sencillos caracteres de texto puestos uno tras otro. Aunque dista mucho de ser el soporte completo que a todos nos gustaría tener. luego. Aunque también es seguro que hará más sencillo encontrar soluciones a los mismos. El siguiente contiene detalles sobre el reparto de Blade Runner: <?xml version="1. Por una parte. MySQL nos ofrece dos formas de combinar datos y XML. desde consultas SQL y. mediante dos funciones que permiten manipular cadenas de texto con formato XML que se encuentren almacenadas en algún campo. PHP dispone de multitud de herramientas para tratar con XML. hace más fácil la posibilidad de que en la base de datos sólo haya datos puros. Estás siglas. Como antes con muchos otros estándares. Por otra. su adopción se anuncia como la solución de los problemas a los que se enfrentan a diario los profesionales del mundo de la informática. Por su parte. permite almacenar en bruto grandes cantidades de datos en un único campo y. utilizaremos PHP junto con XML. La pareja formada por las aplicaciones Web (desarrolladas con MySQL y PHP) y XML resulta especialmente interesante. En segundo lugar. y lo que es seguro es que. En este capítulo encontrará una introducción al formato XML. En primer lugar. sí que se trata de un punto de partida. utilizando herramientas como mysql o mysqldump. por sí sola. Ni una cosa ni otra: no son sólo unas siglas. que tanto han dado que hablar.

dada su naturaleza estructurada. vayamos por partes. aunque los que mejor van a entender XML son las máquinas y los procesos. Parafraseando a Jack el destripador. XML es un lenguaje en el que prima la sencillez y la portabilidad. tampoco es tan sorprendente: XML está pensado con Internet como uno de sus objetivos.<actor>Harrison Ford</actor> </papel> <papel protagonista="no"> <personaje>Roy Batty</personaje> <actor>Rutger Hauer</actor> </papel> <papel protagonista="no"> <personaje>Rachael</personaje> <actor>Sean Young</actor> </papel> </reparto> Si conoce HTML seguro que encuentra similitudes. nosotros también somos capaces de sacar conclusiones a partir de un documento XML. La figura 14. más fácil será crear programas capaces de leerlo de forma eficaz. Todo lenguaje tiene unas reglas más o menos estrictas que deben ser cumplidas para que pueda ser entendido. Partes de un documento XML Antes de describir con más detalle cada parte de un documento XML recordemos que es un lenguaje de .1 muestra cómo se ve el anterior documento XML en un cliente Web. XML en un cliente Web Lo que sí queda claro es que. Aunque. En el caso de XML. de un vistazo.1. desde el principio. esto es aún más cierto. aplicaciones que pensábamos que tenían una única misión (visitar páginas Web. en este caso) están listas para desempeñar muchas otras funciones. Es interesante comprobar que. Figura 14. Mientras más estricto sea. si lo piensa un poco.

incluidas estas dos etiquetas. Prólogo Todo documento XML debe comenzar con un prólogo que se encargue de presentar el tipo del documento. <personaje> y <actor> son etiquetas. se trataría de todo lo que está entre <reparto> y </reparto>. pero siempre con el mismo patrón. Las etiquetas están compuestas por un nombre y unos atributos. o una combinación de ambas. Eso quiere decir que se trata de una instrucción que contiene información sobre el documento. Etiquetas Para diferenciar entre los distintos elementos que componen un documento XML hemos de utilizar etiquetas. a éstos se añade un símbolo de cierre de interrogación.marcas. a excepción de declaraciones XML o de tipo de documento. todo mayúsculas. las marcas están delimitadas por los símbolos "menor que" (<) y "mayor que" (>). lo que resulta en (<?) y (?>). la versión de la norma a la que se adhiere y muchas otras características. lo que se conoce como instrucción de proceso. pensado para la descripción de datos. el cuerpo y el epílogo. . Nombres Es más que recomendable ceñirse a un determinado patrón al dar nombre a las etiquetas: todo minúsculas. Seguir esta recomendación le evitará muchos quebraderos de cabeza en el futuro. Dicho lo cual. Epílogo Situado a continuación del cuerpo del documento. Todo lo que se encuentre entre esos dos símbolos es una marca o etiqueta. puede estar compuesto de instrucciones de proceso como las del prólogo.0"?> La etiqueta de esta línea está compuesta de forma diferente al resto de las que aparecen en el documento: en lugar de estar entre los símbolos "menor que" (<) y "mayor que" (>). En él. Cuerpo Los datos que un documento XML nos ofrece están en lo que se conoce como cuerpo. un documento XML puede presentar tres partes diferentes: el prólogo. debe existir una de apertura y otra de cierre y deben estar correctamente situadas. Este elemento se conoce como la raíz del documento. En el ejemplo que nos ocupa el prólogo es el siguiente: <?xml version="1. A continuación del prólogo nos encontramos con el contenido del documento. Por ejemplo. En el caso de nuestro ejemplo.

atributos y valores. pero si la apertura de comillas es simple. El caso de XML no es diferente: la etiqueta denota el nombre del elemento. . a su vez. Por ejemplo: <actor>Harrison Ford</actor> Las etiquetas de cierre son como las de apertura. el cierre también debe serlo. Uniendo etiquetas. sus propiedades.. En el primer nivel de descendencia están los nodos hijos. pero con una barra inclinada antes del nombre de la misma. En este caso. la etiqueta A se refiere a un enlace y HREF es un atributo. Si conoce HTML ya habrá tenido su primer contacto con los atributos. y el atributo. y nietos del otro. la etiqueta HTML para crear un enlace a otra página podría ser la siguiente: . serán hijos del inmediatamente anterior. ¿qué tenemos? Nodos Un nodo está compuesto por una etiqueta. Esta estructura de padres e hijos también es conocida como estructura arbórea o jerarquía. e igual si son dobles. El valor del atributo debe estar obligatoriamente entre comillas. lo que puede incluir a otros nodos. tienen como descendientes a los nodos <personaje> y <actor>. separados ambos por un signo de igualdad (=). nos referiremos a ellos como nodos descendientes. Este nodo tiene como descendientes nodos <papel> que. sus atributos y su contenido. El contenido es todo lo que está entre la etiqueta de apertura y la de cierre. los nombres de las etiquetas de apertura y cierre deben coincidir. Obviamente. no en las de cierre. Los atributos serían las propiedades que tiene ese elemento: ese enlace lleva a una determinada dirección que se indica en el atributo A. Los atributos sólo pueden indicarse en las etiquetas de apertura.. Si en el contenido de un nodo hay otros nodos..Cada etiqueta de apertura debe tener una de correspondiente de cierre.. utilizando atributos. Un atributo está formado por el nombre del mismo y el valor que toma. <A HREF=http://enreas. La jerarquía en nuestro ejemplo está muy clara: el primer nodo del árbol es <reparto>. Atributos Las etiquetas pueden aprovecharse para incluir otros datos. Estas comillas pueden ser simples o dobles. Por ejemplo. Si estos nodos tienen a su vez otros nodos en su interior.com/mysql> Guía de MySQL </A> .

los descendientes de este nodo son nodos field. La figura 14. SELECT * FROM soporte. pero basta con que realice una consulta para darse cuenta de que no es así. por ejemplo. A su vez. por ejemplo.Con esta breve introducción ya estamos listos para trabajar con XML. Resultado de una consulta en XML En el documento XML obtenido podemos examinar los diferentes elementos que describimos al principio del capítulo: hay un prólogo y un cuerpo. El valor de cada campo se encuentra entre las etiquetas de apertura y . Por ejemplo. resultset (conjunto de resultados. uno por cada campo solicitado en la consulta. para iniciar una sesión con el usuario root utilizaríamos la siguiente orden: mysql -u root -p --xml Cuando introduzca la contraseña le parecerá que nada ha cambiado.). El atributo name contiene el nombre del atributo. uno por fila obtenida como resultado de la consulta. El valor de uno de sus atributos. pero no hay epílogo. statement .2 muestra el resultado de ejecutar esta consulta tras utilizar ese parámetro. de la que tanto partido hemos sacado durante este libro.2. Los descendientes de resulset son nodos row. Figura 14. vamos a seleccionar todos los soportes guardados en la base de datos: USE videoteca. En este caso son todos los campos de cada fila de la tabla soporte. XML desde la línea de órdenes La forma más sencilla de que el resultado de nuestras consultas SQL esté en formato XML es utilizar las herramientas para la línea de órdenes como. Así. mysql. Dentro del cuerpo podemos ver el nodo raíz. xml. Sólo tenemos que añadir un parámetro más. en inglés. es la consulta que dio como resultado el documento XML que estamos examinando.

pero también puede ejecutar esta orden: mysql -u root -p --xml -e "SELECT * FROM soporte" videoteca > soportes. pero quizá lo fuese más si pudiésemos guardarlo en un archivo para poder utilizarlo desde otras aplicaciones. Figura 14. SELECT nombre FROM soporte. Cambio en el nombre del campo Obtener el resultado en formato XML es muy interesante. puede copiar el resultado obtenido y pegarlo en un editor de textos.cierre de los nodos field. Puede ver el resultado en la figura 14. supongamos que no nos interesan ni los identificadores ni las siglas. Por ejemplo.xml . un elemento field correspondiente con el campo nombre. El documento XML también puede modificarse desde la consulta SQL para que el valor del atributo name sea el que queramos. La figura 14. ahora cada elemento row sólo tiene un descendiente. gracias a esta consulta su valor será soporte en lugar de nombre: USE videoteca.3 muestra el resultado de ejecutar esta consulta: USE videoteca. El documento XML obtenido responde fielmente a las características de la consulta SQL realizada.4. Sí.3. SELECT nombre AS soporte FROM soporte. Por ejemplo.4. Figura 14. Consulta SQL con un único campo Como puede comprobar.

indicamos el nombre de la base de datos con la que queremos trabajar y.5 puede ver el archivo resultante.Tras el parámetro xml aparece el parámetro e. que necesita el texto de la consulta a realizar (la de selección de soportes.5. redirigimos el resultado a un archivo. Resultado XML en Internet Explorer Ya sabemos cómo obtener el resultado de nuestras consultas en formato XML. abierto con Internet Explorer. por último. el reparto de cada película. Pero. así como extraer valores de ellos y modificarlos. En la figura 14.6? . en este caso). A continuación. estas dos funciones trabajan con fragmentos de cadenas en formato XML. ¿de qué puede servir guardar fragmentos de documentos XML en los campos de una tabla? Volvamos a la base de datos de ejemplo que hemos utilizado en esta guía y supongamos que queremos almacenar nuevos datos en ella. siendo precisos. En realidad. Figura 14. ¿Dónde encajaría dentro del modelo que puede ver en la figura 14. A continuación veremos que es posible guardar documentos XML en los campos de una tabla. Funciones XML MySQL proporciona dos funciones para trabajar con documentos XML: ExtractValue y UpdateXML . En este caso. ya que no incluiremos el prólogo.

¿verdad? Sólo podríamos almacenar uno de los personajes del reparto. A fin de cuentas. si hace clic en el enlace more (el puntero del ratón se encuentra sobre él) podrá ver el reparto completo de esta película. tenemos una tabla para los actores. Fíjese en que se trata sólo de parte de ella. Pero eso no soluciona otro problema: estamos añadiendo datos duplicados. pero también con cada actor. un mismo actor puede interpretar varios personajes en la misma película (en este caso. Tobey Maguire se encarga tanto de Peter Parker como de Spiderman). Estas relaciones deberían ser muchos a muchos: un mismo personaje puede aparecer en varias películas (como Peter Parker en la serie de películas de Spiderman) y. Está claro que se trata de información relacionada con cada película.7 puede ver el reparto de la primera parte de Spiderman. ¿Merece la pena que añadamos la tabla de personajes y las dos tablas auxiliares necesarias para mantener la integridad referencial de las relaciones correspondientes? En la figura 14. podríamos tener tantas como quisiésemos. con un número al final para diferenciarlas.Figura 14. La base de datos de la videoteca Podríamos añadir una pareja de campos nuevos: reparto_personaje y reparto_actor . Si añadiésemos más parejas reparto_personaje y reparto_actor . Deberíamos crear una tabla de personajes relacionada con la tabla de actores y con la de películas. No parece demasiado lógico. .6. además.

y debe hacerse de forma homogénea. es decir. XPath La clave de utilizar XML es doble: guardar y extraer. sólo necesitamos guardar una lista. Se dice que es absoluta si parte del nodo raíz. hay que saber extraer información a partir de los datos. Las funciones ExtractValue y UpdateXML nos permitirán hacer esto. hay que saber cómo almacenar los datos. XPath no es más que un conjunto de reglas sintácticas que definen un sistema de consulta para documentos XML. En definitiva.7. Aunque se trata sólo de una de las múltiples aplicaciones que se le pueden dar. Pero antes de ver estas dos funciones hablemos un poquito de XPath. Igual que ocurre dentro de un sistema de archivos. Reparto de Spiderman Supongamos que no nos interesa para nada mantener la tabla de personajes. Tampoco queremos que el reparto mantenga relación con la tabla de actores. sólo queremos disponer del reparto como simple referencia. una consulta XPath puede ser absoluta o relativa.Figura 14. Primero. precisamente. Segundo. Recordemos el documento XML con el que comenzó el capítulo: . el primer carácter de la consulta es /.

Ahora vamos a insertar en ese nuevo campo el fragmento XML con el reparto de Blade Runner. XPath también permite acceder al valor de los atributos. Una ruta relativa: papel/personaje.<?xml version="1. para obtener los valores del atributo protagonista tendríamos que utilizar la ruta: /reparto/papel/personaje@protagonista. Ejecute la siguiente consulta para añadir este nuevo campo: USE videoteca. a partir de /reparto. UPDATE pelicula SET reparto = '<reparto> <papel protagonista="si"> <personaje>Rick Deckard</personaje> <actor>Harrisond Ford</actor> </papel> . Datos de ejemplo Para probar el funcionamiento de las dos funciones que permiten trabajar con datos en formato XML vamos a modificar la tabla de películas. la consulta de actualización sería: USE videoteca. Por ejemplo. ALTER TABLE pelicula ADD reparto TEXT NOT NULL.0"?> <reparto> <papel protagonista="si"> <personaje>Rick Deckard</personaje> <actor>Harrison Ford</actor> </papel> <papel protagonista="no"> <personaje>Roy Batty</personaje> <actor>Rutger Hauer</actor> </papel> <papel protagonista="no"> <personaje>Rachael</personaje> <actor>Sean Young</actor> </papel> </reparto> Gracias a XPath podemos llegar a los nombres de cada personaje utilizando: Una ruta absoluta: /reparto/papel/personaje. Si el identificador de esta película es el 1. Crearemos un nuevo campo que contendrá fragmentos de XML con el reparto.

El resultado de ejecutar esta consulta aparece en la figura 14.</papel> <papel protagonista="no"> <personaje>Roy Batty</personaje> <actor>Rutger Hauer</actor> </papel> <papel protagonista="no"> <personaje>Rachael</personaje> <actor>Sean Young</actor> </papel> </reparto>' WHERE id = 1. Como acaba de ver. no es necesario que el fragmento se tome de una tabla. El siguiente es un sencillo ejemplo del funcionamiento de esta función: SELECT ExtractValue( '<papel> <personaje>Roy Batty</personaje> <actor>Rutger Hauer</actor> </papel>'.8. Datos de la película Blade Runner Y ahora.8 muestra el resultado de realizar una consulta de selección sobre la tabla de películas para ver los campos de Blade Runner. La figura 14. . ¿qué hacemos con todo esto? ExtractValue La función ExtractValue permite recuperar valores de un fragmento de un documento XML.9. Figura 14. '/papel/personaje' ) AS personaje. Recibe dos parámetros: el fragmento en cuestión y una expresión XPath que determina qué valores debe devolver.

Haga la prueba. Obtendríamos un resultado distinto si utilizásemos como segundo parámetro la expresión XPath /papel/actor . También podemos acceder a los atributos utilizando la expresión XPath /reparto/papel/@protagonista.9.Figura 14. Ejemplo de utilización de ExtractValue Truco: Las cosas serían mucho más feas sin esa última cláusula AS personaje. papel y luego el nodo personaje. Lista de personajes Igual de sencillo es obtener la lista de intérpretes.9. SELECT ExtractValue( reparto. Primero el nodo raíz.10. Figura 14.10. '/reparto/papel/personaje' ) AS personajes FROM pelicula WHERE id = 1. El valor del segundo parámetro es /papel/personaje. ¿cuál será el resultado de utilizar esta función con un valor almacenado en un campo de una tabla? ¿Qué ocurrirá si más de un registro coincide con la expresión XPath? Ejecute la siguiente consulta para averiguarlo: USE videoteca. La figura . Si interpreta ese valor como una ruta sólo tiene que seguir los nodos para obtener el resultado mostrado en la figura 14. Como muestra la figura 14. Pero. el resultado es la lista de personajes contenidos en el fragmento XML del campo.

CREATE PROCEDURE pa_personajes_obtener ( idpelicula INT ) BEGIN DECLARE i INT DEFAULT 1.11 muestra el resultado utilizarla en una consulta.14. En este último ejemplo sí es fácil diferenciar entre cada uno de los elementos devueltos pero. Podemos solucionarlo si combinamos varias de las técnicas aprendidas a lo largo de este libro. DECLARE j INT DEFAULT 0. DECLARE personajes TEXT DEFAULT ''. El código del procedimiento almacenado es el siguiente: DELIMITER // DROP PROCEDURE IF EXISTS pa_personajes_obtener. Vamos a utilizar el siguiente código para crear un procedimiento almacenado que recupere. Atributos de cada papel Sin embargo. De esa forma. 'count(/reparto/papel)') INTO j FROM . en el caso de los nombres de los personajes (Rick Deckard Roy Batty Rachael) resulta un poco más complicado. de poco nos sirven los resultados que acabamos de obtener.11. Figura 14. DECLARE personaje TEXT DEFAULT ''. podrá acceder fácilmente a cada uno de ellos. si llama al procedimiento almacenado desde un lenguaje de programación. uno por uno. Not a: Encontrará más información sobre los procedimientos almacenados en el capítulo 11. los nombres de los personajes y los devuelva separados por comas. SELECT ExtractValue( reparto.

El resultado. CALL pa_personajes_obtener(1). '/reparto/papel[$i]/personaje') INTO personaje FROM pelicula WHERE id = idpelicula. personaje). END WHILE. separados por comas . END // DELIMITER . Para obtener la lista de personajes de la película con identificador 1 (Blade Runner) tendría que ejecutar la siguiente consulta: USE videoteca.FROM pelicula WHERE id = idpelicula. personaje) INTO personaje. SET personajes = CONCAT( personajes. SELECT IF( i <> j. CONCAT(personaje. Figura 14. SET i = i + 1.12. Personajes. ').12. WHILE i <= j DO SELECT ExtractValue( reparto. en la figura 14. SELECT personajes. '.

eche un vistazo a la lista de actores presentes en el campo reparto. '<actor>Harrison Ford</actor>' ) WHERE . obtenemos uno por uno los nombres de los personajes y los guardamos en otra variable.En este procedimiento almacenado se utilizan varias técnicas avanzadas. por último. El último nombre no incluye una coma al final. Ejecute la siguiente consulta para corregirlo: USE videoteca. Not a: En el procedimiento almacenado anterior utilizamos la instrucción de control de flujo WHILE y la función IF. técnicas avanzadas que no han tenido su hueco en este libro. UpdateXML recibe tres parámetros: el fragmento XML con el que trabajar. Volvamos a utilizar los datos de ejemplo. A continuación.8. Recordemos que ésta última permite extraer datos de fragmentos de documentos XML almacenados en campos de una tabla. UPDATE pelicula SET reparto = UpdateXML( reparto. Para poder acceder a ellos de uno en uno utilizamos la expresión XPath /reparto/papel[$i]/personaje. Pudimos verla en la figura 14. separados por comas. Si desea más información sobre ellas consulte la documentación de MySQL. El resultado de esa consulta se guarda en la variable j. UpdateXML La función UpdateXML es la contrapartida necesaria de ExtractValue. contamos el número de papeles de que disponemos en el fragmento XML. Para empezar. donde $i toma los valores desde 1 hasta el número de papeles existentes: /reparto/papel[1] representa al primer nodo papel. /reparto/papel[2] al segundo y así sucesivamente. Terminamos devolviendo el valor guardado en la variable personajes. Para empezar. No tendría mucho sentido que para modificar los valores de esos campos tuviésemos que guardar una nueva versión de dichos fragmentos. hemos metido la pata: el actor principal de Blade Runner no es Harrisond Ford sino Harrison Ford. '/reparto/papel[1]/actor'. el nuevo valor que queremos guardar. Si se fija. la expresión XPath que determina qué valores se quieren modificar y.

'/reparto/papel[1]/actor' ) AS actor FROM pelicula WHERE id = 1.13. SELECT ExtractValue( reparto. Tras papel. ¿Ha tenido éxito el cambio? Compruébelo con la siguiente consulta: USE videoteca. DOM (o DOM XML si utiliza PHP 4) o la pareja XMLReader y XMLWriter. cada una con sus ventajas y sus inconvenientes si las comparamos entre sí. la siguiente orden devuelve la lista de géneros contenidos en la tabla correspondiente de la base de datos.id = 1.13 muestra el resultado de ejecutar tanto la modificación como la consulta de datos. Existen otras alternativas. Por ejemplo. Apertura Según vimos en los apartados anteriores. Modificación con UpdateXML SimpleXML Su nombre no podía ser más claro: SimpleXML es la forma más sencilla de manipular documentos XML desde PHP. con diferencia. entre corchetes. Figura 14. la posición en la que se encuentra el elemento papel que queremos modificar. La figura 14. . el correspondiente al papel de Rick Deckard. En este caso se trata del primero de ellos.

TRUE ).mysql -u root -p --xml -e "SELECT * FROM soporte" videoteca > soportes.w3. simple: <?php $xml = new SimpleXMLElement( 'C:\soportes.5 mostraba el resultado de ejecutar dicha orden. no parece un documento XML en absoluto.xml'. pues eso. Carga de un documento XML Truco: Efectivamente. ?> La figura 14.14 muestra el resultado de este breve programa. NULL. echo $xml->asXML(). Figura 14.0"?> <resultset statement="SELECT * FROM soporte" xmlns:xsi= "http://www.14. pero eso es porque el cliente Web está interpretando el código XML y sólo muestra la parte .xml La anterior figura 14.org/2001/XMLSchema-instance" > <row> <field name="id">1</field> <field name="nombre">DVD</field> <field name="descripcion"> Digital Versatile Disc </field> </row> <row> <field name="id">2</field> <field name="nombre">VHS</field> <field name="descripcion"> Video Home System </field> </row> </resultset> Cargar un documento XML desde un archivo de texto utilizando SimpleXML es. Se trata del siguiente documento XML: <?xml version="1.

dependiendo del valor del tercer parámetro. En este caso se trata de los nodos row que contiene el nodo resultset . Aunque poder mostrar el contenido de un documento XML está muy bien.interesante para nosotros. Ahora.xml'. Sus descendientes son los nodos row que. si es FALSE como texto XML. Para cargar el documento XML utilizamos el constructor de la clase SimpleXMLElement . El primer parámetro es el contenido XML que deseamos cargar. que quedan fuera del alcance de esta guía. meros seres humanos. NULL. foreach($rows as $row){ echo $row->asXML() . Puede ser tanto una cadena de texto con contenido XML como un URL (que apunte a una dirección Web o a contenido dentro del sistema de archivos). Resulta sencillo recorrer cada nodo row del documento: <?php $xml = new SimpleXMLElement( 'C:\soportes. Para acceder a cada nodo sólo tenemos que iterar por $rows y mostrar su contenido utilizando asXML. Como resultado se devolverán todos los nodos del documento que cumplan ese criterio. Si su valor es TRUE . Not a: El segundo parámetro se puede utilizar para pasar opciones al intérprete XML. Por lo tanto. el parámetro de que debemos pasar a xpath es /resultset/row. Si quiere ver el código XML completo haga clic con el botón derecho del ratón sobre la página y seleccione la opción Ver código fuente del menú desplegable que aparecerá. El método asXML de la clase SimpleXMLElement se utiliza para obtener el contenido XML cargado desde el recurso externo o desde la cadena de texto pasada como primer parámetro. La figura . en lugar de mostrar el contenido del documento utilizamos el método xpath para acceder a los nodos que nos interesan. a su vez. Recorrido de nodos El nodo raíz del documento XML que estamos utilizando en este apartado es resultset . contienen nodos field. '<br/>'. libxml. $rows = $xml->xpath('/resultset/row'). el primer parámetro se interpretará como URL. } ?> La apertura del documento es exactamente igual que antes. TRUE ). lo que resulta realmente interesante es poder acceder a sus elementos.

Por ejemplo.15. break. a continuación. otro bucle para obtener todos los nodos field y. el nombre en negrita y. case 'nombre': echo('<b>' . foreach($attributes as $attribute){ switch($attribute){ case 'id': echo('(' . '</b>: '). tras dos puntos. la descripción. . podría utilizar un bucle foreach para obtener todos los nodos row. Así. $field->asXML() . obtener todos los atributos con otro bucle foreach.xml'. break.14. Dependiendo del valor del atributo name de cada nodo field contenido en su interior mostraremos la información de una forma o de otra. $rows = $xml->xpath('/resultset/row'). TRUE ). foreach($rows as $row){ $fields = $row->xpath('field'). $field->asXML() . ') '). una vez allí.15 muestra lo que se vería al ejecutar el anterior programa. foreach($fields as $field){ $attributes = $field->attributes(). al principio. NULL. El código resultante sería el siguiente: <?php $xml = new SimpleXMLElement( 'C:\soportes. Figura 14. Acceso a nodos Acceso a atributos Para acceder a los atributos de un nodo debemos utilizar el método attributes del nodo que nos interese. terminada en punto. el identificador irá entre paréntesis.

se trata sólo de la punta del iceberg. case 'descripcion': echo($field->asXML() . que permiten extraer y modificar valores de campos que contengan fragmentos de documentos en formato XML. en la figura 14. Es más. DOM o la pareja XMLReader y XMLWriter. le garantizo que MySQL seguirá incorporando nuevas características para facilitar el trabajo con XML.break. hemos aprendido a tratar esos datos XML desde PHP. Además.16. hemos aprendido cómo funcionan tanto ExtractValue como UpdateXML . Consulte la documentación de SimpleXML si desea más información al respecto. Acceso a los atributos Not a: SimpleXML también permite modificar el contenido de los documentos XML. } } } } ?> El resultado. Cada una de ellas tiene sus virtudes y sus defectos. algo que puede serle útil si quiere utilizar esos datos en otros programas. Para terminar. Tras lo visto en este capítulo ya sabe cómo obtener en resultado de sus consultas SQL en formato XML. Figura 14. La elección dependerá de las necesidades de sus programas. por ejemplo. break.<br/>'). Este lenguaje de programación ofrece diferentes interfaces de acceso a XML además de SimpleXML como. .16. incluso construirlos desde cero. así que todo el tiempo que invierta en aprender sobre él será una buena inversión. Aunque las capacidades de MySQL en lo que a este formato se refiere son bastante rudimentarias. '. La mayoría de los lenguajes de programación modernos permiten trabajar directamente con XML. No podemos decir lo mismo de PHP.

gracias a que son capaces de colaborar entre ellas. Y de todas estas herramientas diferentes hemos sido capaces de lograr lo impensable. diferentes lenguajes de programación. servidores de bases de datos. . Espero que. Recuerde: aún queda mucho que aprender. hemos trabado contacto con una gran cantidad de productos diferentes. El espacio del que disponemos en una guía de estas características es limitado y sin embargo.Epílogo Durante este libro hemos recorrido una gran cantidad de tecnologías de diferente naturaleza: servidores Web. todo esto haya servido para que pierda el miedo y sepa que tiene frente a sí una gran cantidad de posibilidades si dispone de las herramientas adecuadas. al menos.

Table of Contents Dedicatoria Agradecimientos Introducción Cómo usar este libro Prólogo 1. Tipos de datos 2. Variables 2.4. InnoDB 3. Instrucciones condicionales 2. Modificación 3.6. Trabajando con PHP 2.1.6.4.8.3. Precedencia de operadores 2.5. Concatenación de cadenas 2.1. Operadores de comparación 2.5.3. Creación de la base de datos 3.6.3.2.2.1.5.3. Cambios de tipo 2. MyISAM 3.1.1.4.5.5.2. Creación de la base de datos 1.5. Estructura de un archivo PHP 2. Operadores de incremento 2.2.2.5.1.2.2.3. Tipos de datos 3.7.4.1.4.4.5.4.1. Salida de bucles 3.3. Editores 2.2.2. XAMPP 1. Operador básico de asignación 2. Bases de datos 3. Operaciones sobre tablas 3.3.2. Funciones de salida 2.3. Base de datos de ejemplo 3. Inserciones 1.6.6.3. ¿Qué es una tabla? 3. Comentarios 2. Operadores 2.3.1.6.5.3. Tipos de tabla 3. Instrucciones iterativas 2. Trabajando con MySQL 1.1.5. Tipos de texto . MySQL y PHP 1.3. Herramientas de consulta 3.5.5. Operadores lógicos 2. Borrado 3.2.1.3. PHP 2. Escapar de HTML 2.1. Creación 3. Puesta en marcha de XAMPP 1.4.3.3. Instrucciones de control 2.6.5. Introducción 2. La primera aplicación 1.1. MySQL 3. Creación de la tabla 1.3. Operadores aritméticos 2.

Devolución de valores 4. Borrado 6.2. Orientación a objetos 4. El ejemplo 5.4.5.3.2.2.2.2.2. PHP orientado a objetos 4.6.3.5.2. Columnas de incremento automático 5. Clases 4.3.1. Conjuntos de registros .1.1. Operadores aritméticos 6. MySQL Workbench 5. Listados de una tabla 6.2.3. Relacionar tablas 5. Tipos numéricos 3.3.1.2.1. Cambiando la precedencia 6. Inclusión de archivos 4.1.3.3.2.1. Inserciones 6. El ciclo de la vida 7. Instalación 5. Operadores lógicos 6.3.1.4.3.3.2.3. El ejemplo finalizado 6.1.3. Creación de la base de datos 6.2. Operadores 6. Actualizaciones 6.2.4.4. Relaciones muchos a muchos 5.1. Borrados 7.4.3. Operación 7.2.1.2.1. Inserción de datos 6. Consultas de selección 6.1. Conexión 7.4.3. Creación de tablas con MySQL Workbench 5. El valor NULL 5.2.1. Divide y vencerás 5.2. Conceptos varios 5. Objetivos 5. La base de datos de ejemplo 6. División de tablas 5.1. Manipulación de bases de datos 6.2.7. Índices 5.2.1. Parámetros 4. Limitaciones 5.1.1.6.3.4.4. El modelo relacional 5.5.4.2.4. Funciones 4.3.3. Operadores de comparación 6. Trabajando con funciones 4.1. Listados de varias tablas 6.2. Más allá de las clases 5.1. SQL 6.4.1. Acceso mejorado a MySQL 7.4. Creación 6.3.2. Desconexión 7.6.1.3. Fechas y horas 4. Diseño de bases de datos 5. PHP y MySQL 7.2. Claves primarias 5.3.

Consultas escapadas 7.1.2.4. Sintaxis 12.3. Parámetros 11.7.6. Creación 11. Ventajas 7.2.2.1. Formularios 8.1.6.5.1.3.4.6. Valores de configuración 7. Introducción 11.1. Sintaxis 11.3.3.2.3.1.1. Otra plantilla 11.1. Inserción 12. Formularios HTML 8.3. Desencadenadores 12.2. La página PHP 10.1.3.2. Archivos de registro 9. Recuperación de información 8. Archivos de registro en tablas 9.3.3.3.2. Funciones almacenadas 11. Opciones de PHP en Apache 8. Inconvenientes 7. Base de datos reducida 11.3.3. Un sencillo ejemplo 11.3. Plantillas 10.6.1.4.6. La plantilla 10. Delimitadores 11.3.2.2.1.3.1.2.2.1.2. Instalación 10. Control en el lado del cliente 9. Inserción 11.1. MySQL y los errores 9.2. Un pequeño ejemplo 10.6. Excepciones 9.1. Configuración 7.2.1.1.2.1. PHP y los errores 9.1.1. ¿Qué es Smarty? 10. Eliminación 11. Introducción 12.4. Creación 12. Base de datos reducida 12.3.1.3. Otras consultas 7. Utilización desde PHP 12.1.3. Lista de géneros 10. Envío de información 8. Configuración 9.1.2. Creación . Elementos de un formulario 8.1.5. Procedimientos almacenados 11.2. Creación de formularios 8.6. Inserción de registros 8.2.6.5.3. Gestión de errores 9.3.5. MySQLi y los errores 10. Funciones 9.4. Creación 11. Cómo funcionan los formularios 8.1. Modificación de la configuración 7. Variables 11. Idioma de los errores 9.2.

Sintaxis 13.3.3.1. XPath 14.1. Borrado 13. XML 14.2.3. ExtractValue 14.2.3.3. Modificación 13.1. Etiquetas 14. Eliminación 13. Ejemplos 13.4. Ejemplos 12.3.3. Introducción 13. Funciones XML 14.3. Vistas 13.2. Eliminación 13. Apertura 14.2. Eliminación 12. Creación 13. Acceso a atributos Epílogo . Modificación 13.4.4.1.3.1. Recorrido de nodos 14.3.2.3.2.3.3. Partes de un documento XML 14. UpdateXML 14. Utilización desde PHP 14.1.2.4.1.2.3. Datos de ejemplo 14.3.1.12. XML desde la línea de órdenes 14.3. SimpleXML 14.4.2. ¿Qué es XML? 14.2.2.2. Actualización 12.3.1.2. Inserción 12. Creación 13.3.1.4.