Desarrollo Web Con PHP y MySQL

March 24, 2018 | Author: Xavi Real | Category: Php, Web Server, My Sql, World Wide Web, Technology


Comments



Description

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. con extremidades copadas de conocimientos y ansioso por atravesar el umbral de la puerta de mi casa. Eligió su lista de canciones favoritas y comenzó a escuchar música. carentes de perspectiva para entenderlos. sin interrogantes y sin perspectiva. Veo pasar todo ante mí fluyendo sin aparente esfuerzo. Nos estamos convirtiendo. Todo según lo esperado. En esta dirección he debido hacer un ejercicio de autocrítica. soluciones. Y en esta senda me topo con algo que uso a diario para mi trabajo. en muchos casos. Qué difícil es entender que nuestra obligación pasa tanto por respetar lo que hay como por arrasarlo para construir algo nuevo. por qué usaron ese plástico para distribuirlo. herramientas. Con naturalidad. de opciones. La velocidad a la que se suceden los acontecimientos en nuestros días nos dejan. No dar nada por supuesto. . por qué tiene ese tamaño si suelo quedarme con ganas de coger otro. con estructura y vida propia. Pensar sin muchos datos. con claridad. con el paso del tiempo y con la ayuda de las nuevas tecnologías. Comienza mi jornada delante del ordenador y algunos actos se suceden a lo largo del día. Todo ocurrió con la misma coherencia y trasparencia que cuando tomó el batido en sus manos. A continuación. que es lo que se espera cuando uno saca una bebida del frigorífico. 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. relleno un formulario. Parar y pensar un poquito. Estaba frío. A veces tiendo a imaginarme lo que Internet ofrece como un ente físico. en auténticos devoradores. publico en otro. dos electrodomésticos le ofrecieron lo que él buscaba.Prólogo Perspectiva. de imágenes. de contactos. En el día de ayer mi hijo de nueve años se acercó al frigorífico de la casa y sacó un batido. Perspectiva para entender que las cosas no suceden porque sí. accedo a un foro. Lo abro y allí está la respuesta. En apenas 30 segundos. La música estaba donde debía y hacía lo que se esperaba que hiciese. un día tras otro: consulto una enciclopedia. Qué difícil es parar y cargar una dosis de perspectiva. que me ofrece información. comento en un blog. Cuestionarme por qué está frío el batido. Recibir y ofrecer. No aceptar nada porque exista desde hace tiempo. 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. Pensar en lo que hago cada día. por qué el color del envase coincide con el del contenido. se sentó delante de un portátil que suele estar en la cocina y abrió Spotify. Me siento como un funcionario del control de aduanas de Andorra. sin Wikipedias a mi alcance. Devoradores de datos. Yo solito. sin Google. levantándose cada día para hacer que todo siga funcionando. sigan pasando páginas y que puedan encontrar en lo que viene a partir de este momento al menos una respuesta a tanto interrogante. pero ya advertí que era el momento de parar y pensar. lo que me dejan es su eficiencia. Lo reconozco con cierta vergüenza. Si he de ser sincero. Conocerlo nos permitiría hacerlo crecer.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. Lo usamos a diario con la misma naturalidad que tenemos al coger el mando a distancia de la televisión. ¿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. Pero a mí me da igual y. Doy fe de que no es mala compañía. 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. pues durante muchos años me fue muy ajeno. Pero es que no puedo dejar de imaginarme a una legión de programadores. Su engranaje es sublime. semejante en número y constancia a un piélago de orcos camino del Abismo de Helm. 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. aunque hoy lo que pretendo es rendir un pequeño homenaje a aquellos que hacen posible que esto siga creciendo. para mí no son más que un conjunto de letras reunidas con poca gracia. Ignacio Cerro . Creer que está a nuestro alcance el participar de la batalla no es algo insensato. Entenderlo un poco nos ayudaría a respetarlo. Les dejo ahora con uno de esos disciplinados orcos. conmigo. Por este motivo les invito a que. 1 MySQL y PHP Para el impaciente. Vamos a desarrollar una pequeña aplicación Web que permita gestionar nuestra videoteca. Las aplicaciones Web que veremos se componen de varias partes: . No queremos engañarle. extraer los datos almacenados en ella y mostrarlos en una página Web. de su futuro. Este trabajo formará luego parte de la aplicación que gestionará nuestra videoteca. MySQL y PHP son grandes productos por sí solos. 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. 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. aprenderá a utilizar de forma conjunta ambas tecnologías. 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. así que iremos por partes: nos limitaremos a crear una aplicación para realizar el mantenimiento de una lista de géneros cinematográficos. Plantéese la lectura de este capítulo como la de una novela: le narraremos una historia que habla del futuro. si cambia alguno de los datos de una tabla. pero juntos forman una de las parejas más formidables del mundo del software libre. utilizando PHP como unión. 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. 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 capítulo está pensado para aquel lector que no está muy seguro de lo que podrá encontrar en este libro. Una vez tenga esos conocimientos básicos. Pero es mejor concretar un poco más. Y veremos que. Veremos que es posible tener una base de datos. de las maravillas que podrá construir tras el trabajo que supondrán los capítulos siguientes a éste. Sería muy ambicioso por nuestra parte comenzar esta guía con un trabajo de tales características. 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. 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. Figura 1. Linux o Mac OS X.2. Entre ellos. por lo que todos podemos utilizarlo en Windows. La figura 1. que se trata del servidor Web más utilizado en el mundo y es libre. Posteriormente poblaremos dicha base de datos con las tablas y los registros necesarios. Un servidor Web: Aunque podríamos escoger cualquier servidor Web que permita la ejecución de PHP. PHP: El nexo de unión entre la base de datos y los clientes potenciales de nuestra aplicación Web. . Aplicaciones Web Por lo tanto. Clientes: Los clientes son los usuarios de nuestra aplicación Web.1.Un servidor de bases de datos: MySQL ha sido la elección lógica. debido a su potencia y a que es uno de los más utilizados. Una base de datos: Contiene las tablas y los datos con los que queremos trabajar. si nadie (persona o máquina) va a utilizarlo quizá su existencia carezca de sentido. nos decantamos por Apache por varios motivos.1 muestra las relaciones existentes entre los diferentes elementos que acabamos de enumerar. Nuestro desarrollo va a comenzar con la creación de la base de datos. podremos comenzar con a trabajar. Al terminar podremos contemplar algo parecido a lo que se puede ver en la figura 1. Tras ello. 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. 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. Sea un desarrollo hecho para nuestro propio disfrute o para el de los demás. Linux y Mac OS X). PHP y Perl. Apache. la opción recomendada para un servidor de producción (es decir. PHP y MySQL con facilidad. en cualquiera de los sistemas operativos antes mencionados: XAMPP. Linux o Mac . Obviamente. como en WAMP o LAMP. en que todo funciona como se espera. Se utiliza una X para representar al sistema operativo y no una W (de Windows) o una L (de Linux). y concéntrese en el contenido de la misma. Puede encontrarlo en la página: http://apachefriends. para que se pueda poner manos a la obra necesita disponer de un sistema con Apache. XAMPP no es algo único. Francamente. En segundo lugar. Existen muchas otras soluciones para instalar Apache. se trata de un trabajo que es necesario dejar en manos de expertos capaces de garantizar la seguridad y el rendimiento del servidor. 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. a su aspecto.Figura 1. XAMPP es ideal para entornos de desarrollo. existe una forma rápida y sencilla de instalar y configurar todo esto. de un plumazo. diseño). La razón por la que lo utilizaremos en este libro es múltiple: Está a su disposición ya utilice Windows. En primer lugar. aunque le parezca mentira. MySQL. 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.2. programación) de la representación (aspecto. Nuestro objetivo Not a: No preste atención al diseño de la página. configuración y mantenimiento de cada uno de los componentes de forma individual. En este libro no utilizaremos esa última P. XAMPP Como acabamos de comentar.org/ Not a: XAMPP son las siglas de X. En el capítulo dedicado a Smarty aprenderemos a separar la lógica (funcionamiento. Pues. Sin embargo. Un par de aclaraciones. 3. podrá seguir los ejemplos de este libro siempre y cuando disponga de un equipo con Apache. El equipo responsable de su desarrollo se preocupa de mantenerlo actualizado para que ofrezca la última versión de cada componente. extraer su contenido y ejecutar una orden para poner en marcha los servicios necesarios. que puede ver en la figura 1. phpMyAdmin. . Como podrá comprobar. según se comenta en la página dedicada a la versión para Windows de XAMPP. Figura 1.html Cuando termine de descargar el instalador haga doble clic sobre él y siga los pasos del mismo.OS X. Instalación de XAMPP en Windows Advert encia: ¿Por qué es el paso más complejo? Porque. C:\xampp. 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. Puesta en marcha de XAMPP Independientemente del sistema operativo. por ejemplo. No es obligatorio que use XAMPP. Proporciona una interfaz de usuario muy fácil de utilizar para poner en marcha y detener los servicios.org/en/xampp-windows. El más complejo de ellos. una aplicación Web para la administración de bases de datos MySQL. Incluye multitud de herramientas como. se trata de un proceso muy simple. de forma individual.3. 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. consiste en seleccionar la ruta en la que se instalará XAMPP. PHP y MySQL correctamente instalados y configurados. por ejemplo. 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.Las opciones predeterminadas de los pasos del asistente serán las más adecuadas en la mayoría de los casos. Como resultado. 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 . Responda que sí: podrá ver un cuadro de diálogo similar al que muestra la figura 1. Utilícelo para detener el servicio correspondiente cuando lo desee. sustituyendo X e Y por los números correspondientes a la versión de XAMPP que haya descargado: tar xvfz xampp-linux-X. 5. Cuando esté en funcionamiento aparecerá una etiqueta a su derecha con el texto Running y el nombre del botón cambiará por Stop.org/en/xampp-linux. XAMPP se encontrará en dentro de la carpeta /opt . a continuación.gz -C /opt 4. Por último. Figura 1. El panel de control de XAMPP se encuentra dentro del menú Inicio. que se encuentra en la página: http://apachefriends.4. Cuando el proceso de instalación concluya se le ofrecerá la opción de ejecutar el panel de control de XAMPP. 3. Utilice la siguiente orden para extraer su contenido. Haga clic en Start para poner en marcha un servicio.html 2. Inicie una sesión como administrador del sistema o utilice la orden su para obtener sus privilegios. ejecute la orden /opt/lampp/lampp start para poner en marcha XAMPP y /opt/lampp/lampp stop para detenerlo. Descargue la versión para Linux de XAMPP. 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.tar.4. en Apache Friends>XAMPP>XAMPP Control Panel.Y. sobre Estado en la parte izquierda de la página. para detener los servicios deberá ejecutar. Para ello abra un terminal y ejecute la orden sudo /Applications/XAMPP/xamppfiles/mampp start . Vaya allí con su cliente Web favorito.6 muestra el resultado de hacer clic sobre Español y. la orden sudo /Applications/XAMPP/xamppfiles/mampp stop.org/en/xampp-macosx.5. también desde un terminal. Cuando el proceso de instalación concluya sólo restará poner en marcha los servicios. al igual que en los dos apartados anteriores. uno por cada idioma disponible. es necesario decir que la instalación de XAMPP en Mac OS X es muy sencilla: 1.pkg y siga los pasos del instalador. Figura 1. Puesta en marcha en Mac OS X De nuevo. La figura 1. Una vez la imagen de disco se monte haga doble clic sobre el archivo XAMPP for MacOS X.es el deseado. algo que puede ocurrir si en su equipo ya están instalados y en funcionamiento Apache o MySQL. Puesta en marcha de XAMPP en Mac OS X 6.html 2. Con independencia del sistema operativo que utilice. De igual forma. Descargue la versión para Mac OS X de XAMPP. Podrá ver algo parecido a lo que muestra la figura 1. dedicados a Windows y Linux. XAMPP estará disponible a través de la dirección http://localhost/.5. podrá ver una página de presentación con diferentes enlaces. que se encuentra en la página: http://apachefriends. 3. 4. después. . Haga doble clic sobre el archivo DMG descargado. 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. Inserciones . sobre el que está el puntero del ratón en la figura 1.13.14. posteriormente.Figura 1. se le preguntará que confirme la ejecución de la instrucción SQL correspondiente. Crear tablas con MySQL Administrator Cuando haga clic en el botón Apply Changes. Para ello. Figura 1.14. el aspecto de este último al seleccionar el nodo Catalogs y. videoteca.13. Tanto si creó la tabla con SQL como si se ayudó de la interfaz de MySQL Administrator. debe ser similar al que puede verse en la figura 1. haga clic en Execute. Nuestra nueva tabla Ya puede realizar las primeras inserciones de datos. 'Aventuras'). ¡Oh. 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. tiene la opción de utilizar las herramientas de MySQL Administrator. aventuras y drama. puede añadir los valores necesarios para representar los géneros de ciencia ficción.15.15. INSERT INTO genero(nombre. 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. Seleccione el nodo Catalogs en el panel de la izquierda. por último. Figura 1. Puede verlo en la figura 1. descripcion) VALUES('D'. Por ejemplo. en lugar de una ficha del tipo Script hay una del tipo Resultset con una consulta ya introducida y ejecutada. descripcion) VALUES('A'. además de SQL. haga clic sobre la base de datos videoteca y. sorpresa! Se ha abierto MySQL Query Browser pero. 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á. INSERT INTO genero(nombre. INSERT INTO genero(nombre. 'Ciencia Ficción'). De nuevo. 'Drama').15). Haga clic sobre el botón Edit . Inserción de datos en MySQL Query Browser . descripcion) VALUES('CF'.El último paso que tiene que dar antes de comenzar a trabajar con PHP es poblar la tabla de géneros con algunas entradas. 16. "Diseño de bases de datos". La figura 1. Cuando termine de introducir los datos de los géneros haga clic en el botón Apply Changes. también editar los existentes. . 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.16 se está insertando el primero de los géneros. MySQL se encarga de asignar ese valor automáticamente debido a que uno de los modificadores de su tipo es AUTO_INCREMENT . Para saber más al respecto consulte el capítulo 5. 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. por ejemplo. en la figura 1. 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).17 muestra el aspecto de la ventana de consultas después de introducir los tres nuevos géneros.Not a: Las fichas de tipo Script de MySQL Query Browser permiten ejecutar instrucciones SQL que no devuelven resultados como. Utilice las fichas de tipo Resultset para realizar consultas en los datos contenidos en las tablas de una determinada base de datos. MySQL Query Browser entrará en el modo de inserción de datos. las de creación de tablas o inserción de datos. Figura 1. Por ejemplo. Figura 1. 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. De esta forma es sencillo reconocer a las funciones de este grupo. tiene tres registros. Hemos completado el primer paso de nuestro pequeño proyecto. Por ahora sólo veremos la primera. Y tiene una limitación: sólo permite acceder a servidores MySQL modernos. ya que esta nueva interfaz mejorada de acceso a MySQL viene en dos sabores: funcional y orientado a objetos. una descripción y un número que los identifica de forma única. 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. Para ello utilice la función mysqli_connect(). Puede hacerlo pulsando la combinación de teclas Control-F4 o seleccionando la opción Exit del menú File. El siguiente paso consiste en utilizar PHP para acceder al contenido de esta tabla y poder mostrar su contenido en una página Web. Los tres géneros de partida Cierre MySQL Query Browser. La función mysqli_connect() recibe como parámetros la dirección en la que se encuentra el servidor (o su nombre). de la que hablaremos detenidamente en posteriores capítulos. Así que abra su editor de textos favoritos: ¡vamos a programar! Trabajando con PHP La anterior versión de PHP. cada uno de ellos con un nombre. ha de establecer una conexión con el servidor. en una tabla llamada genero. La mayor parte de ellas estaban relacionadas con la programación orientada a objetos.17. incorporaba novedades realmente interesantes. Acceder a MySQL a través de esta interfaz es tarea muy sencilla. la 5. La i latina final viene de improved (mejorado). el nombre de usuario. Dentro de ella. la clave de acceso y el nombre de la . Not a: Aunque quizá sí hay relación. no queda mucho por hacer. En primer lugar. Esta nueva forma de acceder tiene nombre: MySQLi. Not a: Todas las funciones de la interfaz de acceso a MySQL que vamos a ver comienzan con el prefijo mysqli_. tan solo utilizar las herramientas que PHP nos ofrece para conectar con el servidor de bases de datos. Realmente. Dispone de una base de datos. videoteca. . 'videoteca' ). . de forma que informamos del error en la conexión y terminamos el programa llamando a exit(). Si es así es que la conexión no se ha realizado correctamente. Schemata. En el código anterior suponemos que el servidor está en el mismo ordenador en el que estamos trabajando (localhost ). en el panel de la derecha. el resultado de llamar a esta función es FALSE . como ya hemos comentado anteriormente. El siguiente paso es obtener todos los valores almacenados en la tabla genero. Para ello. El nombre de la base de datos tiene que ser videoteca en este caso. if ($conexion == FALSE){ echo('Error en la conexión.18 puede ver el resultado de ejecutar esta consulta utilizando MySQL Query Browser. Tras llamar a mysqli_connect() comprobamos si el valor de $conexion es FALSE . puede utilizar el siguiente código para realizar la conexión: <?php $conexion = mysqli_connect( 'localhost'. En caso de error. Si todo ha funcionado correctamente. que el nombre de usuario es root y que no tiene clave (un claro problema de seguridad pero. } .'). exit(). Así le indicará a MySQL Query Browser que quiere trabajar con esa base de datos. Sustituya las credenciales de acceso por las correspondientes a su entorno de trabajo. En la figura 1.. Dicho esto. se trata del funcionamiento predeterminado de XAMPP). el resultado de esta función nos permitirá realizar operaciones en el servidor de base de datos. haga doble clic sobre la base de datos videoteca.base de datos con la que queremos conectar. A continuación ejecute esta consulta SQL: SELECT * FROM genero. 'root'. Pero si todo ha ido bien podemos continuar para bingo. ''. Advert encia: Es conveniente dejarlo todo como estaba antes de comenzar el programa. A continuación compruebe que $resultado no sea FALSE . $resultado = mysqli_query( $conexion.').18. ... mysqli_close($conexion). o FALSE en caso contrario. guardando el valor de respuesta en una variable ($resultado).. como en la función de conexión. 'SELECT * FROM genero' ). El resultado de esta función. Si lo es. es un objeto si se pudo ejecutar la consulta. if ($resultado == FALSE){ echo('Error en la consulta. si obtiene un conjunto de registros.. Esta función recibe como parámetros el valor devuelto por mysqli_connect() y una cadena de caracteres que contenga la consulta a ejecutar. debe cerrarla antes de terminar el programa. cierre la conexión (con mysqli_close()) y salga del programa con exit(). exit(). } . debe liberar la memoria que hayan ocupado. Podría usarla así: . así que informe de ello. Primero llame a la función mysqli_query() con los parámetros necesarios. Recuperando todos los registros Puede utilizar esa consulta desde PHP gracias a la función mysqli_query(). Este fragmento de código es muy similar al anterior.Figura 1. es que ha ocurrido un error al realizar la consulta. Si abre una conexión con un servidor MySQL. $fila[0].Si no ha ocurrido ningún error. como dijimos.. dentro de una matriz. 'SELECT * FROM genero' ). if ($conexion == FALSE){ echo('Error en la conexión. Es decir. completo: <?php $conexion = mysqli_connect( 'localhost'.. Si la función devolvió algún registro. 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. $fila[2] ). La función mysqli_fetch_row() le permite recuperar los registros obtenidos uno por uno.. exit(). $fila será diferente de FALSE . La siguiente llamada mysqli_fetch_row() devuelve el siguiente registro. así que ejecute la función printf(). Cuando ocurre eso. .. 'videoteca' ). mysqli_free_result($resultado). Para terminar. Sólo tiene que mostrarlos. while($fila = mysqli_fetch_row($resultado)){ printf( "(%u) %s . $fila[1]. } $resultado = mysqli_query( $conexion. de forma que puede utilizarla en un bucle while: .'). 'root'. que muestra en la página los valores de ese registro. $fila valdrá FALSE y saldrá del bucle. y así hasta que no quede ningún registro por mostrar. el código de este ejemplo.. deje todo como estaba. llame a la función mysqli_fetch_row() y guarde el resultado en $fila. mysqli_close($conexion).%s<br/>". ?> A continuación. ''. liberando el espacio ocupado por el resultado de la consulta y cerrando la conexión con la base de datos: .. } . Figura 1. mysqli_close($conexion). que se encuentra dentro de aquella en la que haya instalado XAMPP.php.'). $fila[1]. } while($fila = mysqli_fetch_row($resultado)){ printf( "(%u) %s . . ?> <table border="1"> <tr> <th>id</th> <th>nombre</th> <th>descripcion</th> </tr> <?php while($fila = mysqli_fetch_row($resultado)){ printf('<tr>').php. ?> Guarde esta página en la carpeta htdocs.. la que indica nueva línea: <br/>. $fila[0].). vuelva a escribir el bucle while. exit().. Pero eso podemos solucionarlo. Sustituya el código del bucle por el siguiente: .%s<br/>". en PHP Y ahora un detalle curioso: nuestra primera página PHP no ha tenido más que una etiqueta HTML. Entonces. if ($resultado == FALSE){ echo('Error en la consulta.19. visite la página http://localhost/generos. $fila[2] ). pero ahora use tablas. El resultado puede verse en la figura 1. Los géneros.19. mysqli_close($conexion). } mysqli_free_result($resultado). con el nombre generos. php. es el siguiente: <?php $conexion = mysqli_connect( 'localhost'.php en la misma ubicación que generos. 'SELECT * FROM genero' ). } $resultado = mysqli_query( $conexion. if ($conexion == FALSE){ echo('Error en la conexión. } ?> <table border="1"> <tr> <th>id</th> <th>nombre</th> <th>descripcion</th> </tr> <?php while($fila = mysqli_fetch_row($resultado)){ printf('<tr>'). exit().printf('<tr>'). El código completo de esta nueva página. 'root'. .'). printf( "<td>%u</td><td>%s</td><td>%s</td>".'). } ?> </table> <?php .. que debe guardar con el nombre generos2. exit(). $fila[2] ). $fila[1]. $fila[0]. printf('</tr>').. mysqli_close($conexion). if ($resultado == FALSE){ echo('Error en la consulta. 'videoteca' ). ''. facilitando la tarea tanto a programadores como a diseñadores. $fila[2] ). $fila[0]. El resultado es que nuestra tabla tendrá un nuevo registro.20. 'Terror'). printf( "<td>%u</td><td>%s</td><td>%s</td>". descripcion) VALUES('T'. como puede ver en la figura 1. El contenido es el mismo. pero la apariencia cambia. Utilice MySQL Query Browser para ejecutar el código anterior.20. 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. con tablas Y ahora.printf('<tr>'). printf('</tr>'). veremos algunas de las opciones que tenemos para separar la lógica de la representación. Figura 1. } ?> </table> <?php mysqli_free_result($resultado). mysqli_close($conexion). $fila[1]. por fin. Nuestro ejemplo.21. lo más espectacular: contemplar cómo cambia la página PHP cuando añadimos algún nuevo registro a la tabla genero. La siguiente instrucción SQL inserta un nuevo registro: INSERT INTO genero(nombre. ?> El resultado de cargar esta nueva página puede verse en la figura 1. sin necesidad de cambiar el código. En el capítulo dedicado a las plantillas. . Figura 1.21.Figura 1.22. en PHP Impresionante. .22. ¿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. Un nuevo género. El resultado debería ser algo parecido a lo que puede ver en la figura 1. PHP está más cerca de lenguajes como C++ o Java que del propio HTML. Estas decisiones las realizaremos utilizando instrucciones condicionales. como texto. realizando operaciones sobre ellos (sumas. 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.com/. etcétera. a su vez. que permitirán realizar la misma acción varias veces. Este lenguaje sirve para describir las propiedades y la ubicación de una serie de elementos dentro de una página Web. aunque en ocasiones no nos quedará más remedio. será entretenido. se escriben en el lenguaje HTML. Se trata de una excelente combinación de las mejores características de los lenguajes de programación más utilizados. También utilizaremos instrucciones iterativas. con un único objetivo: que la programación de páginas dinámicas sea pan comido. Entre estas acciones puede estar el mostrar o no información en una página Web. imágenes. 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.acronymfinder. Durante este capítulo nos concentraremos en las características de PHP como lenguaje de programación. etcétera). Usaremos el resultado de esas manipulaciones para tomar decisiones. restas. intentando evitar en lo posible la jerga de los programadores. Al terminar este capítulo tendrá las nociones básicas necesarias para comprender cualquier programa escrito en PHP y.2 PHP Aunque se utiliza para crear páginas Web dinámicas. Por el contrario. todas ellas encuentran su traducción en http://www. avanzará un poco más hacia el objetivo final: combinar la potencia de MySQL con la flexibilidad de PHP. si decide quedarse con nosotros. Repasaremos los conceptos básicos de programación tal y como los entiende PHP. Después manipularemos esos valores. HTML son unas siglas que significan "lenguaje de marcas de hipertexto" (Hypertext Markup Language). como qué acciones debemos realizar. Veremos cómo guardar valores en variables y de qué tipo pueden ser. Truco: ¿Asustado por la cantidad de siglas que se nos vienen encima? No tema. no tenga miedo. podrá ver lo que aparece en la figura 2. Figura 2. Una página HTML muy sencilla Not a: Si leyó el capítulo anterior y decidió seguir nuestra recomendación de utilizar XAMPP. 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). no se preocupe. de su interés. a los que abreviadamente se les llama enlaces. son estas relaciones entre diferentes páginas las que hacen de la Web una herramienta verdaderamente única. puede seguir leyendo sin miedo a perderse.Por ejemplo. Mediante estos enlaces podemos vincular unas páginas con otras que pueden estar en nuestro sitio Web o en otro diferente. Como ya sabrá. Si no es el caso.1. hemos visto qué son las páginas HTML: . En este ejemplo puede comprobar que el lenguaje HTML utiliza etiquetas. Si la guarda con el nombre prueba. Estas etiquetas se distinguen del resto porque están entre los símbolos menor que (<) y mayor que (>).1. Muy por encima. Consejo: Se supone que si está leyendo esta guía es porque ya tiene unas nociones básicas de HTML. mientras que la etiqueta h1 permite indicar que el texto será un encabezado de nivel 1. Independientemente de la calidad del contenido de una página. el siguiente es un fragmento de código en lenguaje HTML. la carpeta de archivos del servidor Web es ht docs y se encuentra dentro de aquella en la que decidiese instalar XAMPP. 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.</h1> </body> </html> Este código describe una página muy sencilla. <html> <head> <title>Prueba</title> </head> <body> <h1>Esto es una página HTML.html y la pone en la carpeta de archivos del servidor Web. php. El siguiente código realiza esta tarea: La hora es: <?= date('H:i:s') ?>. El resultado se puede ver en la figura 2. ¿Cómo encaja PHP en todo esto? PHP son también unas siglas.2. cuando utiliza un cliente Web (como Internet Explorer o Firefox) para ver una página hay tres elementos en juego: usted. Un ejemplo puede ayudarnos a entender mejor para qué sirve PHP. frente a las páginas HTML. con PHP puede crear programas cuyo resultado sea código HTML. Seguramente lo primero que hace es escribir la . Y nada más sencillo que crear una página que muestre la hora. Como ya sabrá. un chiste de informáticos que difícilmente hace gracia al resto del mundo.archivos de texto con unas etiquetas especiales que determinan la posición y el formato de sus elementos. Not a: Aunque vamos a concentrarnos en las capacidades de PHP para producir páginas Web. Vamos a intentar aclarar aún más las diferencias que hay entre HTML y PHP. Son unas siglas recursivas: están dentro de la definición. con PHP Si recarga la página. El logotipo de PHP Como su propio nombre indica. Por eso a las páginas PHP se las conoce como páginas dinámicas.net/ si desea más información al respecto. Figura 2. el resultado de una misma página PHP puede ser distinto dependiendo de algunos factores. Puede visitar http://gtk. La figura 2. Como consecuencia. PHP es un preprocesador de hipertexto. El contenido de la página depende de la hora a la que ésta se cargue. comprobará que la hora ha cambiado. tenga presente que no es lo único que puede hacer.3. Figura 2. Por poner un ejemplo. que son estáticas. Ese resultado puede variar en función de la lógica del programa.2 muestra el reconocible logotipo de PHP. el medio (Internet) y el servidor Web. La hora. PHP también puede usarse para crear aplicaciones de escritorio. pulsando F5.3. que vienen de PHP: Hypertext Preprocessor (preprocesador de hipertexto). Es decir. pulsar la tecla Intro. Figura 2. Una página dinámica Sólo hay una diferencia entre las figuras 2. pero como sabe se trata de una muy importante. Allí donde los encuentre. Ahora que hemos abierto boca.4. seguro que tiene ganas de más. así que invoca al preprocesador de PHP y le pasa el control. La figura 2. realizará las operaciones que el creador de la página haya indicado.4 y 2. Editores . Cuando termine de procesar la página. En un momento iremos a ello.4 ilustra el proceso. Figura 2. El servidor se da cuenta de que su extensión no es la de una página HTML. Éste localiza esa página y la devuelve tal y como la encuentra. Una página estática El proceso es ligeramente diferente si se trata de una página PHP. a continuación. que será lo que el servidor Web envíe como respuesta a quien le haya pedido la página PHP.5. Todo es igual hasta que el servidor localiza la página que le pedimos. En ese momento. a través de Internet.5. Algo parecido a lo que podemos ver en la figura 2.dirección de la página que quiere ver (su URL) y. Sabe que tiene que procesarla antes de devolverla. devolverá el resultado. pero antes vamos a buscar algunas herramientas que puedan ayudarle en la tarea.5. Este preprocesador busca algunos caracteres especiales. se envía la petición al servidor. también hace falta un servidor de páginas Web. Nuestra recomendación es que utilice Eclipse PDT (en concreto. asegúrese de que. Y nada más. Aptana PHP. Existen otras herramientas desarrolladas exclusivamente para editar PHP que pueden ser de mucha más ayuda en las tareas de programación. localizar errores. como decimos. Posiblemente el más completo de todos sea Zend Studio. están NetBeans. Fíjese en que el color de las etiquetas <? y ?> y de lo que aparecen entre comillas simples es diferente del resto. Como es costumbre en el mundo del software libre. por sólo mencionar algunas.6 el aspecto que tiene el fragmento de código que dio como resultado la página que pudimos ver en la figura 2. Un editor de estas características no es sólo un editor: es un entorno de desarrollo o IDE (Integrated Development Environment. la clave es que encuentre uno con el que se sienta cómodo. Codelobster o Nusphere PhpED. como el bloc de notas de Windows. existen muchas otras alternativas tanto a Zend Studio como a Eclipse PDT. la versión 2). Figura 2. etcétera. algo de gran ayuda para encontrar determinadas secciones de código. las cadenas de texto. las alternativas son muchas. entorno integrado de desarrollo).6. los comentarios. existen muchas otras alternativas. Si puede permitirse pagar los casi 400 euros que cuesta. Casi todos los IDE tienen muchas características en común. Pero. una búsqueda en Google bastará para que encuentre más editores de PHP.3. tendrá un color diferente. queremos enseñarle en la figura 2. un producto multiplataforma libre que puede encontrar en la dirección: http://eclipse. como mínimo. Aunque estos son ejemplos de editores de texto decentes. pero se supone que ya contamos con él. vi en Linux o TextEdit en Mac OS X. Aunque más avanzado el capítulo veremos ejemplos en los que el resalte de sintaxis será más obvio. le proporciona las siguientes herramientas: Resalte de sintaxis: Las palabras clave del lenguaje. Más que la potencia del editor. Si el IDE que va a utilizar no es ninguno de los que le hemos recomendado.org/pdt/ Not a: Repetimos. cada diferente elemento del código fuente de un archivo PHP.Para programar en PHP sólo hace falta un editor de texto. editores de texto. Resalte de sintaxis . Sí. no lo dude: evalúelo y adquiera una copia si lo encuentra satisfactorio. Entre. Pero no se limite a estas. son precisamente eso y sólo eso. Y una memoria asombrosa hace falta para recordar el nombre de todas ellas. pero no se preocupe que sus preguntas tendrán respuesta. En el ejemplo con el que mostramos la hora en una página Web utilizamos la función date(). como puede verse en la figura 2. La figura 2. Lista de funciones Asistente de código para argumentos de función: De forma similar al asistente para nombres de función. Bueno.7. realmente asombroso. 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. Podrá ver tanto los argumentos como el valor que devuelve la función. Por ahora baste con decir que las funciones permiten obtener valores o realizar tareas concretas. Argumentos de una función Ayuda integrada: Los dos asistentes para funciones son muy útiles. la verdad es que aún no hemos visto qué es una función. basta con saber al menos cómo empieza para obtener una lista de la que seleccionar la que desee. el IDE ya le muestra su nombre completo. A medida que programe con PHP le resultarán hasta imprescindibles. un asistente de código permitirá ver en una lista desplegable cuántas funciones comienzan con los caracteres que ha escrito. a falta de mejores palabras.Asistente de código para nombres de función: El número de funciones que PHP pone a su disposición es.7.8. Figura 2. donde aún sin haber terminado de escribir el nombre de la función date(). el de argumentos muestra la lista de argumentos que admite una función. Figura 2. Pero no hay nada . Esta característica no hace necesario saber el nombre exacto de una función. A medida que escriba. nada más escribir el paréntesis a continuación de su nombre.8 muestra un asistente de código para argumentos en plena acción con dicha función. Pruebe todo aquello que pueda hacer más productivo su trabajo. pero no lo es. Por lo general. el servidor Web se la pasará al preprocesador de PHP. puede leerse con cualquier editor de texto. el resultado será la página PHP tal y como la recibió el preprocesador. funciones. el preprocesador deja pasar tal cual el texto en formato HTML. Figura 2. Como vio en el anterior apartado. Lo normal es que en una misma página coexistan HTML y PHP. 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. Pero. cuando alguien pida una página de estas características.) sin tener que vagar por la documentación en línea de PHP. personalice el entorno de trabajo hasta que lo sienta como suyo propio. Ayuda integrada Not a: Por supuesto.9.9. Al no encontrar ninguno. cualquier otra ayuda a la programación será bienvenida. Como ya sabe.que pueda sustituir a un buen sistema de ayuda integrada en el entorno de desarrollo. 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. No es necesario compilarlo. 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. ¿cómo se diferencia el código PHP del código HTML? Escapar de HTML Parece el título de una película. juegue con todas las características que el IDE con el que trabaje le proporcione. precisamente como muestra la figura 2. 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. Este sistema le permite obtener ayuda sobre PHP (sintaxis. etc. Éste buscará fragmentos de código PHP. pero ejecuta las instrucciones . Por ejemplo. éste no será el caso. ya que nos serán de mucha utilidad. La hora es: <? echo date('H:i:s') ?>. utilizaremos la primera vía de escape de HTML: <?php . PHP deja pasar tal cual todo el texto hasta llegar a los caracteres <?. siempre debería ser posible escapar de PHP de esa forma. que puede estar desactivada. Y esta operación se repite hasta llegar al final del archivo. Sabe que todo lo que encuentre desde ese momento hasta que aparezca la pareja de caracteres ?> será PHP. además. por varias razones: Con independencia de la configuración de PHP. ?>. En la anterior instrucción. Por ello.texto en formato HTML. algo que puede ser útil en determinadas situaciones. con una salvedad: en aquellas partes en las que quiera introducir algún valor que se genere de forma dinámica.... más complicado será trabajar mezclando HTML y PHP.. escapará de HTML para entrar en PHP. Ya hemos utilizado una de ellas: <?= es una forma más corta de escribir <? echo. pero ejecuta las instrucciones PHP. <?php . en adelante. ?> 2. la más recomendable es la primera. Not a: Con el paso de las páginas. Por lo tanto... El capítulo dedicado a las plantillas propone algunas soluciones interesantes que le recomendamos. descubrirá que mientras mayor sea el proyecto para el que esté empleando PHP. Existen varias formas de escapar de HTML. estas dos líneas de código son equivalentes: La hora es: <?= date('H:i:s') ?>. sobre todo si el grupo de trabajo lo conforman varios programadores y diseñadores. Funciones de salida Aunque hablaremos de las funciones en general con posterioridad. una página que cumple el estándar XHTML. . <? . ?> De estas dos. De forma que una página PHP puede ser como una página HTML normal y corriente. algo que no es cierto para la segunda. Cuando escapa de HTML entra en PHP. Una página PHP que utilice la primera forma es. pero nosotros sólo vamos a comentar dos: 1. vamos a ver ahora las que se utilizan para mostrar información en la página HTML resultante de procesar una página PHP. 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') ?>. Algo que hoy nos parece obvio puede ser difícil de entender cuando volvamos a ver el código pasados unos meses. ?> La hora es: <?= date('H:i:s') ?>. // // Las horas.3. dejaremos para otro momento hablar de ellas. 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. así que podemos volver a escribir el código anterior así: <?php /* El siguiente programa muestra la hora actual. Comentarios PHP nos permite escribir texto que el preprocesador ignorará. // pero atención que para los minutos se // utiliza i y no m. Existen dos tipos de comentarios: de línea y de párrafo. pero atención que para los minutos se utiliza i y no m. los minutos y los segundos se // separarán con dos puntos. La página HTML resultante del código anterior es exactamente la misma que se puede ver en la figura 2. . lo que se conoce como comentarios.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')) ?>. Los comentarios son útiles para explicar qué intentamos hacer a lo largo de un determinado programa. // // La función date() recibe como parámetro el // formato en el que se mostrará. Aunque existen otras funciones para mostrar información. Si comenzamos una línea con la pareja de caracteres //. a pesar de la existencia de comentarios al comienzo. esa línea será tomada por PHP como un comentario. La función date() recibe como parámetro el formato en el que se mostrará. La hora se representa como H y los segundos como s. La hora se // representa como H y los segundos como 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. Figura 2.10. De esta forma. Podemos modificar la página PHP de prueba para que incluya ese encabezado.10. 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.Las horas. El resultado seguirá siendo el mismo. 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. Cuando usted. Este encabezado podría contener el nombre del autor del código. los minutos y los segundos se separarán con dos puntos. */ ?> La hora es: <?= date('H:i:s') ?>. mostrándolos de un color diferente al del resto del código. pero que sea legible. Otra costumbre saludable es comenzar sus programas con un encabezado común. la antigüedad del mismo y podrá partir con ventaja al conocer de mano del autor algo sobre el funcionamiento de la página. Le recomendamos que seleccione un color lo más apagado posible para los comentarios. El último fragmento de código se puede ver resaltado en la figura 2. 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 fecha en la que comenzó a escribirlo y una breve descripción del objetivo de dicha página. podrá ignorarlos sin dificultad cuando no le sean necesarios. pero podrá leerlos si lo desea. El resalte de sintaxis también tiene en cuenta los comentarios. Se trata de un ejemplo de página . Por cierto. Para declarar una variable en PHP sólo tiene que escribir el nombre de la variable y asignarle un valor. Una variable es el lugar en el que vamos a guardar los valores que necesitaremos más adelante. Variables Los datos no son etéreos. Hemos comentado que a partir de una sola página PHP puede obtener diferentes páginas HTML. En la jerga de los programadores. Gracias a ellas nos acercaremos aún más a descubrir el verdadero potencial que hay tras PHP.org/. Su página Web se encuentra en la dirección http://phpdoc. Este espacio se encuentra en la memoria principal del ordenador. los segundos avanzando. Nuestras posibilidades estarían muy limitadas si eso fuese todo lo que podemos hacer en PHP. En el ejemplo anterior. un estándar para la documentación de PHP con el que Eclipse PDT es compatible. es necesario almacenarlos en algún lugar. en la RAM. */ ?> La hora es: <?= date('H:i:s') ?>. dependiendo de las circunstancias. Para diferenciar las variables de otros elementos dentro de PHP. ya sea para consultarlos o para modificarlos. ésta ha sido la última vez que utilizamos la forma abreviada de escapar de HTML. los minutos y los segundos se separarán con dos puntos. pero atención que para los minutos se utiliza i y no m. La función date() recibe como parámetro el formato en el que se mostrará. Not a: Quizá le interese echar un vistazo a PHPDoc. Después puede incluir números. es decir. Una variable tiene un nombre. el nombre de éstas comienza siempre con el símbolo del dólar ($ ). Las horas. Advert encia: Y mucho cuidado: PHP diferencia entre mayúsculas y minúsculas. A continuación veremos qué son las variables y de qué tipo las hay. un tipo y un valor. reservar el espacio necesario para guardar dichos valores se conoce como "declarar una variable". La hora se representa como H y los segundos como s. El primer carácter a partir del $ debe ser una letra o un carácter de subrayado (_). Por ejemplo: <?php . como el tiempo va pasando. cada vez que cargue la página el resultado será diferente.Se trata de un ejemplo de página dinámica muy sencillo. recuerde utilizar dicho separador. Enteros En una variable de tipo entero puede almacenar valores . En una variable. Sin embargo. decimales. 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. un valor booleano FALSE equivale al cero. esta declaración es incorrecta. $hipotecado = true. una línea de código se diferencia de la siguiente utilizando precisamente dicho carácter. De todos ellos vamos a ver los que más útiles le pueden ser durante el comienzo de su aprendizaje: tipos booleanos. ya que su nombre comienza con un número: $1hora = date('H:i:s'). enteros. En el siguiente fragmento de código declaramos dos variables de tipo booleano: $millonario = false. Se trata de algo muy importante. ¿Qué tipos de datos nos ofrece PHP? Tipos de datos PHP dispone de varios tipos de datos. En PHP. $_1hora = date('H:i:s'). PHP se reserva dos palabras para indicar esos valores: TRUE (verdadero) y FALSE (falso). mientras que cualquier otro valor numérico sería equivalente al valor booleano TRUE . Puede utilizar cualquier combinación de mayúsculas y minúsculas para escribir estos valores: PHP siempre los reconocerá. Las siguientes líneas son ejemplos de declaraciones correctas: $hora = date('H:i:s'). $_hora = date('H:i:s'). Internamente. Booleanos Una variable de tipo booleano puede tener dos posibles valores: verdadero o falso. Not a: A diferencia de otros lenguajes de programación.<?php $hora = date('H:i:s'). ?> 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 . su tipo determina la naturaleza de los datos que almacena. $Hora = date('H:i:s'). El código anterior almacena en la variable $hora la hora tal y como la mostrábamos en los ejemplos anteriores. sino que lo determina el valor que se le asigna para crear la variable. cadenas y matrices. el decimal. Se trata de un convenio que varía entre países. el contenido de la . Si quiere incluir una comilla simple dentro de una cadena de este tipo. Por ejemplo: $i = 12. Existen límites en cuanto a los valores que puede almacenar en una variable de tipo entero. En bloque. incluido el cero.". debe incluir una barra invertida antes del carácter. Decimales Una variable de tipo decimal puede contener cualquier número en coma flotante. Una cadena de texto no más que una secuencia de caracteres. De esta forma. Cadenas Y llegamos a las cadenas. PHP permite definir cadenas de tres formas diferentes: 1.'. Con comillas simples.14. Not a: Paradójicamente. la siguiente instrucción nos sirve para declarar una variable de tipo decimal: $pi = 3. Con dobles comillas. PHP sustituirá la variable por su valor. Dicho límite depende del sistema operativo en el que PHP esté instalado. Por ejemplo: $i = 20. $j = -40. Tras ejecutar estas dos líneas. $k = 0. $cadena = "Un año tienen $i meses. Las cadenas entre comillas dobles tienen una característica añadida que las hace muy interesantes: si contienen el nombre de una variable existente. Las cadenas más sencillas son las que se especifican entre comillas simples: $cadena = 'Esta es una simple cadena. 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.'. Si intenta asignar a una variable de tipo entero un valor superior al límite. lo que llamamos número en coma flotante utiliza como separador de decimales un punto. posiblemente el tipo de datos que más vamos a utilizar en PHP. 3. así: $cadena = 'Esto es una comilla simple: \'. PHP transformará de forma automática esa variable al siguiente tipo de datos que vamos a ver.enteros positivos y negativos. 2. Y nada mejor que utilizar un ejemplo para explicar cómo utilizar este tipo de cadenas: $i = 12. habrá observado el trabajo con cadenas con PHP es mucho más . principalmente porque no es necesario utilizar caracteres especiales para indicar los retornos de línea. Pero también puede incluir retornos de línea con \n. en bloque. CADENA. Podemos utilizar variables como en las cadenas de dobles comillas.". y algunos otros. es muy similar al segundo tipo. La diferencia principal está en la forma de utilizarlas. así: $i = 12.variable $cadena será "Un año tiene 12 meses. 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. Se trata de la sintaxis más adecuada para cadenas de gran longitud. Igual que para incluir una comilla simple utilizábamos \' en el primer tipo de cadenas. Esas ventajas tienen un inconveniente: PHP tardará más en procesarlas. utilizaremos \" en el segundo.\n Esto es un ejemplo: $i. El tercer tipo de cadenas. tabuladores con \t . Para separar su texto en diferentes líneas ha de utilizar la etiqueta <br/>. Le recomendamos que consulte la documentación de PHP si desea más información al respecto de estos caracteres de escape. Podríamos haber definido esa cadena utilizando dobles comillas. el símbolo del dólar con \$ . Si conoce algún otro lenguaje de programación. Lo veremos en algunos de los ejemplos posteriores. Otra diferencia entre las cadenas con comillas simples y las cadenas con comillas dobles son los caracteres de escape. 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. Utilice comillas simples siempre que no sea necesario utilizar sustitución de variables.\n Podemos utilizar variables como\n en las cadenas de dobles comillas. Esto es un ejemplo: $i. $cadena = <<<CADENA Esto es una cadena definida en bloque. $cadena = "Esto es una cadena\n definida en bloque.\n". una serie de caracteres especiales que comienzan con la barra invertida. no verá retorno alguno. Truco: No se deje llevar por la tentación de rodear siempre sus cadenas entre comillas dobles porque sean más flexibles. Al utilizar la palabra reservada array para asignar valores a la variable $peliculas. La siguiente es una de las posibles formas de declarar una matriz que contenga los tres valores anteriores: $peliculas = array(9. para añadir el número de películas vistas en abril: $peliculas[] = 17. 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. el segundo 12 y el tercero 21. Not a: El primer elemento disponible en una matriz es el cero (0).en febrero: $peliculas_febrero. Las matrices le permiten tener esa información mucho más organizada. entre corchetes.<br/> . 12. Para acceder a estos elementos sólo necesita indicar el índice de cada elemento tras el nombre de la variable. <br/> PELICULAS. Es muy importante tenerlo en cuenta para no cometer errores al trabajar con matrices.en marzo: $peliculas[2]. En otra parte del código podría utilizar estas instrucciones para mostrar dichos valores: echo <<<PELICULAS Películas vistas:<br/> .en febrero: $peliculas[1].flexible. Con lo aprendido hasta ahora podría hacerlo así: $peliculas_enero = 9.en marzo: $peliculas_marzo. PHP comprende que queremos crear una matriz. $peliculas_febrero = 12. Por ejemplo. <br/> PELICULAS. . Puede añadir nuevos elementos a una matriz después de haberla creado. $peliculas_marzo = 21. reservando el espacio necesario para poder guardarlos. <br/> . Hemos creado una matriz con tres elementos: el primero es 9. <br/> . con más posibilidades. Podría mostrar las películas vistas en cada mes con el siguiente código: echo <<<PELICULAS Películas vistas:<br/> .en enero: $peliculas_enero.<br/> . 21). Examinará entonces cuántos elementos aparecen entre los paréntesis. Esto es aún más cierto para las matrices.en enero: $peliculas[0]. etc. Más que matrices. print_r($peliculas). PHP crea los índices de forma automática.11. en lugar de tener que utilizar números? Pues podemos. El código resultante podría ser el siguiente: <?php $peliculas = array(9. . esta sería una forma igualmente válida de declarar la misma matriz: $peliculas = array( 'enero' => 9. En nuestro ejemplo de películas podríamos decir que queremos traducir el 0 por un 9. el 1 por un 12 y así sucesivamente. aunque en realidad lo que queremos es traducir enero por un 9.11. 'abril' => 17 ). Matriz. nuevo elemento y contenido La función print_r() nos presenta los datos que contiene la matriz de una forma muy curiosa. 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. tras las matrices en PHP hay mucho más que lo que parece a primera vista. con los que podemos traducir de un valor a otro. Así podemos ver que en la posición cero está el 9. podríamos considerar que PHP nos proporciona diccionarios. febrero por un 12. ¿No sería fantástico poder hacer esa traducción. ?> El resultado lo puede ver en la figura 2. en la dos el 21 y en la tres el 17. en la que sólo se asignan valores. $peliculas[] = 17. 21). 'marzo' => 21. 12. que recibe como argumento una matriz. puede utilizar una función muy útil: print_r(). 'febrero' => 12. Figura 2. comenzando por el 0. el valor del elemento. En realidad. A continuación y entre paréntesis podemos ver los elementos que componen la matriz. Entre corchetes aparece el índice del elemento y a continuación. tras los caracteres =>.PHP se encargará automáticamente de crear el cuarto elemento de la matriz. en la una el 12. Para ver el contenido de la matriz tras añadir este nuevo elemento. Por ejemplo. En primer lugar nos dice que se trata de una matriz con la palabra Array. Si no indica índice alguno. 'abril' => 17 ). el cero.13. porque permite asociar dos valores entre sí. 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. Figura 2. Figura 2. Para evitar este tipo de situaciones. puesto que nosotros esperaríamos que el índice del mes de mayo fuese el 5. pero ¿qué índice tendrá ese elemento? La figura 2. utilizando la siguiente sintaxis: $peliculas['mayo'] = 14. Ya sabe que la última línea añade un nuevo elemento a la matriz. La matriz con la que hemos estado jugando hasta ahora sólo contenía números . 'marzo' => 21.12. Esta decisión. PHP utilizará el siguiente que esté disponible. 'febrero' => 12. PHP ha considerado que el más adecuado es el primero libre. puede sin embargo dar lugar a confusiones. el que él crea más adecuado. Índices no concordantes Not a: En algunos textos puede encontrar que a este tipo de matriz se le llama matriz asociativa. asigne nuevos elementos a una matriz ya creada indicando el índice de los mismos.12. Matriz asociativa Como no hemos utilizado índice alguno.13 nos muestra el resultado de utilizar print_r() con dicha matriz. totalmente correcta. Ha de ser cauto con los índices al añadir nuevos elementos a una matriz.El resultado de utilizar print_r() con la matriz anterior puede verse en la figura 2. Considere las siguientes instrucciones: $peliculas = array( 'enero' => 9. >$peliculas[] = 14. 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. permiten determinar qué acciones realizar en función de una condición. if ($hora < '12') echo 'Aún no es mediodía. la hora. podríamos mostrar un mensaje de saludo. Por ejemplo. Instrucciones condicionales Como su propio nombre indica. la acción asociada se ejecutará. Puede mejorar este pequeño programa utilizando else junto con if. de las que existen dos tipos: las condicionales y las iterativas. que en su expresión más sencilla tiene este aspecto: if (condición) acción PHP evalúa la condición. Después puede comparar ese valor con uno en concreto. Pero ¿no sería mucho más interesante poder cambiar el contenido de la página dependiendo de la hora? Por ejemplo. la acción se ignora y no se ejecuta. La más simple de este tipo de instrucciones es if. Algo así: <?php $hora = date('H'). "Buenas tardes" desde las 14 hasta las 19 y "Buenas noches" de las 19 hasta las 8.. algo que también sabe hacer gracias al trabajo que ha realizado con los operadores. si la hora es menor que las 12. realizará la acción que haya escrito. De hecho. Ya sabe cómo hacerlo. Y. if ($hora < '12') echo 'Aún no es mediodía. la página estará en blanco. puede almacenar la hora en una variable. si la vemos después de las 12.'. Este mensaje podría decir "Buenos días" si la hora está entre las 8 y las 14.'.Sí. Concretando aún más. entonces. escriba un mensaje indicando que aún no es mediodía.'. ?> ¡Esto marcha! Ahora el que vea la página siempre obtendrá un mensaje. Pues esto y mucho más es lo que vamos a conseguir con las instrucciones de control. ?> El resultado del código anterior variará dependiendo de si vemos la página antes o después de las 12. hemos visto cómo crear una página en la que aparece un elemento que cambia en cada llamada. Así podrá indicar la acción a seguir en caso de que la condición no se cumpla: <?php $hora = date('H'). si ambos valores coinciden. Si el resultado de esta evaluación es TRUE .. aunque no se trata de un mensaje . En caso contrario. else echo 'Ya es mediodía. Para solucionar ese problema puede utilizar las llaves ({}). 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'). if ($hora < '12') echo 'Aún no es mediodía. else if ($hora == '12') echo 'Ya es mediodía. que permiten asociar grupos de líneas a cada parte de la condición.'. si no porque no le hemos dicho que a cada parte de la condición sólo se asocia una instrucción.'. gracias a lo que podemos volver a escribir el código anterior así: <?php $hora = date('H'). vamos a utilizar una nueva instrucción condicional. ¡la respuesta no es correcta! Aunque el fallo no será por desconocimiento. else echo 'El mediodía ya pasó.'. A esa hora ya no es mediodía.'.'.'. elseif. Su respuesta sería correcta si volviésemos a . echo '¡Queda menos para ir a comer!'. se cumpla o no se cumpla la condición. ¿verdad? Para ser más precisos en nuestros mensajes.'.'. 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'). else echo 'El mediodía ya pasó. if ($hora < '12') echo 'Aún no es mediodía. Podemos entonces ejecutar instrucciones cuando aún no sean las 12. digamos a las 8 de la tarde. else echo 'Es mediodía. elseif ($hora == '12') echo 'Ya es mediodía. la última línea. Es decir. es decir. una pregunta con trampa. la que nos avisa que queda menos para ir a comer. se ejecuta siempre. que permite evaluar una nueva condición en caso de que la anterior no se cumpliese.muy exacto si lo ve pasadas las 12. ?> Las instrucciones condicionales pueden anidarse. ?> Si su respuesta fue que sólo veremos el texto "Aún no es mediodía". ?> Ahora. if ($hora < '12') echo 'Aún no es mediodía. . case '14': echo 'Que aproveche. } ?> Not a: Le recomendamos que siempre utilice llaves con sus instrucciones condicionales if .. comprobando la hora y escribiendo mensajes en función de la misma.. if ($hora < '12'){ echo 'Aún no es mediodía. por ejemplo. a las 14 sale a comer. Así. } ?> PHP nos proporciona otra instrucción condicional que permite escribir un programa equivalente al anterior. break. case '19': echo 'Hasta mañana.'.'.'. }elseif ($hora == '14'){ echo 'Que aproveche. pero de forma más clara: la instrucción switch. break.<br/>'. case '16': echo 'Lástima de siesta.escribir el código anterior así: <?php $hora = date('H'). .'. El resultado de utilizarla sería el siguiente: <?php $hora = date('H'). switch ($hora){ case '9': echo 'Bienvenido al curro. break. Podría olvidar incluirlas si más adelante decide añadir una línea más alguna de las partes de la condición. if ($hora == '9'){ echo 'Bienvenido al curro. echo '¡Queda menos para ir a comer!<br/>'.. Utilizando instrucciones if y else puede complicar el programa anterior todo lo que quiera.'.'. }else{ echo 'Es mediodía. aunque a cada parte sólo asocie una línea de código.'. }elseif ($hora == '16'){ echo 'Lástima de siesta. a las 16 vuelve a entrar y a las 19 se va para casa escribiría el siguiente código: <?php $hora = date('H').'. para informar de que a las 9 de la mañana entra a trabajar.<br/>'. }elseif ($hora == '19'){ echo 'Hasta mañana. lo que podría provocar un fallo en la lógica de su programa. Si son iguales. case '16': echo 'Lástima de siesta. expresión2.'. break. Bucle For La primera que vamos a ver es la instrucción for . ejecutará las instrucciones asociadas con ese case y terminará de ejecutar la instrucción switch. Después escribimos las instrucciones asociadas a cada caso. comparando el valor de $hora con el valor correspondiente. case '14': echo 'Que aproveche.echo 'Hasta mañana. Not a: La instrucción break es la que marca la salida del swit ch. PHP recorrerá cada instrucción case. La sintaxis de esta instrucción es la siguiente: for (expresión1.'. break. es decir.'. default: echo 'A trabajar. Puede utilizar la instrucción default .'. case '19': echo 'Hasta mañana.. Incluso puede indicar qué hacer en caso de que no se cumpla ninguna de las condiciones. que permite ejecutar un bloque de instrucciones un número concreto de veces. 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'). } ?> Instrucciones iterativas Estas instrucciones permiten ejecutar un bloque de código tantas veces como sea necesario.'. break. cuando no haya un case que satisfaga la igualdad. break. switch ($hora){ case '9': echo 'Bienvenido al curro. le indicamos a la instrucción sobre qué variable se realizarán las comparaciones. break. mientras se cumpla una determinada condición. De ella hablaremos más adelante.. expresión3) acción . } ?> Como puede comprobar.'. 14. comprueba que $i no sea mayor que 3. la condición se cumple.14. La cuarta vez que pasemos por la comparación. así que vuelve al comienzo del bucle y evalúa la tercera de las expresiones. se evaluará expresión2. $i valdrá 4. El siguiente fragmento de código contiene un bucle for que se ejecuta tres veces. El resultado de ejecutar este código puede verse en la figura 2. Sólo lo hace la primera vez. $i++){ echo 'Probando un bucle for. asigna 1 a la variable $i. expresión2: Antes de comenzar cada iteración. Volvemos a ejecutar la instrucción echo(). Al encontrar el cierre de llave descubre que la primera iteración ha terminado. lo primero que hace es evaluar expresión1. a compararlo con 3 y a ejecutar la instrucción echo. al comienzo del bucle. Cada vez que lo hace. Las iteraciones continuarán mientras se evalúe como TRUE . pero como $i vale 2.. A continuación. expresión3: Al terminar cada iteración. así que ejecuta la instrucción echo(). Segunda iteración: comparamos el valor de $i con 3. a incrementar el valor de $i. escribe el mismo texto: <?php for ($i = 1.<br/>'. Cada vez que se dé una vuelta en la instrucción de iteración. Como $i contiene 1. Resumiendo: expresión1: Sólo una vez. que incrementa en uno el valor de $i. Figura 2.Cuando PHP encuentra una de estas instrucciones. } ?> Cuando PHP encuentra el bucle for. la comparación se evaluará como FALSE y habrá terminado la ejecución del bucle for. la condición se cumple.. Ejecución de un bucle for El siguiente es un ejemplo mucho más vistoso de bucle . después de haber sido incrementada. Esto sólo se hace la primera vez. $i <= 3. Cada vez que se termine una vuelta en la instrucción de iteración se evaluará expresión3. Esa matriz podría ser. resulta que los índices utilizados no son números. } ?> Vaya. son cadenas de texto. Claro.'>Bucle for</h'. Encabezados dinámicos Un bucle for puede utilizarse para recorrer todos los elementos de una matriz y mostrar su contenido.$i. 'marzo' => 21. el resultado de ejecutar este bucle no es el esperado. } ?> En la figura 2. la que contenía las películas vistas durante cada mes: <?php $peliculas = array( 'enero' => 9. ': ' . $peliculas[$i] . Puede utilizar este bucle así: foreach (matriz as $valor) acción El bucle se ejecutará tantas veces como elementos tenga la matriz. Bucle For Each Traducido como "para cada". Vamos a solucionarlo utilizar otra instrucción de iteración: foreach. $i++){ echo '<h'. cuyo valor se irá guardando dentro de $valor . for ($i = 1. Figura 2. 'abril' => 17 ).15 puede ver el efecto del código anterior. por ejemplo.'>'. $i <= 3. En cada iteración.15. .for: <?php for ($i = 1. 'febrero' => 12. se avanzará al siguiente elemento. $i++){ echo $i .$i. '<br/>'. $i <= $meses. // ¿Cuántos meses hay en la matriz? $meses = count($peliculas). con foreach puede recorrer todos los elementos de una matriz sin necesidad de saber cuántos elementos la componen. ' vi ' . ejecutamos la acción.16. la condición no se cumpla y se pueda salir del bucle. . que puede ser conocido previamente. foreach ($peliculas as $mes => $vistas){ echo 'En ' . $mes . 'abril' => 17 ).16.Dentro del bloque de código asociado al bucle puede realizar operaciones con ese valor. en un momento dado. 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. PHP ofrece otras dos instrucciones de control que iteran mientras se cumplan una serie de condiciones: los bucles while y do while. Esta acción puede ser un bloque de instrucciones envuelto entre llaves. La acción puede modificar los factores que se evalúan en la condición para que. el bucle while sigue la sintaxis: while (condición) acción Es decir. Figura 2. '. Esto le puede ser de mucha utilidad en el ejemplo de las películas por mes: <?php $peliculas = array( 'enero' => 9. mientras se cumpla la condición.<br/>'. $vistas . 'febrero' => 12. } ?> Puede ver el resultado de usar foreach en la figura 2. Uso de foreach Las dos instrucciones de iteración que acabamos de ver se ejecutan un número determinado de veces. 'marzo' => 21. Bucles While En su forma más sencilla. 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'). Compara el segundo actual con cero. ?> El resultado de este bloque de código es ligeramente diferente al anterior. A continuación. la página Web nunca le sería devuelta al que desee verla.'. terminará la ejecución del bucle y llegará a la instrucción echo. entre en el cuerpo del bucle. Si no es cero. Cuando eso ocurra. } echo 'Comienza un nuevo minuto. ?> Este sencillo programa guarda en la variable $segundo el segundo en el que se encuentra. Pero tarde o temprano no se cumplirá. PHP vuelve a comparar el contenido de la variable $segundo con cero y sigue iterando mientras se cumpla la condición. donde vuelve a obtener el valor del segundo. Dejando a parte diferencias de sintaxis. aunque buscamos el mismo objetivo. Como consecuencia. }while($segundo != '0'). while($segundo != '0'){ $segundo = date('s').Por ejemplo. Advert encia: Asegúrese de que siempre exista un camino de salida de estos bucles. echo 'Comienza un nuevo minuto. 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. el cuerpo del bucle do while se ejecuta al menos una vez. 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. que le muestra un mensaje. En caso contrario PHP no podría terminar la ejecución del bucle y el programa se ejecutaría indefinidamente. Por lo tanto. debe utilizar do while cuando quiera que el cuerpo del bucle se ejecute al menos una vez y while en caso contrario.'. Salida de bucles . pero con algunas salvedades que comprenderemos mejor con un ejemplo: <?php do{ $segundo = date('s'). ' vi ' . 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. ?> 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. } echo 'En ' . Una de ellas ya la vio cuando aprendió a utilizar la instrucción switch: se trata de break. suponga que no quiere estar esperando demasiado tiempo a que acabe el minuto. foreach. $mes . echo 'Comienza un nuevo minuto.<br/>'. $vistas . Podría utilizar esta instrucción en un bucle do while del que quiera salir antes de que se cumplan todas las iteraciones. } }while($segundo != '0'). } ?> . Hemos modificado el mes de marzo para que el número de películas sea cero: <?php $peliculas = array( 'enero' => 9. '. Podría utilizarlo en el ejemplo de las películas vistas cada mes. 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. break Puede utilizar esta instrucción para detener la ejecución de los bucles for . 'febrero' => 12. while y do while. En el ejemplo anterior.Es posible alterar el flujo de la ejecución de un bucle mediante algunas instrucciones especiales. foreach ($peliculas as $mes => $vistas){ if ($vistas == 0){ continue. 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'). if ($segundo <= '10'){ break.'. 'abril' => 17 ). el código anterior sólo mostrará información sobre los meses de enero. febrero y abril. . una terapia de choque.Como resultado. Ha sido duro. ¡Enhorabuena! Acaba de pasar por un intenso curso de aprendizaje de PHP. como la escritura de funciones o cómo reutilizar código. ¿verdad? Y eso que hemos dejado muchos temas en el tintero. conocer. desde los cimientos hasta los procedimientos más complejos. para desempeñar su trabajo con MySQL y PHP. Es necesario pasar a la acción. Quienes necesiten extraer información de esos datos sólo tienen que realizar una consulta a la base de datos. Y eso es algo que no se puede aprender con teoría. qué es una base de datos.3 MySQL El mundo de los sistemas gestores de bases de datos ha estado reservado a una élite desde el principio. pero para ello han tenido que coincidir mil circunstancias.1 simboliza las relaciones entre estos elementos. En resumen. modificación (para cambiar los datos almacenados) y borrado (para eliminar datos obsoletos o incorrectos). 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. lo más complicado es llegar a entender de qué se nos está hablando. consulta (para extraer información). dueños de sortilegios para desfacer cualquier entuerto. de la más utilizada en el mundo del software libre. Las tablas que mantienen datos que tienen que ver entre si están agrupadas en un mismo contenedor: la base de datos. hasta completar todas las tareas que debería controlar o. Sus administradores eran considerados poco menos que magos. Acompáñenos en el descubrimiento de las bases de datos y. Tras muchos años la situación ha cambiado radicalmente. La figura 3. Considere este tercer capítulo como una unidad autosuficiente en la que creará su primera base de datos. en concreto. Bases de datos Una base de datos es una buena forma de organizar y compartir información. . Le permite mantener todos los datos que nos interesan en un formato tabular unificado. al menos. con diferentes tablas para cada grupo de datos con características comunes. Cuando se es nuevo en el mundo de las bases de datos. En capítulos sucesivos profundizaremos en estos conocimientos. que verá funcionando y sobre la que aprenderá a realizar operaciones de inserción (para incorporar nuevos datos). Tablas. la información se extrae a partir de esos datos: en qué películas ha participado. En el caso de un actor. SQL son las siglas de lenguaje estructurado de consultas (Structured Query Language). Desde la aparición de las redes informáticas.1 se ha extendido. los datos representan hechos acerca de él (su nombre. etcétera).Figura 3. llamado SQL. pudiendo realizarse varias consultas de forma simultánea y desde diferentes ubicaciones geográficas. Gracias a este lenguaje podemos realizar preguntas a los servidores de bases de datos.1. su fecha de nacimiento. Existe un lenguaje especialmente diseñado para realizar consultas a bases de datos. Este lenguaje. cuántas son en total.2. es común para la mayoría de sistemas gestores de bases de datos que existen hoy en día. . etc. base de datos y consulta Not a: Fíjese en la diferencia entre datos e información. como intenta representar la figura 3. Sin embargo. el modelo representado en la figura 3. 1. La tabla 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.Figura 3. más o menos como estarían almacenados dentro de una base de datos.3 podemos ver cómo se mostrarían en una página Web. John Cleese. La publicación Web puede verse como una forma más de permitir consultas simultáneas a través de redes.com/). se trata de la página dedicada a ese actor en IMDb (en la dirección http://imdb.2. Consultas remotas simultáneas Más aún. En la figura 3.1 muestra los datos de un determinado actor. Tabla 3. En concreto.jpg . 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. Sin embargo. sencillamente. lo que facilita la localización de los datos que más interesantes. Python o Perl. MySQL y los lenguajes mencionados pueden funcionar sobre Windows. la página Web muestra las referencias que la base de datos tiene del actor. Not a: Apache. con el servidor de páginas Web Apache. John Cleese en IMDb Como puede comprobar. 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. a lo largo de las páginas de este libro utilizaremos principalmente el sistema operativo de Microsoft. tenga acceso a él. La razón por la que se ha escogido Windows en lugar de Linux o Mac OS X es. lector. Apache.Figura 3. Es precisamente en este tipo de aplicaciones donde MySQL tiene mayor aceptación. Este modelo de trabajo es muy versátil: los encargados de la tarea pueden estar en diferentes ubicaciones geográficas. en el grupo de aplicaciones conocido como LAMP : Linux. presentadas de una forma más atractiva. trabajando sobre la misma base de datos. ¿Qué es una tabla? .3. pero distribuidas de manera que sean legibles por un ser humano. Se lo dice alguien que trabaja con los tres a diario. lo que hace mucho más probable que usted. aplicaciones desarrolladas sobre Linux. De hecho. podrá aprovechar lo que vea en este libro sin ningún esfuerzo tanto en Mac OS X como en Linux. que aún sigue siendo el sistema operativo más utilizado del mundo. lo que permite hablar también de WAMP. MySQL y PHP. que utilizan como el enlace entre las bases de datos y la Web alguno de los lenguajes antes mencionados. Se llama registro a cada una de las filas de una tabla. En la figura 3. Los datos pertenecientes a un mismo elemento están organizados en campos o columnas. poder pasar una lista de las mismas a otros videoadictos o controlar a quiénes ha prestado alguna. Hoy en día no es correcto establecer una relación directa entre tabla y archivo. una tabla es un "lugar" en el que se almacenan una serie de datos de similares características. una base de datos y una tabla pueden estar dispersos en varios archivos. ni entre base de datos y archivo ya que por cuestiones de rendimiento y aprovechamiento de espacio. cada una de un determinado tipo. La mayoría tiene más de una. 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.En el mundo de las bases de datos. Figura 3.4 podemos ver un ejemplo de tabla.4. ya de por sí. con una longitud máxima de 64 caracteres. este "lugar" con el que nos hemos referido a una tabla era un archivo y dentro de este archivo se organizaban los datos. En el mundo de la carpintería es otra cosa. En este caso concreto se trata de información de texto. Incluso los hay que tienen un verdadero videoclub en el salón. Pero gracias a organizar los datos de las películas en una base . sus campos y sus registros Todos los datos pertenecientes a la misma columna de una tabla (el título de las películas. por ejemplo) son del mismo tipo. Base de datos de ejemplo Quien más y quien menos tiene alguna película en su casa. Una tabla. son interesantes. Estas posibilidades. incluso en varios ordenadores diferentes. Antaño. Para ello. Nuestra tabla de películas Not a: No se preocupe en absoluto por el significado de los tipos de datos. Más adelante veremos dichos tipos de datos. deberá hacer clic en Inicio>Todos los programas>Accesorios>Símbolo del sistema. Se le pedirá que introduzca la contraseña del usuario root . en definitiva. pero cubren a la perfección lo necesario para este ejemplo. A continuación crearemos la base de datos que contendrá los datos de las películas y. Herramientas de consulta Vamos a utilizar la más sencilla de las herramientas de consulta a nuestra disposición. como poder consultar cuáles de sus películas fueron dirigidas por un determinado director. Comenzaremos la creación de la base de datos de ejemplo de forma muy sencilla. si está utilizando el sistema operativo Windows. cuáles son de un determinado año. dentro de ella. El objetivo de este ejemplo es que comprenda lo que se puede hacer con una base de datos. una que funciona igual en cualquier sistema operativo: la consola. En esta tabla guardará los datos de las películas de su colección. cuáles las protagoniza un determinado actor. Si está utilizando XAMPP bastará que pulse la tecla Intro de nuevo. Si está utilizando Linux tendrá que abrir un terminal.de datos obtendrá otras ventajas de forma automática. la tabla de películas. puesto que dicho usuario no tiene contraseña alguna asignada. el nombre del director y el de uno de los actores. El terminal de Mac OS X se encuentra en la carpeta de utilidades. escriba: mysql -u root -p Pulse la tecla Intro. Son pocos datos.5.6.5 muestra el diseño de esta tabla: el nombre de la misma en la parte superior. Figura 3. Cuando tenga acceso a la consola. Puede verlo en la figura 3. La figura 3. almacenando sólo el título de la película. poder hacer preguntas y conseguir respuestas. . con el nombre a la izquierda y el tipo de datos a la derecha. y una línea describiendo cada columna de la tabla. haga clic en Variables de entorno y accederá al cuadro de diálogo Variables de entorno. en el explorador de archivos. 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. escriba la orden nano .6. Si utiliza Windows tendrá que modificar las variables de entorno de su sistema. Podrá ver el cuadro de diálogo Propiedades del sistema. y seleccionando la opción Propiedades del menú desplegable que aparecerá. Lamentablemente. En Windows Vista podrá llegar al cuadro de diálogo correspondiente haciendo clic con el botón derecho sobre Equipo. en el panel de la izquierda del cuadro de diálogo que aparecerá. En Linux o Mac OS X. Cliente de MySQL Cuando introduzca la contraseña correcta. abra un terminal (utilizando la aplicación del mismo nombre que se encuentra en la carpeta de utilidades).Figura 3.profile estando en su carpeta personal (por lo general. antes de $PATH: export PATH=/opt/local/bin:/opt/local/sbin: /usr/local/mysql/bin:$PATH Guarde los cambios realizados y cierre el terminal. 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. Active la ficha Opciones avanzadas. que le permitirá modificar la variable Path. XAMPP no incluye las órdenes de MySQL en la ruta del sistema. si MySQL se encontrase instalado en /usr/local/mysql/. el programa esperará que se le indique qué órdenes desea ejecutar. C:\xampp\mysql\bin\) a la variable Path. Añada al final la nueva ruta y guarde los cambios realizados. A continuación haga clic en Configuración avanzada del sistema. La . Para ello. añadiendo la ruta en la que se encuentre MySQL instalado (por ejemplo. es aquella en la que estará al abrir el terminal) y pulse la tecla Intro. 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. aunque mientras el contenido del archivo sea correcto. CREATE DATABASE videoteca. como los acentos. sólo a los nombres de bases de datos y tablas. Esto no es aplicable a los datos que luego contendrán. mientras que los nombres de bases de datos. por lo que evitaremos utilizarlos en los nombres de bases de datos y tablas siempre que sea posible. del que hablaremos con detalle más adelante. actor VARCHAR(128) ). ya se puede apreciar que parece que estemos dando órdenes en inglés. Si ha trabajado con algún lenguaje de programación verá que éste no se parece a ninguno que conozca. Creación de la base de datos Es el primer paso. El nombre de la base de datos que vamos a crear será videoteca. Se trata de un convenio ampliamente aceptado que permite diferenciar de un vistazo las diferentes partes de estas instrucciones. Sin entrar a comentar el significado de cada línea de este script.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. Aunque existen varios métodos para crear bases de datos con MySQL. omitimos el acento. USE videoteca. La extensión SQL se utiliza porque el lenguaje utilizado para escribir estos scripts es precisamente ese. También se habrá fijado en que las palabras reservadas del lenguaje que utilizamos para dar órdenes a MySQL están en mayúsculas. DROP TABLE IF EXISTS pelicula. SQL. ¿Qué quieren decir las dos líneas dedicadas a la . tablas y campos están en minúsculas. la creación de la base de datos. el más versátil consiste en la utilización de scripts. director VARCHAR(128). Por lo general. estos scripts se guardan en archivos de texto con la extensión SQL. la extensión no es demasiado importante. De ello se encargan las dos primeras líneas de este script: DROP DATABASE IF EXISTS videoteca. Not a: Habrá notado que estamos escribiendo pelicula y no película . es decir. Un script es un fragmento de texto con instrucciones para MySQL. CREATE TABLE pelicula ( titulo VARCHAR(64). está mucho más próximo al lenguaje natural que a uno de programación. La razón es que no todas las herramientas de acceso a datos se comportan igual con los caracteres internacionales. la que acabamos de crear: videoteca. Los mensajes indican que las consultas se han ejecutado correctamente.8 puede ver que una de las bases de datos existentes es. Tras la ejecución de la segunda línea. Precisamente lo siguiente que haremos. Escriba en el símbolo del sistema las dos líneas que acabamos de comentar y pulse la tecla Intro al terminar. Figura 3. Si intentase crear la base de datos y ésta ya existiese. para que pueda almacenar datos que posteriormente podamos consultar. En la figura 3. es decir. SQL para crear una base de datos ¡Vaya. Nuestra primera base de datos Para que la base de datos sea realmente útil.7. porque la base de datos ya existe. Traduciendo del inglés. la primera línea le dice a MySQL algo así como: "Borra la base de datos videoteca en caso de que exista". ¿Es posible que hayamos conseguido nuestro objetivo? Para comprobarlo basta con que ejecute la siguiente instrucción: SHOW DATABASES. algo no deseable si quiere comenzar con los ejemplos desde cero. la base de datos habrá sido creada.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. 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. Figura 3. MySQL le diría que no es posible llevar a cabo la acción. Vuelva a examinar las instrucciones anteriores: DROP DATABASE IF EXISTS videoteca. . es necesario crear tablas dentro de ella. Enhorabuena.8. precisamente. Llegó el momento: vamos a crear nuestra primera base de datos. La figura 3. qué decepción! El resultado no es demasiado espectacular.7 muestra el aspecto de dicha ventana tras ejecutar las instrucciones. La segunda línea es la que se encarga de la creación: "Crea la base de datos videoteca". Not a: Podríamos haber incluido el nombre de la base de datos antes del nombre de la tabla. actor VARCHAR(128) ). 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. MySQL sabrá que las siguientes instrucciones que reciba irán referidas a esa base de datos. director VARCHAR(128). Sin embargo. . La tercera línea permite indicarle a MySQL la base de datos con la que debe trabajar: "Utiliza la base de datos videoteca". USE videoteca. Esto es así gracias a la instrucción anterior. en la que se indicó con qué base de datos se iba a trabajar. Al igual que con las dos primeras instrucciones.9 muestra los mensajes que verá tras crear la tabla de películas y ejecutar posteriormente la instrucción DESCRIBE . ¿Quiere asegurarse de que la tabla se ha creado? Escriba la siguiente instrucción: DESCRIBE pelicula. separados por un punto. llamada pelicula. todos los campos contendrán información de texto. CREATE TABLE pelicula ( titulo VARCHAR(64).CREATE DATABASE videoteca. Y llega la parte complicada. en esta instrucción no se hace referencia a base de datos alguna. De esa forma. gracias a la instrucción USE nos lo ahorramos. No se preocupe demasiado por la sintaxis de estas instrucciones. en la instrucción de creación de la tabla: CREATE TABLE videot eca. de nuevo. Escriba esas instrucciones y. La figura 3. Como puede comprobar. sólo necesita traducir al castellano línea por línea. En la cuarta línea se le pide a MySQL que borre la tabla pelicula si ya existe. pulse Intro cuando termine. En este caso.pelicula . DROP TABLE IF EXISTS pelicula. A partir de la quinta línea se instruye a MySQL para que cree una tabla nueva. dentro de la base de datos videoteca. Si están entre corchetes. Por último. Para explicar la forma en la que debe utilizar estas instrucciones recurriremos a la sintaxis que MySQL sigue en su documentación. las instrucciones que verá disponen de muchas más opciones de las que comentaremos. Verá ejemplos de estas tres normas con la sentencia de . para simplificar la forma en la que la sintaxis está expresada. Si encuentra instrucciones entre llaves ({}) separadas por el símbolo | querrá decir que son alternativas: puede utilizar una u otra. lo que quiere decir que no es obligatorio utilizarlos en las consultas. Aunque con lo que verá tendrá las nociones mínimas necesarias. y la ha creado usted mismo. pero ha de utilizar una de ellas.Figura 3. Pero antes de aprender a realizar estas operaciones básicas. detengámonos un momento y veamos qué operaciones se pueden llevar a cabo sobre las propias tablas. modificación y borrado de tablas. Así le será más sencillo entenderla cuando acuda a ella en busca de más información.9. Con lo aprendido hasta el momento estamos listos para comenzar a ver las operaciones básicas de manipulación. Operaciones sobre tablas A continuación aprenderá a realizar las operaciones básicas de creación. puede utilizar una o ninguna de ellas. Es realizando estas operaciones como comprenderá para qué sirve realmente una base de datos. Creación de la tabla Ahora tiene una base de datos con una tabla. por lo que le recomendamos que acuda a la documentación de MySQL y complete sus conocimientos sobre ellas si así lo desea. grandes partes de la descripción pueden sustituirse por un nombre cuya sintaxis se explicará posteriormente. Sólo hay que seguir tres normas muy simples: Aquellos fragmentos incluidos entre corchetes ([]) son opcionales. Si lo desea puede incluir un valor predeterminado. 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. 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. Esto evitará que MySQL le informe del error que ocurre al intentar crear una tabla que ya existe. Sin embargo. Para ver cómo se crea una tabla nada mejor que un ejemplo. Ejecute las siguientes órdenes para crear la base de datos pruebas: DROP DATABASE IF EXISTS pruebas. 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. hablaremos sobre los tipos de datos. no va a ser éste el caso.. en este mismo capítulo. El tipo de la columna se indica tras su nombre.)] [opciones] Si lo desea. Es más que probable que MySQL ya disponga de una base de datos de pruebas llamada test. Más adelante. en cada inserción se asignará ese valor a su columna.. aunque no haya especificado valor alguno.creación de tablas descrita a continuación. pues NULL es la opción predeterminada). El valor guardado será NULL . Si indica NULL para una columna (o no indica nada. Si no desea que esto sea así indique NOT NULL . puede incluir IF NOT EXISTS cuando cree una tabla. MySQL le permitirá insertar registros sin asignar un valor a dicha columna. Vamos a crear una nueva base de datos en la que realizar las pruebas de este capítulo. que podríamos utilizar para crear tablas de ejemplo. De esa forma. . Entre otras opciones. . cada modificación se define de la siguiente forma: modificación: ADD definición | ADD (definición. CREATE TABLE persona( id INT NOT NULL. definición. Además. Vamos a cambiar el tipo del campo nombre para que pueda almacenar cadenas de mayor longitud. Ahora bien.] A su vez. añadiremos un nuevo campo que permitirá guardar la edad. Con esta instrucción se pueden añadir nuevas columnas a una tabla (ADD). que sigue la siguiente sintaxis: ALTER TABLE nombre modificación [.. como ya sabrá. . incluso si ya contiene datos. Para ello debe utilizar la instrucción ALTER TABLE . Para lograr ambos objetivos utilice las siguientes instrucciones: USE pruebas. ALTER TABLE persona MODIFY nombre VARCHAR(32) NOT NULL. modificación. apellidos VARCHAR(64) NOT NULL DEFAULT '' ). CREATE DATABASE pruebas. ADD edad INT NOT NULL. .. eliminar columnas (DROP ) o cambiar el tipo de tabla. modificar las existentes (CHANGE ).. cambiar valores predeterminados (MODIFY) o eliminarlos.) | 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.DROP DATABASE IF EXISTS pruebas.. Ejecute ahora las siguientes órdenes para crear la tabla persona: USE pruebas. nada mejor que modificar la tabla creada en la sección anterior. Las instrucciones anteriores crean una tabla siguiendo las normas sintácticas que se vieron anteriormente. nombre VARCHAR(16) NOT NULL. Como ejemplo. ¿es posible modificar las características de una tabla ya existente? La respuesta es sí.. Modificación Las características de una tabla pueden ser modificadas después de que haya sido creada. Tipos de tabla Al contrario que otros sistemas gestores de bases de datos. Si la prioridad es ahorrar espacio de almacenamiento. nombre es el nombre de la tabla que se quiere eliminar..] El nombre de la tabla actual se cambiaría por el nuevo. Para borrar la tabla que se ha estado utilizando hasta ahora utilice las siguientes instrucciones: USE pruebas. Si lo desea. Como puede ver... . 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 quebraderos de cabeza. puede incluir IF EXISTS en la consulta de borrado.] En dicha sintaxis. DROP TABLE IF EXISTS individuo. dependiendo de sus necesidades. actual2 TO nuevo2. En los siguientes apartados describiremos los tipos de tabla más utilizados: MyISAM e InnoDB. RENAME TABLE persona TO individuo.. Es posible utilizar transacciones si se trata de uno de los requisitos de la aplicación. MySQL permite utilizar diferentes tipos de tabla.. puede cambiar el nombre de más de una tabla a la vez. puede olvidar que existen los diferentes tipos de tabla que se verán a continuación. Las siguientes instrucciones permiten cambiar el nombre de la tabla persona por individuo: USE pruebas. Si lo desea. Y lo mejor de todo: si sólo necesita un sistema para almacenar datos y posteriormente consultarlos. nombre. Borrado La sintaxis de la instrucción de borrado de tablas es: DROP TABLE [IF EXISTS] nombre [. Sin embargo.También es posible cambiar el nombre de las tablas existentes: RENAME TABLE actual TO nuevo[. es posible borrar más de una tabla a la vez con sólo indicar sus nombres separados por comas. existen muchos otros como. por ejemplo: ARCHIVE: Permite almacenar grandes cantidades de . MySQL puede comprimir las tablas para que ocupen lo menos posible. Si precisa velocidad de proceso puede utilizar tablas que estarán directamente en la memoria RAM del servidor. Si tiene alguna duda sobre el tipo de una determinada tabla. Como consecuencia es muy veloz. con mejoras como un superior aprovechamiento del espacio y más velocidad en el acceso a datos. Como su nombre indica. . MyISAM El tipo predeterminado de tablas que MySQL proporciona es MyISAM. 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. MySQL utilizará el tipo MyISAM. CSV: Son las siglas de Comma Separated Values (valores separados por comas). para evitar complicaciones. El primero de ellos es EXAMPLE (ejemplo). pero sólo si el propósito de la tabla es archivar información. Al crear tablas sin indicar de qué tipo serán. ISAM son las siglas de método de acceso secuencial indexado (Indexed Sequential Access Method). Más aún. conocido como ISAM (ya descatalogado). Lo mismo hará si no es capaz de crear el tipo de tabla que se indique. 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. NDBCLUSTER: Tipo de tabla para entornos distribuidos y de alta disponibilidad. Las tablas de tipo MyISAM pueden. FEDERATED: Permite que se pueda acceder a los datos de una tabla desde servidores remotos. Not a: Existen un par de tipos de tablas muy curiosos que no hemos mencionado aún. Permite almacenar datos en archivos de texto separando los valores con comas.información sin utilizar ningún índice. a su vez. El nombre de este tipo de tablas viene de la forma en que MySQL accede a sus datos. El tipo predeterminado de las tablas será InnoDB si ha instalado MySQL en Windows utilizando el asistente. no dejan de aparecer tipos de tabla nuevos para cubrir todas las necesidades de los usuarios de MySQL. 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. Aviso: Existe una excepción a la afirmación anterior. 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. Truco: ¿Quiere saber qué tipos de tabla puede utilizar en su servidor MySQL? Realice la consulta SHOW ENGINES. ser de tres tipos: . utilice la instrucción SHOW CREATE TABLE seguida del nombre de la tabla en cuestión y busque el valor que toma ENGINE. durante una transferencia entre dos cuentas. las tablas MyISAM son especialmente útiles cuando los datos no cambian con frecuencia y la operación más utilizada es la de lectura. Esto se debe a que en cada lectura se pueden recuperar más datos que si la tabla no estuviese comprimida. VARBINARY. algo recomendable en aplicaciones de bases de datos que funcionen desde unidades ópticas. si las tablas son InnoDB. 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. TEXT o BLOB. El ejemplo más utilizado transcurre en la base de datos de un banco.Estáticas: De forma automática. InnoDB Las tablas InnoDB proporcionan bloqueo por registro y control de transacciones. 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. Delante de cada registro almacenará el espacio que ocupa. . Las transacciones son necesarias en multitud de situaciones. por ejemplo. cada registro ocupa siempre el mismo tamaño. como el CD-ROM. si la tabla que está creando no contiene ningún campo de tipo VARCHAR. cumpliendo con el estándar ACID. lo que permite que más usuarios utilicen de forma simultánea la base de datos. La contrapartida: es necesario más tiempo para acceder a un registro en particular. Si las inserciones de nuevos datos y las modificaciones van a ser algo frecuente o necesita utilizar transacciones en sus operaciones con registros. En una tabla de tipo estático. MySQL hará que sea de tipo estático. Como consecuencia. es recomendable que utilice tablas de tipo InnoDB. Dinámicas: Si crea una tabla con algún campo de tipo VARCHAR. ocupa más espacio que las tablas dinámicas. Por el contrario. el bloqueo sólo se realiza en el registro que se esté modificando. Para lograr estos dos objetivos se sacrifica un poco de la velocidad de la que MySQL presume. 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. TEXT o BLOB. Si su tabla está en este formato sólo podrá leer de ella. por lo que deberá realizar las inserciones en tablas sin comprimir y alterar posteriormente las propiedades de la tabla para comprimirla. como algunos discos extraíbles u ópticos. Sin embargo. puesto que se necesita leer antes el espacio ocupado por cada registro y hacer los cálculos oportunos. Comprimidas: Si necesita que el espacio ocupado por sus tablas sea mínimo éste es su tipo de tabla. MySQL hará que sea de tipo dinámico. estas tablas ocupan menos espacio que las tablas estáticas. Por sus características. VARBINARY. pero no se habrá restado de la emisora. un fallo en el hardware del ordenador que hospeda el servidor de bases de datos. donde el saldo de las cuentas de ambos clientes debe estar almacenado en un registro dentro de una tabla de una base de datos. . La situación se complica en el entorno informático. Para el banco no se trata de algo deseable. UPDATE cuenta SET saldo = saldo + 300 WHERE idcliente = 212. A continuación. UPDATE cuenta SET saldo = saldo . INSERT INTO cuenta VALUES(212. inserte un par de valores para almacenar el saldo de dos clientes: USE pruebas.300 WHERE idcliente = 555. Se trata de un valor numérico en coma flotante. 1200. como un corte de suministro eléctrico. 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. CREATE TABLE cuenta( idcliente INT NOT NULL.00). saldo DOUBLE NOT NULL DEFAULT 0 ) ENGINE = InnoDB.Si piensa en esta transferencia en el mundo real. no verá que existan problemas: uno le da el dinero a otro y asunto resuelto.50). como un traspaso de dinero de una persona a otra. ¿En qué situación estaremos si ocurre algún problema entre el primer y el segundo paso. etcétera? El importe a transferir se habrá sumado a la cuenta destino. INSERT INTO cuenta VALUES(555. Claro que es todo lo contrario para los clientes. DROP TABLE IF EXISTS cuenta. 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. Una operación tras la otra: USE pruebas. 220. mientras dure la transacción. Al comienzo de una transacción. Siguiendo con el ejemplo. incluso otras transacciones. 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. una de las reglas de consistencia podría ser que toda transferencia de capital debe estar correspondida por un ingreso. ACID son las siglas de atómico. consistente. permaneciendo la base de datos en el mismo estado en el que se encontraba antes de comenzar la transacción.300 WHERE idcliente = 555. es posible que se pierda la consistencia. definidas por el diseño. Mientras dure una transacción. aislado y duradero (Atomic. La gestión de las transacciones se realiza mediante unas instrucciones muy sencillas. el estado de la base de datos debe ser consistente. Isolated. En el ejemplo del banco. Por el contrario. . UPDATE cuenta SET saldo = saldo . Sin embargo. las instrucciones que la conforman deben tener la impresión de que sólo ellas están en funcionamiento. por ejemplo). UPDATE cuenta SET saldo = saldo + 300 WHERE idcliente = 212. Consistent. En último lugar. si la transacción se interrumpe en medio de su trabajo (por un corte de luz. aunque en realidad se puedan estar realizando otras operaciones en la base de datos. o ninguno lo hará. El estado de una base de datos es consistente mientras cumpla unas reglas. Esto es permisible siempre y cuando al terminar la transacción se retorne al estado de consistencia inicial. la transferencia se realizaría de la siguiente forma: USE pruebas. los cambios realizados por una transacción deben permanecer cuando ésta termine. START TRANSACTION.El estándar ACID se propuso para solucionar este tipo de situaciones. ninguno de los cambios que haya realizado se habrán guardado. and Durable). MySQL dispone de varios tipos de datos diferentes para almacenar esta clase de información: CHAR: Permite definir cadenas de texto de longitud fija. Verá un ejemplo más adelante. Si la columna puede tener veinte caracteres. que finaliza la transacción.10 puede ver cómo almacenaría MySQL los valores de una tabla con una sola columna de tipo CHAR.COMMIT. el tipo de cada columna debe ser diferente. Figura 3. Con la primera instrucción se le dice a MySQL que va a comenzar un bloque de sentencias SQL dentro de una transacción. eliminando el problema de la inconsistencia. En la figura 3. que permite determinar si en las consultas se diferenciará entre mayúsculas y minúsculas. La longitud se especifica entre paréntesis a continuación del nombre del tipo y puede estar entre 0 y 255 caracteres. aunque el texto a guardar sea menor. ya que permiten la existencia de claves externas. Ocupación de CHAR . algo vital para el funcionamiento de la integridad relacional. Tipos de texto En la jerga informática. Verá qué quiere decir esto en el capítulo dedicado al diseño de bases de datos. El bloque termina con la instrucción COMMIT . A continuación veremos cuáles pone MySQL a nuestra disposición. Es decir. todas las instrucciones anteriores a COMMIT se descartarían. A continuación de esta primera instrucción están las operaciones a realizar con los valores dentro de la base de datos. se utiliza la expresión cadena de texto cuando se hace referencia a una sucesión de caracteres que pueden formar palabras o frases.10. siempre se ocuparán esos caracteres. Si existiese un problema antes de ejecutar la instrucción COMMIT . Los bancos son muy listos. Tipos de datos Dependiendo de la naturaleza de los datos que queramos guardar. El tipo CHAR admite el modificador BINARY. MySQL no hará efectivo los cambios hasta que encuentre una instrucción COMMIT . Not a: Existe un motivo más para utilizar tablas del tipo InnoDB. TEXT . Utilizando CHAR se tienen cinco filas de 14 caracteres cada una.11.10 estuviese creada con un tipo VARCHAR. como el contenido de un archivo JPG. BLOB: Aunque no se trata de un tipo de texto propiamente dicho. más un carácter extra por cada fila. Compare el espacio ocupado por los datos en las figura 3. Y claro está. mientras que un VARCHAR sólo once. Con VARCHAR tendría que sumar el número de caracteres de cada fila. con la salvedad de que las cadenas se almacenan en formato binario.11 muestra cómo asignaría MySQL el espacio si la única columna de la tabla mostrada en la figura 3. Las consultas realizadas sobre este tipo de columnas diferenciarán entre mayúsculas y minúsculas. pero la recuperación de los datos al hacer consultas es más veloz. 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. Es decir. no como cadenas de caracteres. con la salvedad de que las cadenas se almacenan en formato binario. en total 38.VARCHAR: Tiene el mismo rango de longitud que el t i p o CHAR.11. No confundir con el tipo de datos VARCHAR BINARY. Sin embargo. en total. para una cadena de diez caracteres. u n CHAR ocuparía veinte caracteres.10 y 3. La figura 3. Figura 3. si define una columna de veinte caracteres y guarda una cadena de diez. también puede utilizarse para guardar texto cuya longitud esté por encima de la permitida por los tipos CHAR o VARCHAR. Este tipo de columnas puede utilizarse para guardar información binaria. el mismo comportamiento de CHAR y . sólo se ocuparán esos diez caracteres más uno para guardar la longitud. Ocupación de VARCHAR Not a: El tipo CHAR ocupa más espacio. no como cadenas de caracteres. El nombre BLOB significa objeto binario de gran tamaño (binary large object). lo que da un resultado de 70 caracteres. 43 caracteres. VARBINARY: Equivalente al tipo VARCHAR. un archivo comprimido con ZIP. No confundir con el tipo de datos CHAR BINARY. Por ejemplo. es necesario hablar de él porque está íntimamente relacionado con el siguiente. 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. etcétera. BINARY: Equivalente al tipo CHAR. CREATE TABLE texto( cadena VARCHAR(32) ). Al definir la columna se indican los posibles valores que puede tomar. podría guardar la ruta en la que el archivo se encuentra en un campo de tipo VARCHAR. en esa columna sólo se podrá insertar alguno de los valores definidos. Internamente. Y realice una consulta a los valores de esa tabla. Los tipos TINYBLOB. los conjuntos se diferencian en que se pueden insertar varios de los valores definidos al crear la tabla. MySQL sustituye la cadena por un número. ahorrando espacio en cada inserción. ENUM: La enumeración es una clase especial de tipo de cadena. como relacionar de alguna manera un archivo en disco con un registro dentro de una tabla. Los tipos TINYTEXT . Posteriormente. MEDIUMBLOB y LONGBLOB son BLOB de diferentes tamaños. Cree una nueva tabla llamada texto. INSERT INTO texto VALUES('d'). Por ejemplo. MEDIUMTEXT y LONGTEXT son TEXT de diferentes tamaños. SELECT * . DROP TABLE IF EXISTS texto. TEXT: Exactamente igual que un BLOB. Esta tabla estará dentro de la base de datos de pruebas que creamos al principio de este capítulo: USE pruebas. SET: Similar a ENUM . MySQL utiliza un ingenioso sistema para no tener que guardar las cadenas en la base de datos. existen otras alternativas. INSERT INTO texto VALUES('b'). la utilizaremos para hacer pruebas con los tipos de texto. Inserte algunas cadenas de texto: USE pruebas. con la salvedad de que TEXT no distingue entre mayúsculas y minúsculas en las consultas. INSERT INTO texto VALUES('A'). ordenándolos de forma alfabética: USE pruebas. INSERT INTO texto VALUES('a'). ahorrando espacio.VARCHAR cuando se utiliza el modificador BINARY. Not a: Aunque es posible almacenar imágenes y cualquier archivo binario en un campo de tipo BLOB dentro de una tabla de MySQL. haciendo menor el espacio ocupado por la base de datos. Con el ejemplo que veremos en breve quedará más claro cómo se insertan estos valores. Enseguida veremos un ejemplo. Téngalo en cuenta cuando desee obtener listados ordenados alfabéticamente. CREATE TABLE texto( cadena VARCHAR(32) BINARY ). el resultado de la segunda consulta sí se obtiene diferenciando entre mayúsculas y minúsculas. repita los pasos anteriores. Ante la duda. como puede verse en la figura 3. un ejemplo de enumeraciones. Figura 3. selecciónelos ordenados alfabéticamente. Ahora. pero no diferencia entre mayúsculas y minúsculas. de nuevo. la primera consulta devuelve los registros ordenados alfabéticamente.12. pero cree la tabla con las siguientes instrucciones: USE pruebas. Figura 3. razón por la que a aparece antes que A. Vuelva a insertar los mismos valores y. Sin embargo. Otra ordenación alfabética Como puede comprobar. Suponga que . Por ello A aparece antes que a. DROP TABLE IF EXISTS texto.13. se basa en el orden de inserción. Ordenación alfabética Ahora.13. Puede ver el resultado de esta consulta en la figura 3.* FROM texto ORDER BY cadena.12. Esta vez el resultado será diferente. 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'. 'VHS'). La siguiente inserción generará un error: USE pruebas. 'DVD' ) ). Puede insertar valores en esa tabla como si de cadenas de texto se tratasen: USE pruebas.quiere almacenar en un campo de su base de datos dedicada a películas el soporte en el que se encuentran las grabaciones. DROP TABLE IF EXISTS pelicula. 'VCD' ). Como sólo dispone de reproductor de vídeo VHS y de DVD le bastará con que la columna tenga esos dos valores. de esta manera: USE pruebas. Puede ver el mensaje devuelto en la figura 3.15. soporte ENUM( 'VHS'.14. CREATE TABLE pelicula( titulo VARCHAR(64). 'DVD'). 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. El resultado de una consulta de todos los valores de esta tabla puede verse en la figura 3. INSERT INTO pelicula VALUES ('TRON'. Figura 3. INSERT INTO pelicula VALUES( 'Blade Runner'. . 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. INSERT INTO pelicula VALUES( 'Blade Runner'.terror' ). 'thriller' ) ). INSERT INTO pelicula VALUES( 'Alien'. . categoria SET( 'ciencia-ficción'.Figura 3. La inserción de registros en una tabla con una columna de tipo SET se realiza de la siguiente manera: USE pruebas. Si utilizásemos enumeraciones tendríamos que modificar las características de la tabla. 'terror'. El tipo de datos SET también podría utilizarse en este ejemplo. el uso de enumeraciones no es una buena idea si queremos permitir la inserción de nuevos formatos de grabación. CREATE TABLE pelicula( titulo VARCHAR(64).15. 'ciencia-ficción. 'ciencia-ficción. Se podría lograr algo similar creando la columna categoria mediante las siguientes órdenes: USE pruebas. Inserción que no pertenece a la enumeración Aunque puede simplificar mucho trabajo. 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. DROP TABLE IF EXISTS pelicula.thriller' ). Suponga que quiere guardar en una columna el género al que pertenece una película. Se estarían desaprovechando recursos si se utilizase una columna de tipo decimal para almacenar información de tipo entero. 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. Por cuestiones relacionadas con la forma en la que los programas están construidos y con el hardware en el que se ejecutan.16. Ocupa un solo byte. mientras que la segunda es decimal. El resultado de una consulta sobre los valores insertados en esta tabla puede verse en la figura 3. la parte decimal. 'ciencia-ficción' ). No es lo mismo guardar el número de veces que se ha visto una película que su precio. Como existe una gran variedad. se perdería. es más costoso almacenar y realizar operaciones con números decimales que con números enteros. 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. Existen seis tipos básicos para almacenar enteros.16. La primera cantidad es un número entero positivo. SMALLINT: Oscila entre -32768 y 32767. es posible seleccionar el tipo de datos más adecuado para cada caso. con un rango entre -128 y 127 con signo. Estos tipos son: TINYINT: El más pequeño de los enteros. Cuanto mayor sea el rango. De igual manera. Figura 3.INSERT INTO pelicula VALUES( 'Contact'. Números enteros MySQL proporciona suficiente variedad de tipos para cubrir todas sus necesidades. Si no se . 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. puesto que la parte de la derecha de la coma. diferenciados por el rango de valores que pueden contener. o de 0 a 255 sin signo. más espacio se ocupará en la base de datos. El espacio consumido es de 3 bytes. añadiendo el modificador UNSIGNED. INT: El tipo entero más común. utilizados de forma conjunta. MySQL recortará el número hasta el límite más cercano sin avisarnos. La columna entero de la tabla enteros puede almacenar números enteros con signo dentro del rango que se encuentra entre -2147483648 a 2147483647. o desde 0 hasta 4294967295 si no lo utiliza. pueden resultarnos interesantes. cambiando así el tipo de datos que la columna podrá guardar. MEDIUMINT: Con signo desde -8388608 a 8388607. Si quisiese almacenar enteros sin signo en ese campo debería cambiar la tercera línea. CREATE TABLE enteros(entero INT UNSIGNED). Existen otros modificadores que. como puede verse a continuación: USE pruebas. que se encarga de la creación de la tabla. . puede almacenar valores desde 9223372036854775808 hasta 9223372036854775807. ZEROFILL . Dos bytes de espacio. Utilice la base de datos creada en el apartado anterior para las pruebas con los tipos de texto. Cree dentro de ella una tabla con un único campo de tipo INT : 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. Con uno de ellos.incluye signo. CREATE TABLE enteros(entero INT). Puede ir desde 2147483648 a 2147483647 si utiliza signo. DROP TABLE IF EXISTS enteros. DROP TABLE IF EXISTS enteros. Con signo. hasta los dígitos seleccionados con el segundo modificador. sólo se ha añadido el modificador UNSIGNED después del indicador del tipo de la columna. BIGINT: El mayor de los tipos enteros ocupa 8 bytes. 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. Advert encia: Aunque es posible realizar inserciones fuera de ese rango. puede ir desde 0 a 65535. se le puede indicar a MySQL que rellene con ceros a la izquierda el número. Sin signo desde 0 a 16777215. Como puede comprobar. mientras que sin signo el rango está entre 0 y 18446744073709551615. Selección de valores enteros Como puede comprobar. el 100 como 0100 y el 1000 tal cual. el segundo de los modificadores antes mencionado se añade a continuación del tipo. INSERT INTO enteros VALUES(10000). y así ver el efecto que tienen en las consultas. 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. Por cierto. el tipo de la columna entero es entero relleno de ceros hasta cuatro dígitos.18. La figura 3. INSERT INTO enteros values(10). INSERT INTO enteros values(1000). Como comprobará. ¿Qué ocurriría si se insertase un valor con más dígitos de los indicados al crear la tabla? Pruebe: USE pruebas. CREATE TABLE enteros( entero INT(4) UNSIGNED ZEROFILL ). La siguiente consulta reconstruye la tabla de enteros. INSERT INTO enteros values(100). ¿qué se obtendrá al consultar ahora los datos de la tabla? Véalo en la figura 3. DROP TABLE IF EXISTS enteros. cambiando las características de su única columna: USE pruebas. Pruebe a insertar algunos valores para después seleccionarlos. Y luego la consulta de selección: USE pruebas.Puede que un ejemplo sirva para explicar mejor el funcionamiento de ZEROFILL .17. . entre paréntesis. Primero las inserciones: USE pruebas. SELECT * FROM enteros. Como ve. el 1 aparece como 0001. INSERT INTO enteros values(1).17 muestra el resultado de esta consulta. Figura 3. el 10 como 0010. Sin embargo. MySQL ofrece diferentes seudónimos para cada tipo de datos. Si tiene conocimientos de programación. Por ello. 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. en los que la parte entera se refiere a múltiplos de la moneda. Los números en coma flotante se llaman así porque se utiliza una coma para separar la parte entera de la decimal. fuera del contexto de las instrucciones SQL se utilizará la coma como separador. habrá visto que no se han mencionado otros tipos de datos. El tipo BOOLEAN (o BOOL ) es un seudónimo de TINYINT(1).99 euros. al enumerar los tipos existentes. Números en coma flotante Como ya sabrá. no se deje engañar. al insertar valores en coma flotante éstos se escribirán utilizando el punto. continuaremos repasando los tipos numéricos con los tipos decimales. Utilice las constantes TRUE . Tras comentar los tipos enteros. en realidad cuesta 30 euros menos un céntimo. Sin embargo. De igual manera. 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. Advert encia: Desde aquí queremos recomendarle que sólo utilice este tipo de modificaciones cuando sea estrictamente necesario. . true. la parte entera es 29 y la parte decimal 99. El ejemplo más claro: los precios. en el resultado de las consultas verá el punto como separador. los números en coma flotante contienen una parte entera y una parte decimal. Puesto que un tipo booleano es el que permite diferenciar entre los estados cierto y falso. y la parte decimal a la moneda fraccionaria. FALSE y false para trabajar con tipos booleanos.Figura 3. De igual forma. Una regla podría ser: mantenga los datos tal como son. en la sintaxis de SQL se utiliza un punto como separador. en un entero de un dígito tendríamos más que suficiente.18. Pero para lo que interesa ahora mismo. como los lógicos o booleanos. Por ejemplo. si el precio de un DVD es 29. Esta última se utiliza para describir cantidades inferiores a la unidad. mientras que el resto se mostrarán tal cual. existe un seudónimo llamado BIT para trabajar con bits. modifique su presentación en la aplicación que haga uso de ellos. el espacio ocupado es bastante mayor. utilice el siguiente código: USE pruebas. este tipo guarda valores exactos.99 y 9999. DROP TABLE IF EXISTS decimales. Para ello. Para estos tres tipos se puede indicar el número de dígitos totales para mostrar y el número de dígitos decimales. permite almacenar valores entre -3. Aunque el rango de valores que puede almacenar es el mismo que el tipo DOUBLE . DECIMAL: Los dos tipos vistos anteriormente codifican la información del número de manera que ocupe lo menos posible. donde N es un valor menor que 53. Como vimos anteriormente.402823466E+38.MySQL proporciona tres tipos básicos para los números en coma flotante. El rango de valores que se podrían almacenar en esta columna estaría entre -9999. especificar que se trata de números sin signo utilizando UNSIGNED no proporcionará un rango de valores más amplio. Estos tipos son: FLOAT: Decimal de precisión simple. entre paréntesis y a la derecha del nombre del tipo.175494351E-38 y 3. . cero incluido.402823466E+38 y 1. Existe una forma alternativa de crear columnas para almacenar valores en coma flotante. con DOUBLE(6. utilizando aproximaciones. con valores entre -1. A mayor precisión. cree una nueva tabla en la que experimentar con valores en coma flotante.99: cuatro dígitos antes de la coma y dos tras ella coma suman seis. simplemente se ignorarán los valores negativos. CREATE TABLE decimales( precio FLOAT(6. incluido el cero.2250738585072014E-308. Por ejemplo.175494351E-38. mientras que si N está entre 25 y 53 lo harían con precisión doble. se pueden insertar valores entre -9999. mayor espacio ocupado por el número. y 2. Sin embargo. DOUBLE: Decimal de precisión doble. Aprovechando que disponemos de una base de datos para pruebas. 2) se estaría indicando que se quiere una columna que almacene números en coma flotante. Inserte algunos y vea el resultado de una consulta de selección: USE pruebas.2250738585072014E308 y 1. y 1. Es posible utilizar FLOAT(N). Si N fuese menor que 25. Como con los números enteros.7976931348623157E+308 y 2.2) ). los valores de la columna se almacenarían con precisión simple.99 y 9999.7976931348623157E+308. con seis dígitos y dos decimales a la derecha de la coma. es posible utilizar ZEROFILL con idénticos resultados. Por el contrario.99. 995 ha pasado a ser 200. INSERT INTO decimales VALUES(199. Pero ¿qué ha pasado con el tercer valor? ¡Se insertó 199. INSERT INTO decimales VALUES(29. 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. Figura 3. MySQL redondea el número.994.38000).99).99.99! Esto se debe al redondeo que MySQL ha realizado.995). Sin embargo. INSERT INTO decimales VALUES(30). Si está entre 5 y 9 suma uno al siguiente decimal. pero la consulta muestra 199. El primer valor insertado ha sido 29. INSERT INTO decimales2 VALUES(3835. . DROP TABLE IF EXISTS decimales2. Para el siguiente ejemplo. Por eso 199.USE pruebas. Si el dígito decimal a evaluar está entre 0 y 4. Puesto que tiene que almacenar el número con 2 decimales. MySQL añade automáticamente dos ceros a la derecha de la coma.5) ).00. descarta el tercero. ya que MySQL redondea las cifras que se salen de la definición del tipo de la columna. Inserte un valor: USE pruebas. SELECT * FROM decimales. INSERT INTO decimales VALUES(199. Inserción de valores en coma flotante El segundo valor insertado fue 30.994). De lo anterior se puede deducir que es muy importante definir correctamente la precisión de los decimales.19. puesto que al crear la tabla se le indicó que esa columna tendría dos decimales. lo descarta. cree una nueva tabla: USE pruebas.19. CREATE TABLE decimales2( precio FLOAT(10. SELECT * FROM decimales2.20. Fechas y horas MySQL permite utilizar los siguientes tipos de datos para almacenar valores relacionados con el tiempo. Estos seudónimos no son más que tipos básicos cuyas características se han modificado. Problemas de redondeo Como ha podido comprobar. pero la parte de la hora debe estar entre 00:00:00 y 23:59:59. internamente. el valor mostrado en la consulta no es el mismo que se insertó. Si utiliza columnas cuyo tipo sea de precisión sencilla es posible que experimente problemas al realizar cálculos. DATETIME: Combinación de los dos tipos anteriores.Ahora. Especialmente indicado para almacenar tiempos transcurridos entre dos eventos. mes y día). . si experimenta problemas de esta índole. Figura 3. Como puede comprobar en la figura 3. El formato de este tipo es AAAA-MM-DD hh:mm:ss. Por ello. minutos y segundos) entre -838:59:59 y 838:59:59. vea lo que se ha insertado en la tabla: USE pruebas. MySQL ofrece seudónimos de los tipos aquí presentados. Permite almacenar la fecha y la hora de un determinado instante. Ya vio el tipo BOOL como ejemplo al hablar de los enteros. es recomendable que utilice el tipo DOUBLE para almacenar valores en coma flotante.20. por ejemplo la aparición de decimales que no ha indicado. MySQL utiliza precisión doble para los cálculos en coma flotante. entre 1000-01-01 y 9999-12-31. o simples nombres alternativos. TIME: Para guardar horas con el formato hh:mm:ss (horas. como acaba de ver. como fechas y horas: DATE: Permite almacenar fechas con el formato AAAA-MM-DD (año. Esto se debe a que. con los tipos numéricos que MySQL pone a nuestra disposición debería tener suficiente para cubrir la mayoría de sus necesidades. El rango permitido para la parte de la fecha es el mismo que para el tipo DATE . primero la fecha y luego la hora. INSERT INTO pelicula(titulo) VALUES('Alieni'). Soluciónelo: USE pruebas. El siguiente es un ejemplo de funcionamiento del tipo TIMESTAMP .21. 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. el valor almacenado puede estar entre 1970 y 2069. Vuelva a crear la tabla pelicula de la base de datos de pruebas para este ejemplo: USE pruebas. mientras que con cuatro dígitos está entre 1901 y 2155. En líneas generales. aunque no incluyó ninguno en la inserción. DROP TABLE IF EXISTS pelicula. YEAR: Un año indicado con dos o cuatro dígitos. De esta forma se puede controlar cuándo se creó un registro o cuándo cambió su valor. dependiendo del valor del modificador. Si utiliza dos dígitos. Su comportamiento varía dependiendo de la versión de MySQL que se utilice. TIMESTAMP: Tipo de datos un poco conflictivo. Lo utilizaremos para saber la fecha de la última modificación de un determinado registro.determinado instante. Realice una inserción en esta tabla: USE pruebas. UPDATE pelicula SET titulo = 'Alien' . Además se puede almacenar el año 0000. ¡Vaya. se ha cometido un error! El título de la película es incorrecto.21. Puede comprobarlo en la figura 3. Figura 3. Al consultar los registros de esta tabla verá que se ha insertado un valor en el campo modificado. CREATE TABLE pelicula( titulo VARCHAR(64). modificado TIMESTAMP ). Contenido de una columna TIMESTAMP La columna modificado contiene la fecha y la hora en la que se realizó la inserción. aunque de nuevo no se ha indicado valor alguno para esa columna.21. TIMESTAMP cambia automáticamente El repaso a los tipos de datos que MySQL permite utilizar en sus tablas ha concluido. Como puede ver. Figura 3.22 muestra el resultado de una consulta sobre la tabla tras la actualización de la columna errónea.com/doc/mysql/en/column-types. disponible en la siguiente página Web: http://dev.22.html . Si desea más información sobre los tipos de datos no dude en acudir a la documentación de MySQL. el valor de la columna modificado representa ahora un instante posterior al que podía verse en la figura 3.titulo = 'Alien' WHERE titulo = 'Alieni'. La figura 3.mysql. Estas funciones pueden ser invocadas con solo una línea de código. Para lograrlo tiene varias opciones. tal y como la entiende PHP y. Not a: La lista de parámetros de la función aparece entre corchetes. ya que sólo nos interesa el resultado de utilizar la función. puede crear funciones que no reciban ningún parámetro. La primera de ellas consiste en agrupar fragmentos de código en unidades funcionales o funciones. quedando oculto el verdadero trabajo que están realizando.4 PHP orientado a objetos Nuestro tercer encuentro con PHP lo hacemos con bastante ventaja. sin necesidad de volver a escribirlo varias veces. el último dedicado al aprendizaje de PHP. Veremos qué es esta forma de programación. Otra manera de lograr el mismo objetivo consiste en situar todo el código PHP común en archivos independientes. Es decir. . puede combinar el uso de funciones con los archivos externos anteriormente descritos. Durante este capítulo. verá cómo debe escribir sus programas para que ese trabajo pueda aprovecharse con posterioridad. Por supuesto. Funciones Una función es un fragmento de código agrupado bajo un mismo nombre. 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. Ahora tenemos mucho más claro qué podemos esperar de una herramienta como ésta. lo que indica que su definición es opcional. Luego podrá incluir el código de esos archivos en sus programas. 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. conociendo las bases del lenguaje y habiendo programado varios ejemplos. cómo podemos aprovecharla para que no tengamos que escribir el mismo código dos veces. de nuevo. La mayoría de los cambios que la versión 5 introdujo afectaban a la programación orientada a objetos. Su código es el siguiente: function par_impar($numero){ if($numero % 2 == 0){ print('par'). De hecho. Internamente. dentro de la función esos parámetros se utilizarán como si de variables se tratasen. $numero. esa función realiza una serie de operaciones que no es necesario que conozca. Veamos un sencillo ejemplo. 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. significa que ese número es par. En el cuerpo de la función utilizamos una instrucción condicional.Ya hemos utilizado funciones con anterioridad. escribimos par. 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'). La condición es que el resto de dividir el número pasado como argumento entre dos sea cero. en este caso $numero y dos. en caso contrario. El resultado: una página que muestra el texto impar. por lo que sus nombres deben seguir las mismas reglas que definimos en el segundo capítulo. }else{ print('impar'). La función recibe un solo argumento. Si el resto de dividir un número entre dos es cero. Por ejemplo. } } par_impar(7). Si lo es. } } El nombre de esta función es par_impar(). printf() en el capítulo 2. . impar. ?> Not a: El operador utilizado en la función par_impar() devuelve el resto de dividir los dos operandos. Lo único que le interesa es saber que la cadena que pase como parámetro a la función se le mostrará al usuario. Para declarar más de un parámetro ha de separarlos mediante comas. }else{ print('impar'). Esta función puede recibir como argumento una cadena de texto que será mostrada en el cliente Web cuando se vea la página. Parámetros La declaración de la lista de parámetros que una función recibe es similar a la declaración de variables. no lo escriba en una página para probarlo: <?php function incrementar($numero){ $numero++. Tiene razón. si se lo estamos preguntando será porque no es obvio. Utilice esta técnica sólo cuando tenga soltura con la programación en PHP. PHP permite que los parámetros de una función se pasen de dos formas: por valor y por referencia. print($i). consulte el apartado “Devolución de valores”. Cualquier modificación que hagamos a dicha variable se perderá al terminar la función. Parámetros predeterminados . 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. qué valor mostrará una página con este código? Claro. sin necesidad de hacer nada más. La realidad es otra: se muestra el número siete. ?> ¿Qué pasará. en lugar de pasar una copia de la variable. ha de indicarle a PHP que ese parámetro se va a pasar por referencia. 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++. } Not a: En la mayoría de los casos. como en nuestra función incrementar(). Un parámetro se pasa por valor de forma predeterminada. nuestras funciones no necesitan modificar los valores de los parámetros que recibe. Para lograrlo. Podría suponer que la página resultante mostrará el número ocho. Pero ¿qué pasaría si lo modificásemos? Fíjese en el siguiente código. } $i = 7. a la función le estamos pasando una copia de la variable $i. Entonces. Si desea que su función devuelva algún valor. PHP pasará la variable en sí misma. Valor y referencia La función par_impar() recibe un número como parámetro. En realidad.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 . El valor recibido no sufre alteración. resultado de incrementar el parámetro de la función. comprueba que el valor sea par o impar y escribe un mensaje. incrementar($i). más adelante. }else{ print('impar'). Aviso de PHP Not a: En el mensaje de aviso puede verse la ruta en la que se encuentran las páginas. Pero PHP ofrece una posibilidad muy interesante: crear funciones que aceptan . Se trataría de este caso: <?php function par_impar($numero){ if($numero % 2 == 0){ printf('par'). Efectivamente. ?> Si intenta cargar la página anterior. Argumentos variables Como hemos comentado. }else{ print('impar'). Es muy sencillo evitar el aviso anterior. puede crear funciones que acepten más de un parámetro. Sin embargo. que es el valor que toma cuando ese parámetro no se pasa: function par_impar($numero = 0){ if($numero % 2 == 0){ printf('par'). como puede verse en la figura 4. PHP le avisará que no se ha pasado argumento alguno a la función par_impar(). por lo que la función determina que el número pasado como parámetro es par. La carpeta en la que está instalado Apache en su ordenador puede ser otra. Sólo tiene que especificar el valor predeterminado del parámetro. } } par_impar(). el código de la página se ejecutará. el resto de dividir cero entre cero es cero. al tratarse de un aviso (o warning). con la salvedad de que no se produce ningún aviso.1. Figura 4.1. } } El comportamiento de la función es idéntico al que tenía antes.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. Puede comprobarlo porque al final de la misma puede leerse el texto par. ¡Un momento! Vamos a parar un momento. } sumatorio(3. 14. 15). ¿Qué es eso de que la función func_get_arg() devuelve una matriz? . ?> La función sumatorio(). muestra el resultado. 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. ?> Como recordará. En este ejemplo. usando un bucle for recupera uno por uno el valor de los parámetros y los suma. en primer lugar. guarda en la variable $parametros el número de argumentos que ha recibido. 32. 15). 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. El resultado será idéntico tanto usando un bucle for como usando un bucle foreach. Para terminar. 14. Al finalizar todas las iteraciones. } sumatorio(3. for($i = 0. ha de crear una función sin parámetro alguno y luego ayudarse de las funciones de PHP func_num_args(). La variable $parametro contendrá en cada iteración un elemento diferente de la matriz. Para ello.un número variable de parámetros. $resultado contendrá la suma de todos los argumentos pasados a la función. } printf($resultado). 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(). Después. $i++){ $resultado += func_get_arg($i). } printf($resultado). func_get_arg() y func_get_args(). la instrucción foreach permite iterar por todos los elementos de una determinada matriz. Utilizando la función func_get_args(). La primera de estas funciones devuelve el número de argumentos que la función ha recibido. La diferencia está en que el código del segundo es mucho más simple. $i < $parametros. Vamos a quedarnos con el primer capítulo. } ?> Trabajando con funciones Hasta ahora. en este libro hemos tenido dos contactos con PHP. El segundo. } } if(par_impar(7) == TRUE){ print('par'). Fue entonces cuando comprobamos que. 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). en lugar de hacerlo directamente desde dentro de ella. A continuación de ella indique el valor que la función debe devolver. 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. }else{ return(FALSE). cedemos la decisión de escribir un texto en la página Web resultante al código que llama a la función.¿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. }else{ print('impar'). El código completo del programa podría ser el siguiente: <?php function par_impar($numero){ if($numero % 2 == 0){ return(TRUE). } } De esta forma. En ese punto la función terminará. más sosegado. devolviendo el valor que ha indicado al código que la llamó. sólo nos interesaba tener una visión de conjunto de las posibilidades que MySQL y PHP ofrecían. }else{ return(FALSE). Si recuerda. Por ejemplo. puede cambiar el código de la función par_impar() que construimos anteriormente. el contenido de la . al añadir nuevos registros a dicha tabla. Sólo ha de utilizar la instrucción return. nos permitió aprender las principales reglas del lenguaje. En el primer capítulo fue un encontronazo. CREATE TABLE genero ( id INT UNSIGNED NOT NULL AUTO_INCREMENT. if ($res == FALSE){ echo('Error en la consulta. INSERT INTO genero(nombre. descripcion) VALUES('CF'. INSERT INTO genero(nombre. ''. 'SELECT * FROM genero' ). descripcion VARCHAR(32) NOT NULL. 'Drama'). nombre VARCHAR(2) NOT NULL. 'root'. 'Aventuras'). exit(). INSERT INTO genero(nombre. USE videoteca. 'Terror'). 'videoteca' ).'). resumiremos. INSERT INTO genero(nombre. CREATE DATABASE videoteca. el contenido de la página Web cambiaba sin necesidad de modificar el código PHP. La versión final del código de dicha página es el siguiente: <?php $conexion = mysqli_connect( 'localhost'.'). } ?> . mysqli_close($conexion). Por si acaso se saltó el primer capítulo. if ($conexion == FALSE){ echo('Error en la conexión. descripcion) VALUES('T'. PRIMARY KEY(id) ). } $res = mysqli_query( $conexion. descripcion) VALUES('D'. exit(). 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) VALUES('A'. 'Ciencia Ficción').al añadir nuevos registros a dicha tabla. <table border="1"> <tr> <th>id</th> <th>nombre</th> <th>descripcion</th> </tr> <?php while($fila = mysqli_fetch_row($res)){ printf('<tr>'). } ?> </table> <?php mysqli_free_result($res). Puede cambiar el comportamiento del bucle while. Sólo tenemos que volver a PHP desde HTML para escribir la cadena que contiene el listado de géneros. $fila[1]. ?> La figura 4. Figura 4. printf( "<td>%u</td><td>%s</td><td>%s</td>". mysqli_close($conexion). $fila[0]. Podría ser algo así: <?php $conexion = mysqli_connect( 'localhost'. $fila[2] ). printf('</tr>'). para que cree una cadena de texto a partir de los resultados obtenidos al realizar la consulta. 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.2. . ¿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. Ha sido necesario escapar de PHP en varias ocasiones.2 muestra el resultado de ejecutar el código PHP anterior. A continuación escaparíamos de PHP. mysqli_close($conexion). } while($fila = mysqli_fetch_row($res)){ $generos .'root'. ''. con dos bloques: uno con PHP y otro con HTML. $fila[1].').'). exit(). 'SELECT * FROM genero' ).= '<tr>'.2. if ($conexion == FALSE){ echo('Error en la conexión. así: <?php function cargar_generos(){ . aunque el código está algo más ordenado. ¿Y qué nos impide ubicar todo el código PHP en una única función.= sprintf('</tr>'). } $res = mysqli_query( $conexion. ?> </table> El resultado es el mismo que puede verse en la figura 4. ?> <table border="1"> <tr> <th>id</th> <th>nombre</th> <th>descripcion</th> </tr> <?php print($generos). $generos . que devuelva como resultado una cadena de texto con todos los géneros cinematográficos en filas para insertar en una tabla? Por ejemplo. if ($res == FALSE){ echo('Error en la consulta. $fila[0]. $fila[2] ). 'videoteca' ). exit(). $generos . } mysqli_free_result($res).= sprintf( "<td>%u</td><td>%s</td><td>%s</td>". mysqli_close($conexion). $generos . return $generos. $fila[2] ). } $res = mysqli_query( $conexion. $fila[0]. if ($conexion == FALSE){ echo('Error en la conexión. en lugar de devolver sólo las filas. 'root'. } while($fila = mysqli_fetch_row($res)){ $generos . 'SELECT * FROM genero' ). } ?> <table border="1"> <tr> <th>id</th> <th>nombre</th> <th>descripcion</th> </tr> <?php print(cargar_generos()). Puede cargar ese listado todas las veces que quiera llamando a la función varias veces.= sprintf( "<td>%u</td><td>%s</td><td>%s</td>". . Hemos conseguido colocar en una función todo el código necesario para cargar el listado de géneros cinematográficos.'). } mysqli_free_result($res).= '<tr>'.function cargar_generos(){ $conexion = mysqli_connect( 'localhost'. mysqli_close($conexion). $fila[1]. ?> </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. exit(). if ($res == FALSE){ echo('Error en la consulta. 'videoteca' ). exit(). $generos .'). mysqli_close($conexion). ''.= sprintf('</tr>'). php').= sprintf( "<td>%u</td><td>%s</td><td>%s</td>".= '<tr>'. } while($fila = mysqli_fetch_row($res)){ $generos . return $generos. $fila[0]. } $res = mysqli_query( $conexion. 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. } ?> A continuación. 'videoteca' ).'). ''. 'SELECT * FROM genero' ). $generos .'). $generos . exit(). $fila[1]. Ese archivo podría llamarse generos. exit().php: <?php function cargar_generos(){ $conexion = mysqli_connect( 'localhost'. Aunque existe una forma de ahorrarse ese trabajo.= sprintf('</tr>'). crearemos un segundo archivo PHP con el siguiente contenido: <?php include('generos. if ($res == FALSE){ echo('Error en la consulta. mysqli_close($conexion). si quiere escribir otra página diferente. $fila[2] ).Ahora bien. ?> <table border="1"> . que también muestre el listado de géneros tendrá que escribir de nuevo el código de la función. 'root'. mysqli_close($conexion). if ($conexion == FALSE){ echo('Error en la conexión. } mysqli_free_result($res). encuentra la instrucción include. Si quiere evitar que el resto de la página se siga ejecutando. que también permite reutilizar código pero que proporciona otras ventajas que veremos a continuación. como si efectivamente ambos fragmentos de código fuesen parte de la misma página. Ha aprendido a reutilizar el código mediante funciones. También existe require_once(). Puede ver un error de este tipo en la figura 4. Entonces busca el archivo indicado a continuación y lo incluye en la página actual. Figura 4. al cargar la segunda página. pero aún así intentará ejecutar el código del resto de la página. Las diferencias entre estas dos son las mismas que entre include() y require().3.3. Podrá comprobar que. guardando esas funciones en archivos independientes que luego pueden ser incluidos en otros archivos PHP. Un paso más allá está la programación orientada a objetos. que sí provoca un error. Orientación a objetos .<table border="1"> <tr> <th>id</th> <th>nombre</th> <th>descripcion</th> </tr> <?php print(cargar_generos()). Cuando PHP analiza el archivo para saber qué tiene que hacer cuando alguien le pide esa página. 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(). obtendrá el mismo resultado que pudo verse en la figura 4. ?> </table> Ambos archivos deben estar en la misma carpeta. puede utilizar la instrucción requiere.2. Sin embargo. el código de esta segunda página es considerablemente menor que el que se utilizó anteriormente. ¿Qué ocurre si el archivo que se intenta incluir no existe? PHP nos avisará de ello. En cuanto al comportamiento. como la devuelta por la función cargar_generos(). Si un método devuelve un valor. los programas anteriores mostraban la lista de categorías disponibles. Podríamos intentar escribir un programa cuyo resultado fuese el mismo. Intentemos crear una clase que represente a los géneros cinematográficos almacenados en la base de datos. Por ejemplo. a la derecha sus propiedades. La figura 4. la flecha será de salida. Para lograrlo hemos de intentar localizar las diferentes entidades con las que trabajamos en nuestros programas y aislarlas. de manera que vamos a limitarnos a sentar las bases necesarias para que esta metodología de programación no le sea desconocida. La versión de PHP 5 incorporó muchas novedades.Ríos de tinta han corrido hablando de la programación orientada a objetos. dependiendo de si puede asignarles valores o no. Una flecha de entrada indica si la propiedad es de lectura. La programación orientada a objetos tiene como finalidad una mejor organización de código y su posible reutilización. ¿Qué es un objeto? Un ejemplar de una clase. pero la mayoría de ellas en lo referido a la orientación a objetos. pero utilizando orientación a objetos. los métodos de la clase. El resultado de esta operación será una cadena de texto con las filas en formato HTML. Las propiedades de una clase describen su aspecto mientras que los métodos se corresponden con su comportamiento. tan de moda durante mucho tiempo como XML lo está siendo ahora. de lectura o de ambos tipos. . Una propiedad de la clase para los géneros podría determinar si el resultado se debe ordenar alfabéticamente o no. En una clase se definen las propiedades y los métodos de los objetos creados a partir de ella. una de salida si es de escritura. Las propiedades pueden ser de escritura. Y una clase. su ordenación. ¿qué es una clase? Clases Podemos definir una clase como la plantilla utilizada para crear un objeto.4 muestra una posible representación gráfica de una clase. Sería muy pretencioso por nuestra parte intentar exponer todas esas novedades con el espacio del que disponemos. ¿Qué puede ser "el aspecto" de la lista de géneros? Por ejemplo. lo tenemos fácil: necesitamos poder pedir a la clase de géneros que cargue los géneros de la base de datos. A la izquierda de la caja. } if($this->Ordenada == TRUE){ . Por tanto.Figura 4. Diagrama de una clase Este diagrama describe a la clase perfectamente. sin ordenación de ningún tipo.'). Sólo nos queda crear la clase. Not a: Si desea más información sobre consultas SQL consulte el capítulo 6. Si le asigna TRUE el resultado de llamar al método Cargar() estará ordenado alfabéticamente. el resultado se mostrará tal cual esté en la base de datos. exit(). ''. function Cargar(){ $conexion = mysqli_connect( 'localhost'. 'videoteca' ). if ($conexion == FALSE){ echo('Error en la conexión. El archivo se llamará generos. mientras que el método Cargar() devuelve un valor. el contenido del archivo generos.cls. La propiedad Ordenada es de escritura. El nombre de la clase es clsGeneros. El método Cargar() será similar a la función cargar_generos().php podría ser el siguiente: <?php class clsGeneros{ var $Ordenada = False. 'root'. En caso contrario. de forma que podrá asignarle valores TRUE o FALSE .4.php. La propiedad Ordenada será de tipo booleano. Para ellos vamos a utilizar un archivo que luego incluiremos en las páginas PHP que vayan a utilizar esta clase. que está dedicado a ello. Este método devuelve una cadena de texto que contiene todos los géneros de la base de datos.cls. comenzamos la declaración de la clase con la palabra reservada class. } mysqli_free_result($res).'). 'SELECT * FROM genero '. definimos el nombre de la clase: clsGeneros. El código del método Cargar() es como el de la función cargar_generos(). El código de la clase está entre llaves. que permite acceder a las propiedades y métodos de una clase desde el código de la propia clase. } while($fila=mysqli_fetch_row($res)){ $generos .= sprintf('</tr>'). return $generos. El prefijo sirve para indicar que se trata de una clase. } if ($res == FALSE){ echo('Error en la consulta. } } ?> Como puede verse en el código anterior. exit(). estando el resultado ordenado por nombre si su valor es TRUE . con una salvedad: la consulta que obtiene los géneros de la base de datos es diferente. mysqli_close($conexion). . $generos .= '<tr>'. 'ORDER BY nombre' ). 'SELECT * FROM genero' ). $generos . Not a: PHP proporciona un objeto especial llamado $t his. mysqli_close($conexion). cuyo valor predeterminado es FALSE .$res = mysqli_query( $conexion.= sprintf( "<td>%u</td><td>%s</td><td>%s</td>". }else{ $res = mysqli_query( $conexion. como $Ordenada. Es necesario utilizar la palabra reservada var antes de declarar una variable propia de una clase. Esta variable es una de las propiedades de la clase. $fila[2] ). dependiendo del valor que tenga $Ordenada. $fila[0]. $fila[1]. con la que hemos estado trabajando anteriormente. Dentro de una clase puede definir variables. A continuación. Cuando declaramos una variable cuyo tipo es una determinada clase se dice que estamos creando un ejemplar de esa clase. $sGeneros = $oGeneros->Cargar(). el nombre de la propiedad o el método que quiere utilizar.php'). Fíjese en que utilizamos require en lugar de include. esta línea crea un nuevo ejemplar de la clase clsGeneros y lo asigna (lo guarda) en la variable $oGeneros. pero la ordenación es diferente. Veamos un ejemplo: <?php require('generos. La clase por sí misma no hace nada.cls. Una vez tenga el objeto necesita acceder a sus propiedades para modificar su comportamiento y realizar tareas mediante sus métodos.Piense en esta clase como en una plantilla. La clase es la plantilla. ya que dicha página es imprescindible para la ejecución de ésta.2. ?> </table> Nuestra página comienza incluyendo aquella en la que se encuentra el código de definición de la clase. $oGeneros->Ordenada = TRUE. Para crear dicho ejemplar hemos de utilizar la palabra reserva new: $oGeneros = new clsGeneros. En el programa anterior modificamos el valor de la propiedad Ordenada así: $oGeneros->Ordenada = TRUE. El resultado de este programa es similar al que pudimos ver en la figura 4. Para ello ha de utilizar los caracteres -> a continuación del nombre del objeto. Y llamamos al método de carga de los géneros así: $sGeneros = $oGeneros->Cargar(). pero si crea en su programa una variable cuyo tipo sea la clase tendrá acceso a toda la funcionalidad definida en dicha clase. . y tras estos caracteres. El prefijo o viene de objeto. $oGeneros = new clsGeneros. Es decir.5. ?> <table border="1"> <tr> <th>id</th> <th>nombre</th> <th>descripción</th> </tr> <?php print($sGeneros). Puede comprobarlo en la figura 4. el ejemplar de la clase es el objeto. ?> </table> . ?> </table> </td><td> <table border="1"> <tr> <th>id</th> <th>nombre</th> <th>descripción</th> </tr> <?php print($sGeneros2). $sGeneros1 = $oGeneros1->Cargar().php'). $oGeneros1 = new clsGeneros. Géneros ordenados por nombre Puede crear tantos ejemplares de la clase clsGeneros como necesite. $oGeneros2 = new clsGeneros. $oGeneros2->Ordenada = FALSE.Figura 4.cls. $oGeneros1->Ordenada = TRUE. y cada uno de ellos tendrá sus propias propiedades. El siguiente código es perfectamente válido: <?php require('generos. $sGeneros2 = $oGeneros2->Cargar(). ?> <table><tr><td> <table border="1"> <tr> <th>id</th> <th>nombre</th> <th>descripción</th> </tr> <?php print($sGeneros1).5. .. la primera mostrará la lista de géneros ordenados por nombre.6. . el constructor es un método especial que se ejecuta siempre que se crea un ejemplar de dicha clase. Más allá de las clases . es posible definir una lista de argumentos que el constructor puede recibir. Hágalo justo debajo de la definición del método de carga: var $Ordenada. Constructores Dentro de una clase. Esa operación puede realizarse de otra manera: utilizando un constructor.6. function clsGeneros(){ $this->Ordenada = TRUE. Sería interesante que recibiese si quiere o no la lista de géneros ordenada: function clsGeneros($fOrdenada){ $this->Ordenada = $fOrdenada. mientras que la segunda no. Como si de un método normal y corriente se tratase. Con y sin orden En la definición de la clase asigne un valor inicial a la propiedad $Ordenada. Figura 4. Ahora.</table> </td></tr></table> Como resultado de cargar esta página obtendrá dos tablas. el comportamiento predeterminado del método de carga será devolver la lista de géneros ordenada. Puede verlo en la figura 4. } Al crear el ejemplar de la clase indicaremos si queremos ordenación o no: $oGeneros = new clsGeneros(TRUE). } Hemos trasladado la asignación de un valor inicial a $Ordenada al constructor de la clase. El nombre de ese método especial debe ser el mismo que el de la clase. Si añade el siguiente método al código de la clase clsGeneros tendrá su constructor. 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 El resultado de comparar cualquier valor . pero ningún intérprete: USE videoteca. sin el actor. Figura 5.4. De ella conocemos el título y el nombre del director.Ahora vamos a insertar una nueva película. ya que no se proporcionó valor alguno durante la inserción. La inserción se realizará sin problemas.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.5. SELECT * FROM pelicula. así es como debe ser. 'Douglas Trumbull' ). Pero la realidad puede verse en la figura 5. director ) VALUES( 'Naves misteriosas'.4: USE videoteca. La siguiente consulta de selección devolverá los valores que pueden verse en la figura 5. Figura 5. Concatenación con NULL Y no se trata de un comportamiento erróneo. La columna actor contendrá el valor NULL. INSERT INTO pelicula( titulo. director VARCHAR(128) NOT NULL. En el caso de la tabla de películas podríamos hacer obligatorio el título. actor VARCHAR(128) NOT NULL ). la recomendación desde aquí es evitar en lo posible el uso de valores nulos. como en la última que se ha utilizado para la película "Naves misteriosas". pero no el director ni el actor. DROP TABLE IF EXISTS pelicula. Existen variadas alternativas para evitar este comportamiento. Quede claro que esta recomendación se debe nada más que a experiencias personales. actor VARCHAR(128) NOT NULL DEFAULT '' ). Puede evitar la aparición de dicho error si asigna un valor predeterminado para las columnas no obligatorias. Utilice la instrucción ALTER TABLE que vimos en el tercer capítulo: . Por simplicidad. Cualquier operación aritmética en la que participe un valor NULL da como resultado NULL. CREATE TABLE pelicula( titulo VARCHAR(64) NOT NULL. 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. Cualquier concatenación con NULL acaba siendo NULL. DROP TABLE IF EXISTS pelicula. como el uso de cadenas vacías. se producirá un error. De esta forma. pero sin eliminar los registros que ya ha insertado en ella. 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. director VARCHAR(128) NOT NULL DEFAULT ''. CREATE TABLE pelicula( titulo VARCHAR(64) NOT NULL. DELETE FROM pelicula WHERE titulo = 'Naves misteriosas'. si en una inserción no indica el valor de alguna columna. 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.con NULL es NULL. También es posible cambiar las propiedades de la tabla de películas de acuerdo a lo que acaba de ver. INSERT INTO pelicula VALUES( 'Alien'. 'James Cameron'. Concatenación sin NULL Claves primarias Para explicar qué es una clave primaria vamos a volver a utilizar la tabla pelicula. llamada "Aliens". MODIFY director VARCHAR(128) NOT NULL DEFAULT ''. Ahora. por Sigourney Weaver: USE videoteca.Utilice la instrucción ALTER TABLE que vimos en el tercer capítulo: USE videoteca. vuelve a insertar la película "Naves misteriosas" y. SELECT * FROM pelicula . ALTER TABLE pelicula MODIFY titulo VARCHAR(64) NOT NULL. de nuevo. esta vez la segunda parte de "Alien". MODIFY actor VARCHAR(128) NOT NULL DEFAULT ''. consulte el contenido de la tabla pelicula y ordene el resultado por título: USE videoteca. Si. que está dando mucho juego. tras modificar la tabla. La inserción se realiza sin problemas. con lo que es posible utilizar la misma consulta para aquellas películas de las que no conozca su director o su actor. ejecuta la consulta de selección que concatena el nombre del director y el del actor. Insertemos una más. a continuación. 'Sigourney Weaver' ). dirigida por James Cameron y protagonizada. Figura 5. La figura 5.6 muestra el resultado de dicha consulta. podrá comprobar que el resultado ya no incluye ningún NULL.6. qué torpe! El título no se ha introducido correctamente. CREATE TABLE pelicula( titulo VARCHAR(64) NOT NULL. Figura 5. Cambie la sentencia para crear la tabla pelicula de manera que el título sea la clave primaria: USE videoteca. PRIMARY KEY(titulo) ).pelicula ORDER BY titulo. Veremos un ejemplo de esto al final del capítulo. ALTER TABLE . un valor mediante el cual se puede distinguir de forma única cada elemento de una determinada tabla. ¡Pero aun así. Con la segunda parte de "Alien" ¡Uy. así no perderá los datos almacenados en ella: USE videoteca. 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. director VARCHAR(128) NOT NULL DEFAULT ''. no era Alien sino Aliens. MySQL ha permitido introducir dos películas con el mismo título! Esto no está bien. Todos los registros deben tener algún valor almacenado en esa columna (no se permiten valores NULL). y todos los valores de dicha columna deben ser diferentes. Vea el resultado de realizar esta consulta en la figura 5. con las relaciones muchos a muchos.7. 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. Y precisamente eso es una clave primaria.7. el título de la película debería ser algo único. algo que permita diferenciar una película de otras. También puede modificar la tabla ya existente. actor VARCHAR(128) NOT NULL DEFAULT ''. 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. cree un índice para ella. Una de ellas. También hemos realizado un par de inserciones implícitas. de manera que sean únicas. Como en el que aparece al final de esta guía: busque el término que le interese. . Índices Con un índice es posible encontrar más rápido los datos que se necesitan. Solucionarlo es bien sencillo: USE videoteca. ¿Recuerda? "Alien" aparece dos veces. UPDATE pelicula SET titulo = 'Aliens' WHERE director = 'James Cameron'. con el paso del tiempo. Es muy importante seleccionar las claves correctas. que le permitía precisamente indicar qué valor se insertaría en una columna si no se indicaba ninguno. 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. Si insertábamos de forma explícita un valor. Podría llevarse una sorpresa si. se encuentra con que sí existen dos películas con el mismo título. Hablaremos con más detalle los índices en el capítulo dedicado a la optimización. Si sabe que las búsquedas de valores de una determinada columna serán frecuentes. y allí aparecerá el número de página al que tiene que acudir. Para las tablas se puede utilizar una técnica similar. las dos en el capítulo dedicado a tipos de datos. al explicar el uso del modificador DEFAULT .ALTER TABLE pelicula ADD PRIMARY KEY(titulo). Bastante más rápido que leer desde la primera página hasta localizarlo. como verá. sabíamos que éste sería el almacenado en la columna. que encontrará rápidamente gracias a que está organizado por orden alfabético. La segunda inserción implícita tenía lugar al utilizar el tipo TIMESTAMP . 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. se produce un error: existe un valor duplicado para la clave que está intentado crear. Y. Si selecciona todos los registros de la tabla verá que a los existentes ya se les ha asignado un identificador único. Podría tratarse de un número. actor VARCHAR(128) NOT NULL DEFAULT ''. Con cada nueva inserción en la tabla. Utilice las siguientes instrucciones para crear una tabla con esas características: USE videoteca. "La cosa". Es posible que el identificador asignado a cada película que aparece en dicha figura no sea el mismo en su caso. La única condición que debe cumplir es que sea diferente para cada registro. Puede comprobarlo en la figura 5. CREATE TABLE pelicula( id INT NOT NULL AUTO_INCREMENT. 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. Y para ahorrar esfuerzos. porque es algo que no se repite. manteniendo los registros ya existentes: USE videoteca. director VARCHAR(128) NOT NULL DEFAULT ''.8. lo ideal sería que la columna fuese de incremento automático. Sin embargo. es una nueva versión de la película del mismo título de 1951. titulo VARCHAR(64) NOT NULL.Existe otra forma de insertar valores de forma implícita en una columna: utilizando el incremento automático. Por ejemplo. . ADD PRIMARY KEY(id). un identificador que permita diferenciar entre una y otra película. un nuevo valor se insertará de forma automática en la columna id. diferenciando de forma única cada registro de la misma. Anteriormente tomamos la decisión de utilizar como clave primaria de la tabla de películas el título de las mismas. ALTER TABLE pelicula DROP PRIMARY KEY. la historia del cine está plagada de películas con títulos idénticos. PRIMARY KEY(id) ). ADD id INT NOT NULL AUTO_INCREMENT FIRST. dirigida por John Carpenter. para que MySQL se encargase de hacer que todos sus valores fuesen diferentes. También existe la posibilidad de modificar la tabla para lograr el mismo resultado. ¿No debería ser posible insertar en la tabla las dos películas. Por supuesto. Suponga que tiene tantas buenas películas que sus amigos no hacen más que pedírselas prestadas. Sin embargo. a fin de cuentas. 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. Figura 5.Figura 5. tanto impresas como en Internet. La tabla de películas. esto es una guía práctica. Lo mejor para comprenderlo es un sencillo ejemplo. en esta guía prima lo práctico. Sin embargo. ha decidido guardar en otra tabla de la base de datos una lista de préstamos. ¿Cómo se consigue algo así? Vea en la figura 5. con el tiempo comprenderá que se trata de una herramienta imprescindible. tanto histórica como teórica. ¿Qué significa esto? Entre otras cosas.8. Nueva clave primaria Puede que ahora mismo no encuentre demasiada utilidad a este tipo de columnas. que es posible relacionar entre sí las diferentes tablas que componen una base de datos. Es más.9. si está interesado podrá encontrar todas las fuentes de documentación al respecto que necesite. y siempre se le olvida a quién deja qué película. A los más puristas no les gustará nada que nos saltemos toda esa parte pero. 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. Tras este modelo para la organización de los datos existe amplia documentación. 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.9 cómo ha quedado el diseño de la tabla de películas tras aplicar lo aprendido en los apartados anteriores. Y con el tiempo es al terminar este capítulo. En esa lista sólo necesita almacenar el . le recomendamos que lo haga. de ahí la palabra relacional. mientras que la tabla a la que hace referencia se conoce como tabla madre o principal. que contiene la clave externa. . Ahora que disponemos de dos tablas relacionadas vamos a comprobar que se cumple lo descrito acerca de las relaciones. Not a: La tabla prest amo. Tabla de préstamos La primera columna. fecha DATE NOT NULL. id. existe la posibilidad de que se inserte como identificador de la película un valor sin contrapartida en la tabla pelicula. Como la tabla de películas contiene un campo llamado id que identifica a cada registro de forma inequívoca. Cuando esa condición se cumple. la película que se lleva prestada y en qué fecha se la llevó. se dice que se está manteniendo la integridad referencial entre las tablas.10. que es la clave primaria de la tabla. Utilice las siguientes instrucciones para crear la tabla de préstamos: USE videoteca. Para ello sólo tenemos que realizar inserciones en la tabla de préstamos. el identificador que MySQL asignó automáticamente a esa película es el 4.10. Pero claro. idpelicula INT NOT NULL. tiene las mismas características que la homónima de la tabla pelicula: un identificador de incremento automático. persona VARCHAR(128) NOT NULL. vamos a prestar "Contact" a Kake. algo parecido a lo que se puede ver en la figura 5. y que idpelicula es una clave externa. idpelicula. persona. contiene el nombre de quien se lleva la película. Como pudo verse en la figura 5. DROP TABLE IF EXISTS prestamo. La segunda columna. Figura 5. puede guardar aquí ese campo para saber qué película se llevó su amigo. En tercer lugar. En primer lugar. PRIMARY KEY(id).nombre de la persona. FOREIGN KEY(idpelicula) REFERENCES pelicula(id) ). el identificador de la película.8. Lo ideal sería que MySQL controlase que en ese campo sólo se pudiesen insertar valores existentes en dicha tabla. CREATE TABLE prestamo ( id INT NOT NULL AUTO_INCREMENT. así que: USE videoteca. se conoce como tabla hija o secundaria. Como ve.11. fecha ) VALUES( 4. El primer préstamo Ahora comprobaremos cómo funciona la integridad relacional. Utilice el identificador asignado en su sistema para este ejemplo.11. El propósito de esta jugarreta ha sido demostrarle lo sencillo que es perder la consistencia de los datos de una . ¿Cómo? ¿Que no informa de ningún error? ¿Que se ha podido realizar la inserción? Claro que se ha podido. persona. MySQL le informará de que ha surgido un error. Figura 5. sólo intentaba comprobar si prestaba atención. CURRENT_DATE() ). Advert encia: Es posible que el identificador de "Contact" en su tabla de películas sea otro. Si ahora selecciona todos los registros de la tabla prestamo podrá ver algo parecido a lo que aparece en la figura 5. 'Germán'. 'Kake'. intentando prestar una película no presente en la base de datos. CURRENT_DATE() ). Utilice un identificador de película que no exista: USE videoteca.. no se preocupe en absoluto. hemos utilizado la función CURRENT_DATE() para guardar la fecha actual en la columna fecha. fecha ) VALUES( 123. INSERT INTO prestamo( idpelicula. persona..INSERT INTO prestamo( idpelicula. simplemente las ignora. ALTER TABLE pelicula ENGINE = InnoDB. INSERT INTO prestamo( idpelicula. elimine y vuelva a crear la tabla de préstamos: USE videoteca. persona. no incorpora los mecanismos de integridad relacional. idpelicula INT NOT NULL. Esto se debe a que. CREATE TABLE prestamo ( id INT NOT NULL AUTO_INCREMENT. Para lograr nuestro objetivo hemos de utilizar tablas InnoDB. 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. fecha DATE NOT NULL.base de datos si no se presta atención durante la fase de diseño. el tipo de tabla predeterminado es InnoDB. Ahora. Intente ahora la inserción del préstamo de una película inexistente: USE videoteca. Cuando MySQL encuentra las instrucciones de integridad referidas a una tabla MyISAM. para ellos. de las que ya hablamos en el capítulo tercero. FOREIGN KEY(idpelicula) REFERENCES pelicula(id) ) ENGINE = InnoDB. DROP TABLE IF EXISTS prestamo. 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. . ¿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. El primer paso para lograr que la integridad referencial funcione es convertir la tabla de películas en una tabla InnoDB: USE videoteca. así de fácil. Localizar este tipo de problemas en una tabla con dos registros es sencillo pero. 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. que rompía la integridad referencial. película que no existe en la base de datos. persona VARCHAR(128) NOT NULL. MyISAM. PRIMARY KEY(id). Hecho. no MyISAM. Esta última inserción ha conseguido que se inserte un préstamo de la película con identificador 123. Es el caso de la relación entre tablas que acaba de crear. Como podrá comprobar. un registro de la tabla hija puede estar relacionado con cualquier registro de la tabla madre y viceversa. aunque a lo largo del tiempo esa película la ha podido tener mucha gente. ya que así sólo podría guardar un registro por película. 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. fecha) VALUES( 123. Un actor puede haber participado en muchas películas y. Hemos logrado (no sin esfuerzo) nuestro objetivo. MySQL ya no le permite insertar en la columna idpelicula identificadores de películas que no estén en la tabla pelicula. Muchos a muchos: En esta relación. La figura 5. Adelantando contenidos. 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. un registro de la tabla principal puede estar relacionado con más de uno de la tabla hija. Figura 5. . 'Germán'. es el "divide y vencerás". y en el de la informática en general. Una de ellas contendrá información sobre los actores. en una película pueden participar muchos actores.12.12 muestra un diagrama de su primera base de datos con tablas relacionadas. Tras lo visto hasta ahora dispone de los conocimientos necesarios para afrontar el objetivo de este capítulo. CURRENT_DATE() ). Resulta interesante si no se quiere almacenar un histórico de préstamos (algo que ahora sí se puede hacer). mejorar el diseño de esta base de datos. A su vez. 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. en el siguiente apartado dividiremos la tabla de películas en otras tablas. a su vez. relacionada con la tabla de películas. Un préstamo sólo se aplica a una determinada película. Una de las técnicas más empleadas en el mundo de las bases de datos.persona. etcétera). La figura 5. Utilizó estas instrucciones para crearla: USE videoteca. CREATE TABLE pelicula( id INT NOT NULL AUTO_INCREMENT. DVD.9. nm0000631.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.com/) dedicada al cine asigna a ese director. titulo VARCHAR(64) NOT NULL. actor VARCHAR(128) NOT NULL DEFAULT ''.13 muestra la página del director Ridley Scott . Pudo ver su diseño en la anterior figura 5. . imdb_director: El identificador que la famosa Web IMDb (http://imdb. Una aplicación podría utilizar este dato para mostrar una página con detalles de un director en concreto. Creación de tablas con MySQL Workbench Vamos a mejorar el diseño de la tabla de películas. director VARCHAR(128) NOT NULL DEFAULT ''. 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. aparece en la barra de direcciones. Se guardará en una cadena de 32 caracteres. Su identificador. PRIMARY KEY(id) ) ENGINE = InnoDB. Siga estos pasos para crear esta tabla utilizando MySQL Workbench: 1.Figura 5. Ridley Scott en IMDb imdb_actor: Igual que el campo imdb_director . Inicialmente. Ponga en marcha MySQL Workbench. el aspecto de este programa es que el puede verse en la figura 5. pero aplicado al actor. genero_desc: Descripción de las siglas del campo anterior. .13. genero: Siglas del género cinematográfico al que pertenece la película.14. mostrándole una rejilla en la que podrá situar los diferentes elementos que compongan su base de datos. 3. También puede utilizar la combinación de teclas Control-T . MySQL Workbench 2. El aspecto de MySQL Workbench cambiará. Vamos a añadir un nuevo diagrama: seleccione la opción Add Diagram del menú Model. . Para comenzar a trabajar con un documento en blanco seleccione la opción New del menú File.14. tal y como muestra la figura 5.Figura 5.15. significa diagrama entidad-relación mejorado (Enhanced Entity Relationship). 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. La segunda. es la que pudo ver en la figura 5. La primera. bajo la barra de menús.14. Para ello. como puede ver en la figura 5. Cree una nueva tabla. Escriba videoteca y pulse la tecla Intro.15. 5. Antes de nada. se insertará una nueva tabla. cambie el nombre de la base de datos. Fíjese en el panel de la derecha llamado Catalog. espere y vuelva a hacer clic para poder editar su nombre. El nombre de la base de datos actual es mydb. cuando haga clic sobre la zona de edición del documento. . 6. Aparecerá una nueva tabla con un nombre predeterminado table1. También puede hacer clic con el botón derecho sobre él y seleccionar la opción Rename del menú contextual. Haga clic en la zona de edición del documento. EER Diagram.16. aparecen ya dos fichas. MySQL Model.Figura 5. en la parte central de la ventana donde se encuentra la rejilla. El puntero del ratón cambiará de forma para indicarle que. Haga clic sobre él. 4. Diagrama en blanco Not a: Fíjese en que. etcétera. MySQL Workbench le presentará el editor de tablas. el tipo de tabla. cambiar sus propiedades.17 le muestra este panel tal y como quedaría tras introducir los detalles de las columnas de la tabla pelicula. desde el que puede añadir nuevos campos. en la parte inferior de la ventana del programa. La figura 5. .Figura 5. Haga doble clic sobre el nombre de tabla que acaba de aparecer.16. Nueva tabla 7. Además de tener una representación visual de sus tablas. imdb_director VARCHAR(32) NOT NULL DEFAULT ''. 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. actor VARCHAR(128) NOT NULL DEFAULT ''. soporte VARCHAR(3) NOT NULL DEFAULT ''. titulo VARCHAR(64) NOT NULL. 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. genero_desc VARCHAR(32) NOT NULL DEFAULT ''.Figura 5. Haga clic con el botón derecho del ratón sobre la tabla y seleccione la opción Copy SQL to Clipboard. 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. también puede obtener las instrucciones necesarias para crear la que acaba de diseñar. PRIMARY KEY (id) ) ENGINE = InnoDB. Diseñando la nueva tabla 8. genero VARCHAR(2) NOT NULL DEFAULT ''. imdb_actor VARCHAR(32) NOT NULL DEFAULT ''.17. Para terminar. director VARCHAR(128) NOT NULL DEFAULT ''. 'DVD'. imdb_director. 'DVD'. director. imdb_actor. imdb_director. 'Ridley Scott'. 'Ridley Scott'. 'nm0000128'.videoteca. INSERT INTO pelicula( titulo.) y. director. 'Ciencia-ficción' ). . genero. 'A'. Cree ahora la tabla de películas (no se olvide de seleccionar antes en qué base de datos con USE videoteca. actor. 'Russell Crowe'. CREATE DATABASE videoteca. 'nm0000631'. actor. 'nm0000631'. genero_desc ) VALUES( 'Gladiator'. imdb_actor. soporte. 'nm0000148'. genero. 'Aventuras' ). 'CF'. Es posible que ya exista si la creó en el segundo capítulo. INSERT INTO pelicula( titulo. Las siguientes instrucciones eliminarán esta base de datos si ya existiese y la volverán a crear: DROP DATABASE IF EXISTS videoteca. genero_desc ) VALUES( 'Blade Runner'. inserte algunos datos en la tabla: USE videoteca. 'Harrison Ford'. a continuación. soporte. Podría escribir Harrisond Ford como protagonista de . imdb_actor.18. ¿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. 'nm0000148'. genero_desc ) VALUES( 'A propósito de Henry'. 'D'. si ese actor ya participó en alguna de las películas que tiene en la base de datos. 'VHS'. Fíjese en el uso de \G al final de la operación de consulta. Figura 5. 'Harrison Ford'. es posible que cometa algún error al introducir el nombre de algún actor. El resultado de hacer una consulta de selección tras estas inserciones puede verse en la figura 5. 'Drama' ). genero.INSERT INTO pelicula( titulo. ocupando más espacio. Con relación al punto anterior. imdb_director. estará duplicando los datos. Los datos de partida Con este diseño y estos datos de partida. actor. 'nm0001566'. director. soporte. 'Mike Nichols'.18. no hemos continuado con esa división en las tablas obtenidas. Los datos han de dividirse todo lo posible. Algunas. por ejemplo. Por sí misma. siempre que esta división sea útil. División de tablas Vamos a comenzar con los directores. Cree una nueva tabla en la que almacenar los detalles de cada uno de ellos. creada con MySQL Workbench. Otro diseño de la tabla de directores . por ejemplo). Aunque hemos comenzado con la división de la tabla principal. como "Delicatessen". fueron dirigidas por dos personas. por el error en el nombre.19 muestra el aspecto de dicha tabla. utilizando claves externas como las que vio en el apartado dedicado a las bases de datos relacionales. La figura 5. Esta misma fuente de errores se repite con el género de la película y su descripción. 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. puede llevar a cabo correspondencias con cada película.19.20 muestra este otro diseño de la tabla de directores. de los actores. Pero aún hay algo que falla en esta tabla. ¿Qué más se puede dividir en esta tabla? El nombre del director. Lo mismo se puede decir.una de las películas de Indiana Jones. ahora se convierte en dos. La figura 5. Figura 5. la creación de una tabla para la gestión de los directores de películas podría tener sentido. con más razón. a la vez que se evitan errores en la introducción del nombre. que sólo permitía ordenación por el nombre. De esta forma. podría dividirlo en dos partes: nombre y apellidos. Sólo puede indicarse un director por película. Figura 5. la de Indiana Jones no aparecería. haciendo bueno el dicho "divide y vencerás". Los datos de los directores ¡Fantástico! Ya tiene una tabla para los directores que. y con los códigos de IMDb. lo que antes era un único campo (Ridley Scott. Si posteriormente hiciese una consulta de las películas protagonizadas por este actor.20. Esto le da la oportunidad de ordenar también por los apellidos. PRIMARY KEY(id) ) ENGINE = InnoDB. imdb VARCHAR(32) NOT NULL DEFAULT ''. y otra al actor. PRIMARY KEY(id) ) ENGINE = InnoDB. Ha de incluir una referencia al director de la película. para seguir guardando los mismos datos que antes. imdb VARCHAR(32) NOT NULL DEFAULT ''. es necesario introducir el resto de valores en cada inserción. CREATE TABLE director ( id INT NOT NULL AUTO_INCREMENT. 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.21.22. Figura 5. apellidos VARCHAR(64) NOT NULL. Los datos de los actores.21 muestra el diseño de dicha tabla. Relacionar tablas El diseño de la tabla de películas ha de cambiarse para reflejar los cambios realizados en la sección anterior. Figura 5. La figura 5. por separado El código para crear esta tabla es el siguiente: USE videoteca. 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. nombre VARCHAR(64) NOT NULL. CREATE TABLE actor ( id INT NOT NULL AUTO_INCREMENT. 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. nombre VARCHAR(64) NOT NULL. Por el contrario. apellidos VARCHAR(64) NOT NULL. Este cambio se muestra en la figura 5.22. 5. Haga clic sobre la tabla pelicula para seleccionarla. Active la ficha Foreign Keys. 3.23. La relación entre directores y películas es lo que se definió anteriormente como una relación uno a muchos. Introduzca el nombre de la tabla con la que quiere relacionar la actual en la primera fila de la columna Referenced Table . Figura 5. Siga estos pasos para crear relaciones utilizando MySQL Workbench: 1. en este modelo. Introduzca el nombre que quiera dar a la relación en la primera fila de la columna Foreign Key Name. Como se trata de saber quién ha dirigido cada película. 7. director y pelicula. Marque la casilla de verificación del campo iddirector . ya que ahora estarán en las tablas correspondientes. 6. Justo a la derecha del panel con el que hemos estado trabajando podrá ver la lista de los campos de la tabla pelicula. la columna idactor debe estar relacionada con la columna id de la tabla actor . una película sólo la dirige un director. Seleccione el campo id. pero un director puede haber dirigido muchas películas. Repita la operación con la tabla de actores. Para terminar tenemos que relacionar las tres tablas existentes entre sí: actor . En este caso hemos de seleccionar la tabla director . Por otra parte. 2. por los identificadores correspondientes de las tablas que acaba de crear. Traduciendo: por ahora. y eliminar los datos de IMDb que se guardaban. que toma datos de las dos primeras. La columna iddirector debe estar relacionada con la columna id de la tabla director . 4. llamémosla dirigida_por .23. El aspecto del modelo en ese momento será similar al que puede verse en la figura 5. Primer paso de la creación de relaciones El modelo de datos que tiene ahora permite mantener una lista de directores. Este . Cuando lo haga se desplegará una lista con los campos de la tabla de directores.actor. otra de actores y una última de películas. Una lista desplegable le permitirá seleccionar entre las tablas existentes. se encuentra en la parte inferior de la ventana de MySQL Workbench. que guardaban sus nombres. formatos y géneros. dividiendo el modelo. De esta manera.24 puede ver el aspecto del modelo resultante tras la nueva división de los datos. Para ello.24.proceso de simplificación. el resultado final es que la tabla de películas tendrá una relación de muchos a muchos con la de actores. Películas. El soporte en el que está grabada la película puede ser otra tabla que. En la figura 5. directores y actores Aún se puede añadir una mejora más al modelo. de nuevo. idactor2. soporte y genero. tras eliminar los campos correspondientes de las nuevas tablas. Figura 5. La opción más sencilla sería incluir otro identificador de actor más. los identificadores necesarios a la tabla de películas para mantener las relaciones entre películas. al igual que la tabla de actores. El identificador del actor dejará de estar en la tabla de películas y pasará a esta nueva tabla. permitiendo que una película pueda estar protagonizada por más de un actor. que ocasiona la aparición de dos nuevas tablas. y la incorporación de los campos idsoporte e idgenero a la tabla pelicula. Los géneros también podrían llevarse a otra tabla. Pero entonces ¿qué ocurre si se quiere guardar información sobre tres actores? ¿Creamos un tercer campo. algo que este no permite en este momento. que almacenará las relaciones entre películas y actores. por ahora. 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. puede seguir aplicándose a la tabla de películas. pero que en el futuro puede contener los valores de los formatos que vaya añadiendo a su videoteca. Puede ver cómo quedará esta . como ha visto. Ahora mismo es una relación uno a muchos. La tabla de películas tendrá una relación de uno a muchos con la tabla de actores por película. es necesario utilizar una tabla intermedia. Hay que lograr convertirla en una relación muchos a muchos. sólo contendrá los valores DVD y VHS. Debería añadir. Por ejemplo. INDEX actores_por_pelicula_fk2( idactor ). Figura 5. DROP TABLE IF EXISTS pelicula. Sería necesaria otra inserción en la tabla de películas para crear la película. nombre VARCHAR(64) NOT NULL.25. DROP TABLE IF EXISTS actor.parte del modelo de la base de datos en la figura 5. Tenga en cuenta que ahora. FOREIGN KEY(idactor) REFERENCES actor(id) ) ENGINE = InnoDB. apellidos VARCHAR(64) NOT NULL. titulo VARCHAR(64) NOT NULL. PRIMARY KEY(id) ) ENGINE = InnoDB. CREATE TABLE actor ( id INT NOT NULL AUTO_INCREMENT. una inserción . es necesario realizar más inserciones. idactor). CREATE TABLE actores_por_pelicula ( idpelicula INT NOT NULL.25 sería necesario ejecutar las siguientes instrucciones: USE videoteca. FOREIGN KEY(idpelicula) REFERENCES pelicula(id). CREATE TABLE pelicula ( id INT NOT NULL AUTO_INCREMENT. Se ha simplificado la tabla de películas para que sólo incluya los campos interesantes para este apartado. idactor INT NOT NULL.25. imdb VARCHAR(32) NOT NULL DEFAULT ''. Una relación muchos a muchos Por ejemplo. y por último. PRIMARY KEY(idpelicula. para crear las tablas que se pueden ver en la figura 5. para guardar en la base de datos los detalles de una película. INDEX actores_por_pelicula_fk1( idpelicula ). "Blade Runner" requeriría una inserción en la tabla de actores para disponer de Harrison Ford. DROP TABLE IF EXISTS actores_por_pelicula. PRIMARY KEY(id) ) ENGINE = InnoDB. apellidos. INSERT INTO pelicula(titulo) VALUES('Blade Runner'). 'Ford'. 'nm0000148'). 'Hauer'. SELECT id FROM actor WHERE imdb = 'nm0000442'. Esta última inserción requiere que conozca los identificadores tanto del actor como de la película. . SELECT id FROM pelicula WHERE titulo = 'Blade Runner'. 10 ). INSERT INTO actor(nombre. Este modelo le permitiría incluir un segundo actor relacionado con la película de la siguiente forma: USE videoteca. 'nm0000442'). idactor ) VALUES( 15. imdb) VALUES('Rutger'. apellidos. imdb) VALUES('Harrison'. que pueden obtenerse mediante una consulta: USE videoteca. 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. SELECT id FROM actor WHERE imdb = 'nm0000148'. 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. Encontrará más información al respecto en los capítulos correspondientes. INSERT INTO actor(nombre. INSERT INTO actores_por_pelicula( idpelicula.en la tabla de actores por película para crear la asociación entre ambos. 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.26.27 muestra el mismo diagrama que la 5. Figura 5. dedicado a las consultas de datos. MySQL Workbench ocultará los campos de las tablas. podrá ver cómo recuperar la información de los actores que han trabajado en una determinada película.27. 11 ). Not a: En el siguiente capítulo. Figura 5. ¡El diseño. La figura 5. 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. por fin! Existe un truquito de MySQL Workbench que permite trabajar con diseños grandes en poco espacio. La figura 5.26.26 muestra el diseño final de la base de datos tras incorporar este cambio. idactor ) VALUES( 15. pero tras utilizar dicho triángulo para simplificar el aspecto del diagrama. Simplificación del diagrama . así como otras consultas más complejas.INSERT INTO actores_por_pelicula( idpelicula. Una nota final: queda como ejercicio mejorar el diseño de la tabla dedicada a almacenar los préstamos de las películas.Durante este capítulo se ha terminado de diseñar la base de datos con la que trabajaremos en los capítulos sucesivos. una calificación sobre la misma o los comentarios que desee. añadir más campos a la tabla principal para guardar la fecha de la película. O. 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. . por ejemplo. le permite comunicarse con el sistema gestor de bases de datos para realizar todas esas operaciones. Mientras la base de datos se encuentre en funcionamiento estas cuatro operaciones serán fundamentales. en el que podrá hacer todas las pruebas necesarias. borrados o simples solicitudes de información. La práctica logrará que se convierta en una tarea más. la utilización de SQL proporciona muchas ventajas de las que hablaremos a lo largo de este capítulo. el diseño de la base de datos le acarreará dolores de cabeza. ya sean inserciones. que debe tener lugar al principio del proceso de desarrollo. pero no va a ser el caso. Le recomendamos que. Existen herramientas visuales para llevar a cabo las tareas de mantenimiento de las bases de datos. que facilitan mucho las inserciones puntuales. en el que la aplicación funcionará una vez se haya probado convenientemente. 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. Por último. por otro. lo que permitirá ilustrar algunas de las ventajas de este método de trabajo. 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. Estos valores se utilizarán durante el resto del capítulo. Continuaremos insertando valores en las tablas de la base de datos. Sin embargo. por varios motivos. precisamente utilizando instrucciones SQL. veremos los borrados. por un lado. el uso de las herramientas visuales como MySQL Administrator y MySQL Query Browser para crear bases de datos y tablas y. siempre que sea posible. La base de datos de ejemplo Quizá sería interesante ofrecerle una lista de ventajas y desventajas comparando. Tras repasar las consultas para la creación y el mantenimiento de bases de datos. el uso de archivos de instrucciones (también conocidos como scripts). actualizaciones. o SQL. utilice archivos de instrucciones para este tipo de tareas.6 SQL Las primeras veces que se encargue de él. Existe una tarea que le ocupará bastante más tiempo que el diseño: las consultas a la base de datos. El lenguaje estructurado de consultas. Comenzaremos creando desde cero la base de datos que diseñamos en el capítulo anterior. y un servidor de explotación. . dentro del apartado dedicado a este capítulo. puede repetir la operación de forma exacta e idéntica todas las veces que lo necesite. descripcion VARCHAR(32) NOT NULL. . El contenido de ese archivo es el siguiente: DROP DATABASE IF EXISTS videoteca. Consejo: Le recomendamos encarecidamente que. dadas unas instrucciones muy sencillas.sql.Crear la base de datos. Sin embargo. lo haga. nombre VARCHAR(2) NOT NULL. CREATE TABLE director ( id INT NOT NULL AUTO_INCREMENT. introduciría un punto de fallo. ahorrará un valioso tiempo en el futuro. 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. Creación de la base de datos En los archivos de ejemplo de este libro. Una vez disponga de las instrucciones de creación de la base de datos y de sus tablas. sin necesidad de tener el más mínimo conocimiento acerca del diseño de la misma. si existe la posibilidad de automatizarla mediante el empleo de archivos de órdenes. cualquiera puede crear la bases de datos. Aunque le cueste más esfuerzo al principio. apellidos VARCHAR(64) NOT NULL. PRIMARY KEY(id) ) ENGINE = InnoDB.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. en cualquier operación que tenga que realizar con MySQL. DROP TABLE IF EXISTS director. USE videoteca. Más aún. CREATE DATABASE videoteca. CREATE TABLE genero ( id INT NOT NULL AUTO_INCREMENT. imdb VARCHAR(32) NOT NULL DEFAULT ''. podrá encontrar un archivo llamado 01 . DROP TABLE IF EXISTS genero. PRIMARY KEY(id) ) ENGINE = InnoDB. una vez creados los archivos de instrucciones necesarios. 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. nombre VARCHAR(64) NOT NULL. Podría cometer algún error al repetir las operaciones una y otra vez. FOREIGN KEY(idpelicula) . PRIMARY KEY(id) ) ENGINE = InnoDB. idactor). nombre VARCHAR(3) NOT NULL. CREATE TABLE actores_por_pelicula ( idpelicula INT NOT NULL. INDEX p_FK2(idgenero). DROP TABLE IF EXISTS directores_por_pelicula. descripcion VARCHAR(32) NOT NULL. imdb VARCHAR(32) NOT NULL DEFAULT ''.DROP TABLE IF EXISTS actor. apellidos VARCHAR(64) NOT NULL. nombre VARCHAR(64) NOT NULL. idsoporte INT NOT NULL. PRIMARY KEY(idpelicula. CREATE TABLE actor ( id INT NOT NULL AUTO_INCREMENT. INDEX p_FK1(idsoporte). CREATE TABLE pelicula ( id INT NOT NULL AUTO_INCREMENT. iddirector INT NOT NULL. INDEX dpp_FK1(idpelicula). DROP TABLE IF EXISTS actores_por_pelicula. titulo VARCHAR(64) NOT NULL. PRIMARY KEY(id). idactor INT NOT NULL. FOREIGN KEY(idactor) REFERENCES actor(id) ) ENGINE = InnoDB. INDEX app_FK1(idpelicula). iddirector). FOREIGN KEY(idgenero) REFERENCES genero(id) ) ENGINE = InnoDB. CREATE TABLE directores_por_pelicula ( idpelicula INT NOT NULL. CREATE TABLE soporte ( id INT NOT NULL AUTO_INCREMENT. FOREIGN KEY(idpelicula) REFERENCES pelicula(id). DROP TABLE IF EXISTS soporte. idgenero INT NOT NULL. FOREIGN KEY(idsoporte) REFERENCES soporte(id). PRIMARY KEY(idpelicula. INDEX app_FK2(idactor). INDEX dpp_FK2(iddirector). PRIMARY KEY(id) ) ENGINE = InnoDB. DROP TABLE IF EXISTS pelicula. Puede utilizar un archivo que se encuentra en la misma ubicación que el que utilizó anteriormente para crear la base de datos. con los mismos elementos. FOREIGN KEY(iddirector) REFERENCES director(id) ) ENGINE = InnoDB. necesita un archivo en el que guardar las instrucciones SQL que acaba de ver.sql. Su nombre es 02 .1. Recuerde que si instaló MySQL a través de XAMPP y no cambió su configuración predeterminada. usted y yo. Entonces. El aspecto de la consola será similar al que puede verse en la figura 6. 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. Inserción de datos Tras la ejecución de las instrucciones de creación de la base de datos estaremos trabajando.Insertar valores iniciales. hablamos de él anteriormente. Si tiene acceso a Internet no es necesario que las escriba usted mismo.sql El cliente de MySQL le pedirá que introduzca la contraseña y. 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. Ahora aprenderá una forma nueva de hacerlo. le devolverá el control. Si no tiene acceso a Internet tendrá que teclear.1. Ejecútelo siguiendo los mismos pasos que con el de creación de base de datos y tablas. En primer lugar.FOREIGN KEY(idpelicula) REFERENCES pelicula(id). el usuario root no tendrá contraseña. Ahora vamos a llenar las tablas de la base de datos con los registros que utilizaremos durante los siguientes apartados. Las instrucciones de inserción incluidas en dicho archivo son las siguientes: . De un plumazo. guarde el archivo en el disco con el nombre crear. Y puede repetir la operación las veces que sea necesario con la misma facilidad. la base de datos y sus correspondientes tablas. ya sabe del archivo 01 .sql. tras pensárselo un momento.Crear la base de datos.sql. En segundo lugar. Creación de la base de datos Eso es todo. De nuevo vamos a utilizar archivos de instrucciones. 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. ejecute la siguiente orden: mysql -u root -p < crear. creadas. Figura 6. descripcion) VALUES('VHS'. 'Nichols'. idgenero) VALUES('A propósito de Henry'. apellidos. 'Aventuras'). DELETE FROM soporte. 2). descripcion) VALUES('CF'. INSERT INTO director(nombre. 1. 'nm0000128'). DELETE FROM pelicula. INSERT INTO soporte(nombre. DELETE FROM director. apellidos. imdb) VALUES('Ridley'. 'Ford'. apellidos. imdb) VALUES('Mike'. idactor . descripcion) VALUES('D'. 'Video Home System'). DELETE FROM actor. 'nm0001566'). 2. INSERT INTO pelicula(titulo. DELETE FROM directores_por_pelicula. imdb) VALUES('Russell'. INSERT INTO genero(nombre. idgenero) VALUES('Blade Runner'. 1. INSERT INTO actor(nombre. idsoporte.USE videoteca. 3). idgenero) VALUES('Gladiator'. 'Crowe'. 'nm0000148'). 'nm0000631'). INSERT INTO pelicula(titulo. apellidos. 'Drama'). 1). DELETE FROM genero. DELETE FROM actores_por_pelicula. INSERT INTO actores_por_pelicula( idpelicula. INSERT INTO actor(nombre. INSERT INTO soporte(nombre. idactor ) VALUES(1. INSERT INTO actores_por_pelicula( idpelicula. imdb) VALUES('Harrison'. idsoporte. INSERT INTO pelicula(titulo. idsoporte. 'Scott'. 'Digital Versatile Disc'). INSERT INTO genero(nombre. descripcion) VALUES('A'. 'Ciencia Ficción'). INSERT INTO director(nombre. 1). descripcion) VALUES('DVD'. INSERT INTO genero(nombre. iddirector ) VALUES(3. 'Digital Versatile Disc'). Si. Ahora necesita un registro en la tabla de géneros cinematográficos que se ajuste al de esta película. 1). Por una parte. INSERT INTO actores_por_pelicula( idpelicula. son los siguientes: 1. INSERT INTO genero(nombre. 2). 2). INSERT INTO soporte(nombre. descripcion) VALUES('CF'. 2. porque han de cumplirse las reglas de integridad referencial. 'Ciencia Ficción'). puesto que ya tendrá almacenado el valor necesario. 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. inserta otras películas que estén grabadas en el mismo formato. "Blade-Runner" es de ciencia ficción. Con valores en esas dos tablas sí es posible realizar inserciones en la de películas. descripcion) VALUES('DVD'. 1). USE videoteca. Los pasos necesarios para insertar la película "Blade Runner" en la base de datos. 1).) VALUES(2. INSERT INTO directores_por_pelicula( idpelicula. iddirector ) VALUES(2. 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. idactor ) VALUES(3. Inserte el soporte en que se encuentra la película. como si fuese la primera que se inserta. INSERT INTO directores_por_pelicula( idpelicula. y también géneros en la tabla de géneros cinematográficos. iddirector ) VALUES(1. ha de tener soportes válidos en la tabla de soportes de grabación. no tendrá que insertar un nuevo registro en esta tabla. posteriormente. INSERT INTO directores_por_pelicula( idpelicula. . La primera inserción de un valor en una columna de ese tipo toma el valor 1. 5. Adelántese e inserte ya el actor de la película. mucho más complejo que el utilizado en el diseño original de una sola tabla. INSERT INTO directores_por_pelicula( idpelicula. Y es en ese momento en el que se insertan las películas y se asocian con actores y directores. Las inserciones del resto de películas se han realizado siguiendo estos mismos pasos. El último paso previo a la inserción de la película será la inserción de su director en la tabla de directores. luego todos los géneros. Not a: Este proceso. 1. INSERT INTO actor(nombre. 7. 8. Igualmente. puede insertar la película utilizando 1 como referencia al formato de grabación y 1 como referencia al género cinematográfico.sql podrá comprobar que en primer lugar se borran todos los registros de todas las tablas de la base de datos. imdb) VALUES('Harrison'. INSERT INTO director(nombre.3. asocie el director a la película. idsoporte. 1). apellidos. iddirector ) VALUES(1. a continuación los actores y por último los directores. asocie a la película su actor. INSERT INTO pelicula( titulo. 'Ford'. imdb) VALUES('Ridley'. Por lo tanto. 4. cada uno de los elementos que insertados tiene el identificador 1 en su tabla correspondiente. 1).Insertar valores iniciales. 'nm0000631'). 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. 'nm0000148'). Como la base de datos está recién creada. Si examina el código del archivo 02 . Tras ello se insertan todos los soportes en los que están las películas que tenemos. apellidos. idgenero ) VALUES('Blade Runner'. Como verá en capítulos sucesivos. aunque también una desventaja: la inserción de una película requiere de comprobaciones e inserciones adicionales por su parte. 'Scott'. INSERT INTO actores_por_pelicula( idpelicula. esto no supone ningún problema: . idactor ) VALUES(1. Siguiendo el mismo razonamiento. aunque también podría insertar en este momento la película. tiene múltiples ventajas. Recuerde que los identificadores de cada uno de los registros insertados hasta ahora son de incremento automático. 1). INSERT INTO actor(nombre. 'Eastwood'. INSERT INTO actor(nombre. idgenero) . 'nm0000709'). con los mismos registros ordenados de la misma forma. INSERT INTO actor(nombre. 'Trumbull'. apellidos.sql. 'nm0000707'). INSERT INTO director(nombre. 'Boxleitner'. 'nm0781029'). imdb) VALUES('Matthew'. imdb) VALUES('Bruce'. descripcion) VALUES('C'. 'nm0000310'). que la utilizada en este libro. Ahora que dispone de la misma base de datos. INSERT INTO actor(nombre. INSERT INTO actor(nombre. Ejecute las instrucciones de ese archivo para introducir muchos más valores en la bases de datos de películas. 'Zemekis'. apellidos. 'Dern'. apellidos. imdb) VALUES('Jean'. apellidos. 'Young'. Lo usará en el resto del capítulo. ' Hauer'.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. INSERT INTO director(nombre. imdb) VALUES('Rutger'. INSERT INTO genero(nombre. apellidos. imdb) VALUES('Bruce'. 'Seberg'. apellidos. 'nm0001511'). INSERT INTO pelicula(titulo. Su contenido es el siguiente: USE videoteca. 'nm0000190'). 'Marvin'. INSERT INTO actor(nombre. 'nm0874320'). imdb) VALUES('Douglas'. apellidos. 'nm0000142'). 'McConaughey'.Resto de inserciones. Existe un tercer archivo en el apartado de ejemplos de este capítulo que le será de utilidad. apellidos. INSERT INTO soporte(nombre. apellidos. imdb) VALUES('Lee'. descripcion) VALUES('LD'. con los mismos identificadores. idsoporte. imdb) VALUES('Sean'. comienza el trabajo. 'nm0001136'). INSERT INTO actor(nombre. 'Laser Disc'). apellidos. 'Comedia'). 'nm0000442'). imdb) VALUES('Clint'. Se llama 03 . imdb) VALUES('Robert'. INSERT INTO actor(nombre. claro. Obviamente. . Puede utilizar una consulta de selección de SQL para comprobar el funcionamiento de estos operadores. Operadores aritméticos En las cuentas sobre papel. dígame. -. respectivamente.2. se pueden realizar entre un valor numérico y el valor de una columna de un determinado registro. algo que puede ser de mucha utilidad.2. Igual que se pueden realizar estas operaciones entre dos valores numéricos en una consulta de selección. Si recuerda. Durante los siguientes apartados aprenderá a manejar algunos de los operadores que MySQL proporciona. el resultado varía dependiendo del operador que tenga entre los valores. Escriba la siguiente: SELECT 2 + 2. Ya ha utilizado operadores en SQL con anterioridad. multiplicación y división se representan utilizando los operadores aritméticos +. las operaciones de suma. * y /. en el ejemplo dedicado a las transacciones. Y de los valores. 1). 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. MySQL permite utilizar esos operadores dentro de las consultas. ¿verdad? En líneas generales. no hará falta base de datos alguna. resta. Operadores Desde que aprendió a sumar utiliza operadores: el símbolo de la suma (+) es un operador. ¿cuántas son dos más dos? Figura 6. señor maestro Ésta no era difícil. La consulta podría ser ésta: USE videoteca.VALUES('Naves misteriosas'. como lo son el de la resta y el de la multiplicación. así funcionan todos los operadores aritméticos: un valor. Dos más dos son cuatro. 1. Y mirando a la figura 6. Con SQL no es diferente. un operador y otro valor dan como resultado un tercer valor. sumaba y restaba cantidades a los saldos de dos personas para realizar una transferencia de capital. Si la tabla de películas almacenase el año en el que se estrenaron. como ya sabrá a estas alturas. DROP TABLE IF EXISTS operadores. Y esta sencillez también es aparente en otro aspecto. SELECT YEAR(CURDATE()) . Ya vio cómo crearla: DROP DATABASE IF EXISTS pruebas. 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. la siguiente instrucción calcula el tiempo pasado desde el estreno de todas las películas de la base de datos: USE videoteca. ¿Qué ocurre en estos casos. CREATE DATABASE pruebas. otro TINYINT UNSIGNED ).SELECT YEAR(CURDATE()) . con una sola instrucción en SQL obtendrá los mismos resultados. inserte un registro: . 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. aunque esto lo va a ver con otro ejemplo. Vuelva a utilizar la base de datos de pruebas. Cree una tabla con dos columnas con las siguientes instrucciones: USE pruebas.estreno FROM pelicula WHERE id = 12. 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. Siguiendo con el ejemplo anterior. CREATE TABLE operadores( uno TINYINT UNSIGNED. las consultas de selección pueden devolver más de un valor. La consulta anterior se realiza sobre un determinado valor de un registro pero. Ahora. realizando la operación sobre todos y cada uno de ellos. Sin embargo. Donde 12 es el identificador de la película en cuestión y YEAR(CURDATE()) devuelve el año actual. Si tiene algunas nociones de programación.estreno FROM pelicula. Uno diría que se obtendrán dos registros. . Se trata de algo similar a lo que pasaría si intentase multiplicar dos valores enteros muy grandes. La razón. INSERT INTO operadores VALUES(3. Obviamente.3 cuál ha sido el resultado real. el valor máximo es 255). que es de tipo TINYINT sin signo. Operadores de comparación Estos operadores permiten comparar dos valores. Pero. Fuera de rango Y es que se ha salido de rango: ha insertado en una columna. el resultado es 10. 7).USE pruebas. SELECT uno + otro FROM operadores. Figura 6. 500). valores superiores al máximo que puede almacenar una columna de este tipo (recuerde. Fíjese en que el resultado cambia si en lugar de multiplicar por 2 (entero) lo hace por 2. El resultado de sumar los valores almacenados en las dos columnas de esta tabla se consigue así: USE pruebas. el primero con el valor 10. tome el mayor número entero que se puede almacenar en MySQL y multiplíquelo por 2: SELECT 18446744073709551615 * 2. INSERT INTO operadores VALUES(300. El resultado de dicha comparación puede ser TRUE (verdadero). Por ejemplo. de nuevo. El resultado de la comparación será NULL si uno de los valores comparados es NULL . mire en la figura 6. cuyo resultado estuviese por encima del máximo permitido por esa operación.0.3. que ha intentado almacenar en una columna un valor mayor que el que cabe en ella.0 (coma flotante): SELECT 18446744073709551615 * 2. FALSE (falso) o NULL . y el segundo con el valor 800. resultado de la suma de las columnas de los primeros valores insertados. ¿cuál será el resultado de esta misma consulta cuando inserte esta nueva pareja de valores? USE pruebas. El resultado: ese mismo número menos uno. Pues hay una sorpresa. Cualquiera diría que el resultado de esta consulta debería ser TRUE (cierto) en ambos casos. ahora NULL sí es igual a NULL Las comparaciones se pueden hacer entre cualquier tipo de valores. NULL <=> NULL. NULL no es igual a NULL De ahí la existencia del operador "a prueba de NULL".4. Tanto es así. Pruebe el operador de igualdad comparando dos parejas de valores: SELECT 7 = 7. MySQL proporciona operadores para comprobar si dos valores son iguales (=) o diferentes (<>). Vea: SELECT 7 <=> 7. Figura 6.Not a: MySQL utiliza un cero como FALSE y un uno como TRUE. y las variantes mayor o igual (>=) y menor o igual (<=). Por ejemplo. 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. Téngalo presente al obtener los resultados de las consultas. Bueno.5. La realidad que muestra la figura 6. NULL = NULL. si uno es mayor (>) o menor (<) que otro. que hasta existe un operador de igualdad "a prueba de NULL": es el <=>. Éstos son los operadores más utilizados cuando se comienza a trabajar con MySQL. o si está dentro de un rango. existen operadores para comprobar si un determinado valor pertenece a un conjunto de valores. como puede verse en la figura 6. Figura 6. Las constantes TRUE. cualquier comparación de un valor con NULL tendrá como resultado NULL . t rue. para localizar en la base de datos de actores todos aquellos cuyo apellido .4 es otra: mientras que 7 sí es igual a 7. Fíjese en los quebraderos de cabeza que puede dar NULL . El comparador de igualdad se puede utilizar para localizar aquellas cadenas iguales a una dada. Por ejemplo. FALSE y false están a su disposición. por ejemplo.5. cadenas de texto. El resultado de esta consulta sí es cierto en ambos casos. Antes buscaba todos los actores cuyo apellido fuese Crow. por ejemplo: USE videoteca. en . SELECT * FROM actor WHERE apellidos LIKE 'Crow%'. SELECT * FROM actor WHERE apellidos = 'Crow'. Resulta que está buscando un determinado actor con ese apellido. Utilice la siguiente consulta: USE videoteca. se ha utilizado el carácter del tanto por ciento a continuación de la cadena de comparación. ¿que no? Ah... pero ahora quiere que la consulta devuelva todos los actores con Crow como comienzo de su apellido. El resultado: todos los actores con ese apellido. Esta consulta sólo devuelve aquellos registros cuyo apellido sea Crow más un carácter al final. para esos casos existe un operador especial para cadenas. LIKE . es que su apellido es Crowe. el famoso protagonista de "Gladiador".fuese Crow. Podría utilizar esta consulta: USE videoteca. no Crow. utilizando algunos caracteres especiales. por ejemplo Russell. SELECT * FROM actor WHERE apellidos LIKE 'Crow_'. pero no recuerda su nombre. claro. Ambos caracteres (% y _) se conocen como comodines. puede utilizar el carácter del guión bajo para buscar concordancias con un solo carácter. Si lo desea. Ese carácter concordará con cuantos caracteres aparezcan tras Crow en los apellidos de la tabla de actores. se obtendrá un resultado. Bueno. aunque el apellido concuerde exactamente. Operadores lógicos Están basados en las premisas de la lógica booleana. El operador LIKE permite realizar comparaciones con cadenas parciales. Como ve. 7 puede ver el resultado. ya sabe que no siempre se obtiene el resultado esperado.la que las operaciones básicas son NOT . Dependerá de si MySQL efectúa antes la suma o la multiplicación. 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. Sin embargo. (2 + 2) * 5. Uso de paréntesis . OR y XOR.6 se está investigando el funcionamiento del operador AND. Nada hay nada más sencillo que saber cómo funcionan estos operadores. MySQL no realiza las operaciones según las va encontrando: existe una prioridad. ¿Cómo funciona AND? Ah. es posible modificar esa prioridad siempre que lo desee. con sólo utilizar paréntesis. En la figura 6. Figura 6.6. en la figura 6. Por ejemplo. Cambiando la precedencia Se entiende por precedencia el orden en el que MySQL efectúa las operaciones de una determinada consulta. aunque no es evidente si el resultado de 2 + 2 * 5 será 12 o 20. Y precisamente éstos son los nombres de los operadores. Las pruebas con NOT deben hacerse de forma distinta. AND. Figura 6. Es sencillo saber el resultado de la operación 2 + 2.7. por ejemplo. Puede comprobar que el resultado es 12. Las multiplicaciones o divisiones se evalúan antes que las sumas o las restas. Puede comprobarlo ejecutando la siguiente consulta: SELECT 2 + 2 * 5. no se olvide de hacer estas mismas pruebas con el valor NULL . ya que se trata del operador de negación y actúa sobre un único valor. Aquellas operaciones rodeadas por paréntesis se realizan antes. Sin embargo. Simplificando. el borrado de bases de datos sigue la sintaxis: DROP DATABASE [IF EXISTS] nombre. las que más útiles le serán durante su trabajo. Tanto la base de datos como la carpeta y los archivos que conforman la ubicación en disco de la misma serán eliminados. En ese caso. Advert encia: Tenga mucha precaución antes de ejecutar una instrucción de borrado de una base de datos. Creación Las sintaxis de la sentencia de creación de base de datos es muy sencilla: CREATE DATABASE [IF NOT EXISTS] nombre. Borrado Tan sencilla como la creación. pero no hemos visto la sintaxis exacta de la instrucción de creación de bases de datos. una instrucción SELECT debe seguir la siguiente sintaxis: SELECT lista de columnas [FROM lista de tablas] [WHERE lista de condiciones] . se producirá un error del que MySQL avisará. 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. Donde nombre es el nombre que quiera darle a la base de datos. MySQL sólo ejecutará el borrado en caso de que la base de datos exista. El resultado: si existe una base de datos con ese nombre. incluya IF NOT EXISTS. no se continúa con la instrucción de creación de bases de datos actual. MySQL avisará de ello. veremos las consultas más frecuentemente utilizadas. de manera que vamos a simplificar su definición. Si intenta crear una base de datos cuyo nombre ya esté asignado a otra base de datos. Si la base de datos no existe. Si no desea que dicho error se produzca.Manipulación de bases de datos Durante los capítulos anteriores (incluso en éste) hemos creado y eliminado bases de datos. aunque puede evitar el mensaje si utiliza IF EXISTS. SELECT * FROM actor.Insert ar valores iniciales. las tablas sobre las que se realizará la selección. utilizando operadores de comparación: un valor debe ser mayor que otro. pueden ser operaciones de algún tipo. 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.sql y 03 . puede indicar una serie de condiciones que quiera que cumplan los campos de los registros sobre los que realiza la consulta. ¿qué actores están dados de alta en la base de datos? Seguro que sabe cómo obtener ese listado: USE videoteca. 02 . La lista de tablas determinará qué columnas podrá mostrar en la primera sección de la consulta. Por último.8.[ORDER BY campos por los que ordenar] La lista de columnas que quiera obtener siempre debe estar presente aunque. podrá determinar la ordenación del resultado por una o más columnas. o igual a otro. Trabajaremos con la base de datos de películas que construimos al empezar el capítulo. no es necesario que sean nombres de columnas de tablas. una cadena debe parecerse a otra. Listado de actores . A continuación veremos algunos ejemplos de las consultas que más útiles pueden serle en su quehacer diario. Es necesario que haya ejecutado las instrucciones mostradas al principio de este capítulo.sql. Estas instrucciones están también en los archivos 01 . Not a: Para los ejemplos necesitaremos trabajar con la misma base de datos. como vio con los ejemplos de los operadores. Figura 6. es decir. Listados de una tabla En primer lugar. El resultado debería ser similar al que se puede ver en la figura 6. En tercer lugar. etcétera.8.Crear la base de dat os.Rest o de inserciones.sql que se encuentran en la Web de esta guía. SELECT id. el nombre y los apellidos: USE videoteca. ' '. por ejemplo. Puede ver en la figura 6. el identificador. CONCAT(nombre. ' '. Figura 6.9. Figura 6. SELECT id. Para asignar un nombre a esa columna ha de indicarlo tras su definición en la instrucción de selección: USE videoteca. Aunque también puede concatenar nombre y apellidos en un solo campo: USE videoteca. apellidos) AS nombre FROM actor. ahora la columna de la concatenación se llama nombre. SELECT id.10.10 cómo cambia el resultado.El asterisco permite seleccionar todos los campos de las tablas afectadas por las consultas. ' '. Podría indicar qué campos quiere obtener como. apellidos) AS nombre FROM actor .9. SELECT id. apellidos FROM actor. CONCAT(nombre. Esta última consulta tiene un problema "estético": observe el encabezado de la columna que muestra la concatenación en la figura 6. Cambio del nombre de un resultado Un posible cambio en esta consulta sería obtener el resultado ordenado por apellido: USE videoteca. Encabezado de una concatenación Es muy sencillo cambiar este comportamiento. nombre. apellidos) FROM actor. CONCAT(nombre. ¿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.' '. Pero. indicando a continuación los campos por los que se quiere ordenar el resultado. Puede cambiar el nombre de las columnas devueltas: USE videoteca. se ha añadido al final de la consulta la cláusula ORDER BY. Otra consulta que le resultará muy útil es la que permite contar el número de elementos en una determinada tabla. . SELECT COUNT(*) actores FROM actor. El resultado de esta consulta puede verse en la figura 6. Podría cambiar el orden de los resultados utilizando DESC después de cada campo. 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. SELECT COUNT(*) FROM actor. Por ejemplo.apellidos) AS nombre FROM actor ORDER BY 2.actor ORDER BY apellidos. así la ordenación sería descendente (en lugar de ascendente). SELECT id. CONCAT(nombre. Como puede ver. la función CONCAT es el segundo campo escrito tras SELECT .11. La siguiente le dirá el número de actores que tiene en la base de datos: USE videoteca. 11. como se hizo con los campos de las consultas. indicando ahí cómo se relacionan las tablas.12 puede ver un fragmento del modelo relacional de la base de datos. hasta ahora no podemos hacer algo así ya que sólo hemos visto cómo realizar operaciones sobre una sola tabla. necesita saber qué campos desea obtener. El resultado es caótico.Figura 6.. En la figura 6. SELECT * FROM pelicula. 120 registros resultantes: ha obtenido todas las combinaciones posibles de los registros de las tres tablas envueltas en la selección. El primer paso es determinar qué tablas están envueltas en la consulta. el . 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. actor.. con sus actores. Es mejor ir poco a poco. ' '. Para poder organizar la información de estas tres tablas ha de utilizar de forma diferente la parte del FROM de la consulta. apellidos) AS interprete FROM . La parte "complicada" viene a partir del FROM . CONCAT(nombre. En primer lugar. Bastará con el título de la película y la concatenación del nombre y los apellidos del actor. La primera parte de la consulta podría ser algo así: .. actores_por_pelicula.. SELECT titulo. Construya una consulta que devuelva la lista de películas. 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. Para simplificar las consultas se utilizarán seudónimos para los nombres de las tablas. De nada serviría hacer una consulta como ésta: USE videoteca. Figura 6. En el primer caso. Como ve. La parte del FROM de la consulta que intentamos crear es similar a la siguiente: . De esa manera se simplifica enormemente el código. apellidos) AS interprete FROM . que de otra forma debería incluir los nombres completos de las tablas. A continuación puede ver la consulta completa: USE videoteca. La siguiente línea comienza con la palabra reservada JOIN . En primer lugar aparece la primera tabla. la pareja de campos que han de ser iguales.idactor = a. la tabla de actores tendrá el seudónimo a. Tras ella.idpelicula JOIN actor a ON app. no es necesario utilizar AS. FROM pelicula p JOIN actores_por_pelicula app ON p. Por último. 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).. Truco: Fíjese en que utilizamos los seudónimos de las tablas inmediatamente. la de películas.. en realidad no lo es. Actores y películas. SELECT titulo. La tabla de actores por película une a los actores con las películas guardando parejas de identificadores de películas y actores.12. seleccionados Considere como tabla principal la de películas. el identificador de la película debe ser igual al campo idpelicula de la tabla de actores por película. A continuación de su nombre se indica su seudónimo. a la que llamaremos p en la consulta... CONCAT(nombre.dedicado a películas y actores. A esta tabla la llamaremos app.id . Está claro que debemos utilizar los identificadores de actores y películas para enlazar las tablas entre sí. Aunque parezca algo enrevesado.id = app. La palabra reservada ON se utiliza para especificar qué campos se utilizarán como enlace entre los resultados. ' '. nombre.apellidos) interprete. a.apellidos) director FROM pelicula p JOIN actores_por_pelicula app . ' '. La figura 6.idactor = a. SELECT titulo. ' '. Parece correcto. Para ello necesitamos incluir más campos en la selección. pero no lo es.13 muestra el resultado de esta consulta de selección sobre varias tablas. Comencemos viendo los nombres de los campos: .. apellidos) AS interprete. SELECT p. separando ambos con un punto.pelicula p JOIN actores_por_pelicula app ON p.nombre. Actores y películas. usando el seudónimo de la misma como prefijo del nombre de columna..titulo. más tablas en la parte del FROM y más relaciones entre campos. ' '. Solucionar este error es bien simple: sólo necesitamos indicar también la tabla a la que pertenecen los campos. CONCAT(nombre. muy diferente al obtenido con el primer intento. Figura 6.. CONCAT(a. La siguiente es la consulta que buscamos: USE videoteca. CONCAT(d.idpelicula JOIN actor a ON app. MySQL no será capaz de determinar a qué tabla pertenece cada campo y le informará de un error. ' '. CONCAT(nombre. apellidos) AS director . Existe un problema en esta selección: los nombres de los campos de la tabla de actores y de directores son los mismos. seleccionados Vamos a incluir en esta consulta el director de la película.id.id = app. Si intenta hacer una consulta de esta forma.13. d. sin JOIN .. a.idactor ORDER BY a.apellidos. La siguiente consulta devuelve dos columnas: el nombre del actor en una de ellas.id = app. mirando el resultado de la figura 6.id = app.nombre) actor. no parece demasiado de fiar. SELECT CONCAT(a.iddirector = d.14.idactor = a. Películas. sólo de dos.ON p.nombre. El resultado de esta consulta puede verse en la figura 6.id. Una de ellas. pero si el resultado de la consulta fuesen miles de registros lo tendríamos mucho más complicado.14. el número de películas en las que ha participado en la otra: USE videoteca. mostrado en la figura 6. ¿El señor Ford. El resultado. para mostrar información conjunta. la que acabamos de ver. COUNT(app. '. '. Otra aplicación interesante sería calcular el número de películas en las que aparece un determinado actor.idpelicula JOIN actor a ON app. . Figura 6. protagonista de tres películas en nuestra base de datos? Que sepamos. a.id JOIN directores_por_pelicula dpp ON p.idpelicula JOIN director d ON dpp.15. Podríamos saberlo de un vistazo.apellidos.idpelicula) peliculas FROM actor a JOIN actores_por_pelicula app ON a.14.id = dpp. actores y directores Las consultas que involucran datos de muchas tablas se pueden utilizar de varias formas. nombre) actor. Todos los actores y sus películas .id ORDER BY a. En este caso particular. '.16. a.idactor GROUP BY a.16 la información que buscaba. a.nombre.id = app. quiere ver las películas de cada actor. o para un determinado actor.Figura 6. COUNT(app. así que tendría que agrupar por idactor . SELECT CONCAT(a. Esto es otra cosa: ahora puede ver en la figura 6. o para una determinada película. 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.15. Figura 6.idpelicula) peliculas FROM actor a JOIN actores_por_pelicula app ON a. así: USE videoteca. pero esa cuenta puede realizarse de muchas formas: contando todos los registros que aparecen en la tabla.apellidos. '.apellidos. le está diciendo a MySQL que quiere que cuente las veces que aparece idpelicula en la tabla actores_por_pelicula. . '. pero no aparecen como resultado de esta consulta.nombre) actor. el orden de aparición de las tablas: .17.17.idpelicula) peliculas FROM actor a LEFT JOIN actores_por_pelicula app ON a. FROM actores_por_pelicula app LEFT JOIN actor a ON app. 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.id = app. La razón: esos actores sin película no tienen ningún registro en la tabla actores_por_pelicula.. Al usar LEFT JOIN se obtienen todos los registros de la tabla de actores (que está a la izquierda de LEFT JOIN ). El resultado de esta consulta puede verse en la figura 6. a. aunque no exista correspondencia en la tabla de la derecha.id . '.id ORDER BY a... a.Sin embargo. COUNT(app. ¿y si quiere que aparezcan también los actores sin película en este listado? Podría utilizar esta otra consulta: USE videoteca. de manera que la consulta anterior no los incluye en el resultado. Figura 6..idactor GROUP BY a. SELECT CONCAT(a.apellidos. Pero. ¿verdad? Como sabe.apellidos. en la tabla de actores hay más de dos registros.idactor = a.nombre. . Efectivamente. FROM actores_por_pelicula app RIGHT JOIN actor a ON app.. Ahora.17. ¿no? ¿No devuelve nada? Pruebe a buscar sólo por el nombre.. Es el caso de Rutger Hauer y Sean Young. pero obtenga todos los campos.idactor = a. en caso contrario.. no sólo el identificador. 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. Aquí hay algo raro.. SELECT id FROM pelicula WHERE titulo = 'Blade Runner'. Volverá a obtener lo que vio en la figura 6. SELECT id FROM actor WHERE nombre = 'Rutger' AND apellidos = 'Hauer'. presentes en "Blade Runner". ¿verdad? Fíjese en la figura 6..16 porque ahora la tabla de la izquierda no contiene más que esos dos actores. Primero necesita saber el identificador de la película "Blade Runner": USE videoteca. Pero es sencillo volver a obtener el resultado de la figura 6. use RIGHT JOIN. utilice RIGHT JOIN en lugar de LEFT JOIN : . Esta consulta le. fíjese en la separación que hay entre . pero aún no se les ha asociado a ella.18. Ahora sí. Inserte los registros necesarios para que esa asociación exista.El resultado variará.id . Su identificador debería ser el 1. los identificadores de los dos intérpretes: USE videoteca.. Figura 6.18. Algunos de estos actores están dados de alta porque participan en una de las películas. que muestra el resultado de la consulta.. use LEFT JOIN. Ahora sí. ¿No le parece que hay más separación entre Hauer y la línea correspondiente? Quizá haya un espacio antes del nombre. utilizando los operadores que vimos anteriormente.] [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. su identificador es el 9. Inténtelo con esta consulta: USE videoteca...Rutger y la línea de la izquierda. tabla . Actualizaciones Las actualizaciones de datos se rigen por la siguiente sintaxis: UPDATE tabla [. . ¿verdad? Not a: En breve verá cómo modificar este registro para solucionar el problema. Fíjese en que se ha dejado un espacio entre la comilla simple y Hauer. SELECT id FROM actor WHERE nombre = 'Sean' AND apellidos = 'Young'. El identificador de este actor es el 8. Se trata de comparaciones entre valores.. a continuación los valores que se tienen que asignar a los campos que interesa modificar.. SELECT id FROM actor WHERE nombre = 'Rutger' AND apellidos = ' Hauer'. ¿Y el de Sean Young? USE videoteca. Ejecute la consulta. Fíjese en cómo se han utilizado condiciones en la parte del WHERE de la consulta en las consultas anteriores. A continuación veremos cómo se modifican los valores almacenados en una tabla. El último que necesita.] SET columna = valor [. columna2 = valor2 . y el resultado de aplicarle la función TRIM .nombre = TRIM(d.nombre = TRIM(a.apellidos = TRIM(d.nombre).19. director d SET a. no se ha utilizado la cláusula WHERE . a. utilizando la función TRIM . Es necesario hacer un cambio en un determinado registro de la tabla de actores. 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. que afecte a todos los registros. Recuerde que el apellido de Rutger Hauer tenía un espacio al comienzo. o del nombre? Lo ideal sería poder eliminar esos espacios de todas las columnas donde sea necesario. Puede hacerlo con una consulta de actualización sobre la tabla de actores y directores. El apellido del actor Rutger Hauer ya es correcto. UPDATE actor a. Estas condiciones son similares a las utilizadas en las consultas de selección. pero . Esta función elimina los espacios que anteceden o preceden a una cadena de texto. Aunque puede que le asalte la duda: ¿existirá algún actor más con un espacio delante del apellido.Por último.apellidos = TRIM(a. En la figura 6.19 puede comparar el aspecto de la cadena con sus espacios antes y después. d.nombre).apellidos). d. Como ve. Esta modificación se puede realizar de la siguiente forma: USE videoteca. es posible utilizar una lista de condiciones que restringirán el conjunto de registros cuyo valor se modificará.apellidos). Ejecute esta consulta: SELECT TRIM(' cadena '). Figura 6. algo que causó problemas en el apartado anterior. lo que significa que se actualizarán todos los registros de ambas tablas. UPDATE actor SET apellidos = 'Hauer' WHERE nombre = 'Rutger'. ..). viendo de paso cómo realizar las asociaciones entre películas. La primera instrucción hace referencia a Rutger Hauer. ' '. CONCAT(nombre. 9).idpelicula JOIN actor a ON app. Inserciones La sintaxis de la instrucción de inserción es la siguiente: INSERT INTO tabla [(columna.titulo = 'Blade Runner'. 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. la segunda a Sean Young. apellidos) AS interprete FROM pelicula p JOIN actores_por_pelicula app ON p. 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". Puede ver el resultado de esta consulta en la figura 6.)] VALUES (expression. Vea el efecto que han tenido estas inserciones: USE videoteca.aún no aparece como intérprete de ninguna película.... INSERT INTO actores_por_pelicula VALUES(1. Podría insertar el primero así: USE videoteca. SELECT titulo. El siguiente apartado está dedicado a las inserciones de datos.. Pero también puede hacer esto otro: USE videoteca.id = app. 8).idactor = a.id WHERE p. INSERT INTO actores_por_pelicula( idpelicula. . idactor ) VALUES(1. y además existe un valor para cada columna.20. Una nueva inserción en la tabla de actores por película solucionará el problema: USE videoteca. Figura 6. También podría construir una consulta que contase el número de actores que tiene cada película. COUNT(app. Not a: Queda como ejercicio para el lector repetir el mismo proceso con los directores. podemos decirle que Douglas Trumbull dirigió "Naves misteriosas". 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.idactor) interpretes FROM pelicula p LEFT JOIN actores_por_pelicula app ON p.21. podrá comprobar que "Naves misteriosas" ya tiene uno. En caso de que encuentre alguna película sin director. Para añadirlo como actor necesitamos conocer el identificador de la película. ¿Existirá algún actor de esa película en la tabla de actores? "Naves misteriosas" fue protagonizada por Bruce Dern. es posible saber si una película tiene más de un actor si su título aparece más de una vez. Hay una película sin actores: Naves misteriosas. INSERT INTO actores_por_pelicula(idpelicula.titulo. idactor) VALUES(4. Varios actores para una película Como ve. "Blade Runner" tiene tres actores.idpelicula GROUP BY p. Pero esta consulta devuelve otra información digna de mención. Como puede comprobar.21.20. Si lo buscamos en la base de datos verá que aparece con el identificador 6.Figura 6. 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. . Si vuelve a repetir la consulta que dice cuántos intérpretes tiene asociados una determinada película. El resultado de esta consulta puede verse en la figura 6.id. ya lo sabíamos. 6). Ya debe tener los conocimientos suficientes para hacerla por sí mismo.id = app. SELECT p. que es el 4. Si no indica ninguna condición se eliminarán todos los registros de la tabla. COUNT(p.id) peliculas FROM soporte s LEFT JOIN pelicula p ON s. SELECT s.Borrados Una de las operaciones más peligrosas es el borrado de registros.idsoporte GROUP BY s. La sintaxis de esta instrucción es la siguiente: DELETE FROM tabla [WHERE condición]. Formatos de grabación Puede averiguarlo con la siguiente consulta: USE videoteca.id = p. Una simple equivocación en la condición de borrado y se perderán datos. Figura 6. El resultado de esta consulta puede verse en la figura 6. La parte del WHERE es similar a la utilizada en consultas de selección y permite restringir los registros que se borrarán.id.23.22 muestra el resultado. SELECT * FROM soporte. Quizá necesite hacer algún borrado en la base de datos.22. o que el lector haya dejado de funcionar y las .23: no existe ninguna película en formato LaserDisc. La figura 6. Compruebe qué formatos de grabación están disponibles: USE videoteca. Películas en cada formato Puede que se haya deshecho de todas sus grabaciones en LaserDisc. ¿Existen películas en todos esos formatos? Figura 6.nombre. LaserDisc! Durante este capítulo hemos visto la sintaxis de las instrucciones de selección. Las opciones y los modificadores son muchos. manteniendo la consistencia de los datos.películas ya no sean útiles. actualización y borrado de registros en tablas. ¡Adiós. en realidad. siempre que la base de datos esté diseñada correctamente. 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. Elimine ese formato de la tabla de soportes de grabación: USE videoteca. pero las herramientas están ahí. También hemos visto cómo crear y borrar bases de datos. Y tan importante como extraer la información es saber guardarla. Sin embargo. . 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. inserción. DELETE FROM soporte WHERE id = 3. 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. La sintaxis real de las instrucciones que este capítulo ha cubierto es más compleja. y el espacio disponible en esta guía es limitado. Quizá unas consultas sean más complicadas que otras. Hemos visto lo más destacado de ambas tecnologías. Estas opciones de configuración también pueden incluirse en las secciones que se refieran a nuestro servidor Web. 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. Durante este capítulo veremos cómo utilizar MySQLi en su vertiente orientada a objetos.7 PHP y MySQL Hasta ahora nos hemos dedicado a adquirir los conocimientos básicos de MySQL y PHP. no por ello se descuidaron otros. Además de éstas. para trabajar con archivos en formato PDF y un largo etcétera. Comenzaremos viendo cómo se realiza una conexión con un servidor de bases de datos. Para terminar el capítulo veremos cómo modificar el archivo de configuración de PHP para influir en el comportamiento predeterminado de MySQLi. inserciones. pero no se trata sólo de aspecto técnicos: acceder a MySQL resulta mucho más sencillo con esta nueva interfaz. nuestro primer paso para trabajar con MySQL. dentro de la configuración de Apache. la nueva forma de acceder MySQL desde PHP que apareció en la versión 5. pero sin llegar a mezclarlas (exceptuando la toma de contacto del capítulo primero. Realmente largo: PHP dispone de extensiones para casi cualquier operación que pueda imaginar. también es posible realizar operaciones de creación de bases de datos y tablas. Es muy importante que sepamos cómo reaccionar ante situaciones no previstas. Ha de prestar especial atención a esta forma de trabajo. para gestionar archivos XML. . Pero incluso en ese capítulo nos limitamos a utilizar la cara funcional de MySQLi. 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. claro). la interfaz de acceso a MySQL fue mejorada. PHP agrupa las funciones dentro de extensiones. Existen extensiones para acceder a MySQL. Not a: No vamos a entrar en los detalles que hacen mejor a esta versión. Utilizando esa conexión realizaremos operaciones de consulta. actualizaciones y borrados sobre bases de datos existentes. puesto que es la que utilizaremos en el resto de capítulos. 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. Si es su caso. Entonces. La "compatibilidad hacia atrás" (backwards compatibility) es un aspecto fundamental en la vida de un lenguaje de programación. se entiende. conectábamos con la base de datos de películas utilizando el siguiente código: <?php . A fin de cuentas. como el puerto o el socket. Todas las operaciones que realicemos desde PHP con MySQL van a seguir los mismos pasos: conexión. 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. no tendrá que desandar el camino: todo lo que sepa de MySQL podrá aprovecharlo en MySQLi. Not a: Aunque. operación y desconexión. PHP son las siglas de PHP: Hypertext Preprocessor. incluyendo las nuevas bajo una denominación diferente. cuál es su clave y cuál es la base de datos con la que va a trabajar. el nombre de la nueva versión es MySQLi. Para que los programas ya existentes fuesen compatibles con las nuevas versiones de PHP era necesario mantener las anteriores funciones de acceso. en la mayoría de las ocasiones bastará con los cuatro parámetros antes enumerados. Puede realizar la conexión en el mismo momento de crear el objeto que utilizará para conectar con la base de datos. opcionalmente.Mientras que el nombre de la versión primigenia es MySQL.1. Durante el proceso de conexión indique dónde está el servidor de bases de datos. La creencia más extendida es que la última "i" latina significa mejorado (improved) aunque no es descabellado pensar que su significado sea otro. Conexión El paso primordial de su relación con MySQL es la conexión. recuerde el ejemplo del primer capítulo. con qué usuario quiere conectar. 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. El ciclo de la vida De la vida en común de PHP y MySQL. Por ejemplo. el usuario root de MySQL.0. exit(). if ($videoteca->errno != 0) { echo('Error en la conexión. 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. Por lo tanto tendrá que sustituir 'clave' por '' (una cadena vacía).. } .$conexion = mysqli_connect( 'localhost'. no tendrá contraseña alguna asignada. el nombre del usuario. 'videoteca' ). 'root'..'). que siempre se asigna al ordenador con el que estamos trabajando. Como parámetros del constructor de la clase hemos pasado el nombre del servidor. pero ahora utilizando la versión orientada a objetos de MySQLi: <?php $videoteca = new mysqli( 'localhost'. que hemos llamado videoteca. 'clave'. 'root'.1. la clave es clave y el nombre de la base de datos es videoteca. Este nombre se corresponde con la IP 127. Volvamos a escribir el código de conexión. el nombre del usuario es root . 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. si instaló XAMPP para seguir el contenido de este libro. El servidor de bases de datos se encuentra en la misma máquina que el servidor de páginas. if ($conexion == FALSE){ echo('Error en la conexión. exit(). Este código muestra cómo conectar con un servidor MySQL utilizando la versión funcional de MySQLi. 'videoteca' ). la . por defecto... 'clave'.0.'). } . no tiene más que utilizar la propiedad errno de la clase. podrá comenzar realizar operaciones con la base de datos. no existir la base de datos o quizá se haya equivocado en el nombre de usuario o en la contraseña. } .. por lo general. devolverá cero. una tienda a través de Internet. El objetivo de utilizar PHP y MySQL de forma conjunta es. Operación Una vez establecida la conexión. Siguiendo con nuestro ejemplo del primer capítulo.clave y el nombre de la base de datos con la que queremos trabajar. mientras que los administradores se encargarán del mantenimiento de la base de datos. Es el primer parámetro de la función mysqli_query(). este fragmento de código era utilizado para obtener la lista de géneros cinematográficos que hay en la base de datos: . 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. En la tienda que acabamos de mencionar. que contiene la información devuelta por la función mysqli_connect() en el primer fragmento de código. que en caso de error devuelve el código asociado al mismo. Pero si no ha ocurrido ningún error. en caso de que no sea cero.'). la creación de aplicaciones Web. Si no se produjo ningún error. informará de que ha ocurrido un error al realizar la conexión. Para controlar esos casos.. El segundo es la consulta que queremos realizar en la base de datos.. La primera de las líneas anteriores utiliza la variable $conexión. 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. Por lo general los usuarios de estas aplicaciones realizarán consultas. Por ejemplo. if ($resultado == FALSE){ echo('Error en la consulta. modificar los ya existentes o eliminar aquellos que estuviesen descatalogados. 'SELECT * FROM genero' ). los clientes buscarían los productos que les interesasen (realizando consultas). $resultado = mysqli_query( $conexion. . Así.. . como se suele decir coloquialmente. $fila[1]. Esta variable es. $fila[2] ). que puede parecer una tontería. Utilizamos printf() para mostrar los datos que acabamos de obtener. el bucle no terminaría nunca y el programa no avanzaría.%s<br/>". Esto. Acaba de ver cómo se ejecuta una consulta y se obtienen los datos utilizando la versión funcional de MySQLi. $resultado contiene la información necesaria para poder recuperar todos los registros devueltos por la consulta. $fila[2] ). . if ($resultado == FALSE){ echo('Error en la consulta. siendo cada uno de sus elementos un campo del registro. } while ($fila = $resultado->fetch_row()){ printf( "(%u) %s . avanzamos automáticamente al siguiente.. una matriz. quedando. con la que se obtiene el mismo resultado: . $fila[1]. $fila[0]. $resultado = $videoteca->query( 'SELECT * FROM genero' ). } . while($fila = mysqli_fetch_row($resultado)){ printf( "(%u) %s . Al obtener un elemento de la lista de registros devueltos. Puede recuperar esos registros utilizando el siguiente código: . El siguiente fragmento de código muestra el equivalente utilizando la versión orientada a objetos. en realidad nos evita muchos problemas.. Suponga que escribe el mismo bucle anterior.%s<br/>".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. Si olvidase avanzar al siguiente registro. pero el avance automático no se realiza.. existe una ventaja que PHP tiene sobre algunos de ellos. $fila[0]. "colgado".'). a su vez. Esta forma de trabajo es similar en otros lenguajes de programación con acceso a bases de datos... Sin embargo. Cada llamada a mysqli_fetch_row() devuelve un registro que se almacena en la variable $fila. cerrarlas. Una conexión no cerrada estará consumiendo recursos. mysqli_close($conexion). Es curioso que. y pasado un tiempo. utilizando la versión . en la versión orientada a objetos trabajamos directamente con el resultado de la consulta. Veamos la instrucción que permite obtener uno por uno todos los registros. Sin embargo.. Estamos trabajando con una función.. Pero mientras pasa ese tiempo. en muchas ocasiones. ?> Mientras que la primera línea elimina de memoria el resultado de la consulta a la base de datos. lo ha adivinado: en este caso esa variable no es otra cosa que un objeto. Desconexión No por ser la última es la menos importante.). llamamos a una función que recibe como parámetro el resultado de realizar la consulta. la segunda cierra la conexión con MySQL. mysqli_free_result($resultado). El buen funcionamiento de sus aplicaciones depende de que sea civilizado en el empleo de los recursos a su disposición. que no están realizando alguna tarea. MySQL no podrá responder más peticiones. Una vez alcanzado ese techo. pero hasta un límite. la variable $resultado. El servidor de bases de datos es lo suficientemente inteligente para detectar aquellas conexiones ociosas. Y. algo tan sencillo de hacer utilizando la versión funcional de MySQLi como el código que puede verse a continuación: . El servidor de bases de datos puede responder simultáneamente a varios clientes. } . 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... El mismo objetivo puede obtenerse con las siguientes líneas. los recursos seguirán malgastándose. 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. Para terminar este ciclo de operaciones hemos de cerrar la conexión con la base de datos. efectivamente. 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. $resultado->close().orientada a objetos de MySQLi: .%s<br/>". 'root'. $fila[0]. Como puede comprobar es idéntico al que se obtiene con la versión funcional de MySQLi.'). 'videoteca' ). ?> Acabamos de recorrer el ejemplo del primer capítulo. viendo cómo se obtendría el mismo resultado utilizando la versión orientada a objetos de MySQLi. exit().1 muestra el resultado de ejecutar esta página.. } while ($fila = $resultado->fetch_row()){ printf( "(%u) %s . if ($resultado == FALSE){ echo('Error en la consulta. ?> Aunque dista mucho de ser un programa profesional. Veámoslo completo: <?php $videoteca = new mysqli( 'localhost'. $fila[1]. } $resultado = $videoteca->query( 'SELECT * FROM genero' ). cumple su función con dignidad. . $videoteca->close(). mostrando lo que le pedimos: la lista de géneros cinematográficos que hay en nuestra base de datos. que pudo ver en la figura 1.').19. $videoteca->close(). $fila[2] ). 'clave'. } $resultado->close(). La figura 7. if ($videoteca->errno != 0) { echo('Error en la conexión.. 2. La lista de géneros. aunque entonces con la versión funcional de MySQLi. Conjuntos de registros Ni la conexión ni la desconexión con MySQL guardan ningún misterio. las operaciones que hemos tenido que realizar para realizar una consulta a nuestra base de datos de películas son siempre las mismas.Figura 7. La figura 7. $resultado = $videoteca->query( 'SELECT * FROM genero' .. consulta y desconexión) vamos a profundizar en algunos aspectos interesantes de esta biblioteca de funciones.2 describe las operaciones que tendrá que realizar para lograr su objetivo. Recordemos cómo recuperamos los registros devueltos por una consulta: .. Figura 7. el resultado de realizar una consulta a la base de datos sí. El ciclo de la vida y los géneros Not a: Como recordará. Durante este capítulo utilizaremos la versión orientada a objetos.1. en el primer capítulo ya realizamos estas operaciones. Ahora que sabe cómo utilizar MySQLi para realizar las operaciones básicas (conexión. Sin embargo. con objetos Resumiendo. siendo el resultado el que puede verse en la figura 7. Tras realizar una consulta con éxito. ¿qué resultado obtendrá si la consulta no tiene éxito? Para comprobarlo..'SELECT * FROM genero' ).. printf("%s". el tipo de la variable $resultado será boolean. if ($resultado == FALSE){ echo('Error en la consulta. puede ser interesante mostrar el número de registros encontrados. generos).. En nuestro ejemplo de la lista de géneros.. se les da el nombre de mixed.. lo que permitirá localizar el problema. Pero. ha obtenido una referencia a un objeto. Si la consulta tiene éxito. $fila[2] ). La variable $resultado es un ejemplar de la clase mysqli_result . En este caso. . $fila[0]. que pueden adoptar varios tipos en función de las circunstancias. Es decir.%s<br/>". El resultado será la cadena object . Si intenta realizar la consulta ocurrirá un error. puede acceder a sus métodos y atributos. realice la consulta llamando al método query() del ejemplar de la clase la clase mysqli que esté utilizando. Entonces. Not a: A estas variables. } while ($fila = $resultado->fetch_row()){ printf( "(%u) %s . gettype($resultado)). 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.3: .. En primer lugar. podrá acceder a los resultados gracias a la variable $resultado.. Sólo tendría que incluir el siguiente fragmento de código. Puede comprobar el tipo de esta variable utilizando la función gettype(): .'). cambie en la consulta el nombre de la tabla (genero). $fila[1]. Veamos algunas de las propiedades más interesantes: num_rows: Contiene el número de registros que la consulta ha devuelto. ese ejemplar se llama $videoteca. } . . con sus métodos y sus atributos.. 1. Nombre original de la columna. indica el número de decimales empleados.1 muestra los diferentes elementos en los que esta información está repartida.. Puede ser útil cuando no quiera realizar una iteración por todo el conjunto de resultados devuelto por la consulta que haya realizado. data_seek: Permite que nos desplacemos a un registro en concreto dentro de los resultados. Figura 7. La tabla 7.<br/><br/>". puede utilizar un bucle for controlado por una variable cuyo valor irá incrementando. El resultado lo devuelve en una matriz. $resultado->num_rows ). Si el campo es entero. en caso de que se utilizasen alias en la consulta. Número de registros encontrados field_count: Devuelve el número de columnas que tiene cada uno de los registros devueltos. 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. Tabla 7. Atributos del campo. 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.3. . en caso de que se utilizasen alias en la consulta. Ese mismo . 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. por ejemplo. expresados de forma numérica. Por ejemplo si sólo quiere mostrar los resultados en páginas de un número de elementos cada una. Nombre original de la tabla. siendo cada uno un elemento de la matriz devuelta. Tipo del campo.. Valor predeterminado. Este valor puede resultar interesante para controlar el ancho de una tabla en la que mostrar el resultado de la consulta. Tamaño del campo.printf( "Registros encontrados: %s. Nombre de la tabla. fetch_field() devuelve información sobre los campos del registro actual. como hacía fetch_row(). $fila = $resultado->fetch_row(). Si obtiene cuatro registros. para obtener el primero debe pasarle a la función un cero. $fila[1]. $fila[2] ). CONSULTA. 'Thriller' ). sus métodos y sus atributos en la documentación de PHP.%s<br/>". que nos permitiría insertar un nuevo género en la base de datos.. $resultado = $videoteca->query($sConsulta). el siguiente fragmento de código. el método query() puede utilizarse para ejecutar consultas. $sConsulta = <<<CONSULTA INSERT INTO genero( nombre. pero no tienen que ser sólo consultas de selección: también puede tratarse de consultas de borrado. Otras consultas Como ya hemos comentado. Sustituya el bucle while por: . El siguiente fragmento de código ilustra el concepto..'). y así sucesivamente. Not a: Si lo desea puede encontrar más información acerca de la clase mysqli_result . . para obtener el segundo un uno.. if ($resultado == FALSE){ echo('Error en la consulta. pero no un conjunto de registros. . Como ejemplo. $resultado->data_seek(0). recuperando sólo el primer elemento devuelto por la consulta. 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. printf( "(%u) %s . una vez establecida la conexión: .. descripcion )VALUES( 'TH'. $fila[0]..valor será el que pasaremos a data_seek() para obtener uno por uno los registros que nos interesen.. inserción o actualización. ")VALUES(". } $sTitulo = "Ocean's Eleven".. 1. $resultado = $videoteca->query( $sConsulta ). Y esta cadena no es otra que una consulta."'. 'clave'. idgenero".". el objetivo de esta conversión es hacer válida una cadena que no lo es. "escapar" se entiende en algunos contextos como "realizar una conversión". En la jerga de los informáticos. ")". como las comillas simples. 'videoteca' ). en la carga de la página que muestra los géneros podrá ver el que acabamos de añadir. . $sConsulta = "INSERT INTO pelicula(".". if($resultado == FALSE){ echo('Error en la consulta. Como resultado. En nuestro caso. } .'). 'usuario'. 4".')..".echo('Error en la consulta.". idsoporte. " " " titulo. Si la inserción no tuvo éxito podrá saberlo gracias al valor devuelto por el método query(). La siguiente inserción no sería válida: <?php $videoteca = new mysqli( 'localhost'. exit(). Existen ciertos caracteres que no pueden incluirse en una consulta. if (mysqli_connect_errno() != 0) { echo('Error en la conexión.'). Consultas escapadas No se trata de aquellas consultas que se fugaron (perdón por el chiste fácil y malo). " " " '".$sTitulo. Valores de configuración Aunque existen varias formas de consultar los valores de configuración de MySQLi vigentes en nuestro sistema. El método real_escape_string() hará los cambios necesarios en el título para que la consulta de inserción pueda realizarse.. Pero luego encuentra otro carácter de apertura de cadena. y MySQL lo entiende como el cierre de una cadena. Tampoco vamos a verlas todas ahora..'). . . Inserte la siguiente línea antes de crear la variable $sConsulta: . El problema se debe. Configuración Al comienzo del libro hablamos sobre cómo programar usando PHP. no cerrado y se hace un verdadero lío..php Lo que sí trataremos en este apartado son las opciones de configuración de PHP que afectan al funcionamiento de MySQLi. Hay soluciones para todo..net/manual/es/configuration. a que el título tiene una comilla simple. ?> . debido a que son demasiadas y no es éste un manual de referencia.. concretamente en la siguiente dirección: http://php. simplemente. la más inmediata consiste en crear una página PHP con el siguiente contenido: <?php phpinfo().. Y el primer paso es consultar los valores que estas opciones tienen en nuestro sistema. echo($videoteca->error).echo('Error en la consulta. } $videoteca->close(). $sTitulo = $videoteca->real_escape_string( $sTitulo ). Existe numerosa documentación al respecto en la Web de PHP. aunque no entramos en detalles tales como las posibles opciones de configuración existentes para este lenguaje. La segunda sección es la que nos interesa. Compare el logotipo de PHP que aparece al principio de la información devuelta por la función. ya que muestra los parámetros de configuración aplicables en este momento. este parámetro no tiene ningún valor asociado.default_host: Le permite indicar cuál será el servidor MySQL al que se conecte por defecto.4. 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. En este caso el valor predeterminado es . Not a: API son las siglas de interfaz de programación de aplicaciones (Application Programming Interface).4.4. si al establecer la conexión no ha indicado ninguno.Una vez la tenga. april's fools). Configuración de MySQLi Truco: El comportamiento de la función phpinfo() no es siempre el mismo. busque dentro de esa página el texto mysqli. por lo que cualquier intento de conexión sin indicar servidor será fallido. 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. mysqli.default_port: Especifica el número de puerto predeterminado al que realizar las solicitudes de conexión. No cabe duda: tienen sentido del humor. es decir. Utilizando las herramientas de su cliente Web. 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. y que puede cambiar si lo considera oportuno. Como puede ver en la figura 7. El cliente le mostrará la sección de parámetros de configuración de la biblioteca de funciones MySQLi. del propio MySQLi. La primera de ellas muestra detalles sobre el funcionamiento de MySQL. Son los siguientes: mysqli. puede acceder a ella con cualquier cliente Web. este parámetro no contiene ningún valor. Está obligado a especificar el nombre del usuario porque. Por defecto no contiene ningún valor. La ubicación de este archivo varía dependiendo del sistema operativo que utilice y de cómo haya instalado PHP. Si utiliza Linux o Mac OS X. Pero. Sin este parámetro de configuración tendría que incluir el número de puerto al realizar la conexión. En cambio. mysqli.4 habrá podido comprobar que existen dos columnas asociadas a valores: Local Value y Mast er Value (valores locales y maestros. la reconexión con el servidor MySQL en caso de que ésta se perdiese. mientras que la segunda a los aplicables a todas las páginas. es decir. Si no se indica ningún valor (como es el caso) PHP utilizará los valores internos de los que dispone. sin límite. mysqli. de forma automática.3306. En breve veremos cómo hacer esta distinción. La primera se refiere a los valores aplicables a la página que estamos viendo ahora. mysqli. tras el nombre de la base de datos. o de la potencia y recursos de su servidor. la que sus intentos de conexión utilizarán si no indica ninguna al intentar conectar. es más que probable que pueda encontrar este archivo en algún lugar de la carpeta /etc. ¿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.reconnect: Por defecto desactivado.default_socket: Permite indicar el socket que se utilizará durante la comunicación entre el servidor de bases de datos y el cliente. mysqli. por defecto. 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.ini.default_pw: Clave de acceso predeterminada. Not a: En la figura 7. puede que quiera indicar un límite. Dependiendo de la naturaleza de las aplicaciones que esté desarrollando.default_user: Nombre del usuario predeterminado si al intentar conectar no indica ninguno. mysqli. Por defecto. . de forma que su servidor no se colapse ante un aluvión de peticiones. respectivamente). Es la existencia de este parámetro el que permite realizar la conexión sin indicar valor alguno para el puerto. el puerto estándar de MySQL. Permite que PHP intente. es una buena idea mantenerlo en la carpeta del sistema (C:\WINNT puede ser uno de los nombres que tome).max_links: Número máximo de conexiones con MySQL permitidas desde sus aplicaciones PHP. en Windows. aunque también puede estar en la carpeta en la que instaló PHP. ini se encontrará en la carpeta /apache/bin/php. El resultado debería ser similar al que se puede ver en la figura 7. si utilizó XAMPP para instalar Apache. el archivo php.ini. sólo tiene que reiniciar el servidor de páginas Web.ini dentro de la carpeta en la que XAMPP se instaló. indicando su nombre entre corchetes. sea localhost . . Figura 7. 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. En la figura 7. PHP y MySQL. que ahora mismo no tiene ninguno asignado. Apache.ini Haga una prueba sencilla: cambie el servidor predeterminado al que conectar de manera que el valor de esta variable.Independientemente del sistema operativo. ábralo con su editor de textos favoritos y busque la sección MySQLi.5. Sección MySQLi en php.6. Cuando haya realizado el cambio y guardado el archivo. Esté donde esté el archivo.5 realizamos dicha búsqueda con el bloc de notas. recuperando la lista de géneros cinematográficos y mostrándolos perfectamente. que debería ser el nombre del servidor. En cada una de esas páginas debe realizar una conexión con el servidor MySQL para . Como puede ver. ahora es una cadena vacía. exit(). no indicando el servidor MySQL al que quiere conectar.. Sin embargo.. 'videoteca' ). 'root'. el primer parámetro que pasamos al constructor de la clase. Anteriormente esa cadena era localhost . Servidor MySQL predeterminado ¿Cómo puede aprovecharse de este cambio en sus programas? Por ejemplo.6. 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( ''. 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. 'clave'.'). if ($conexion == FALSE){ echo('Error en la conexión. } .Figura 7. Podría utilizar archivos de inclusión. sin utilizar ni nombre de usuario ni contraseña. una sola vez? De esa forma. Obviamente. Uno de ellos. en cada una de ellas. de los que hablamos en el capítulo cuatro. este método también tiene sus inconvenientes. Not a: Existen otras técnicas para almacenar en un único lugar los parámetros de conexión al servidor MySQL. Imagine lo desconcertante que puede ser ver una línea de código que conecta con un servidor MySQL que no se especifica. indicando el servidor. el nombre de usuario y la contraseña. antes de sus cambios. 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. Tiene entonces el nombre de usuario y su contraseña en todos los archivos que conectan con la base de datos. esta información se encuentra en un archivo de configuración del sistema. Y por último. como programador. algo que puede ayudarle a mejorar la seguridad de su aplicación Web. se aplican a todas las aplicaciones Web que se ejecuten bajo su servidor PHP. existe una forma de modificar las opciones de configuración de MySQLi para sus aplicaciones. estos valores son globales. conservando las opciones globales del archivo php. ya que esa página mostraría a todo el mundo la forma de conectar con el servidor de bases de datos. Esta ventaja supone comodidad para usted que. aunque no demasiado importante. 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. debe asegurarse de que la aplicación funciona correctamente bajo cualquier circunstancia. es decir. Pero existe otra ventaja. Además.posteriormente obtener los registros que quiere mostrar en la página. También ha de asegurarse que en ninguna página de la Web se muestre la información devuelta por phpinfo(). ¿No sería mejor tenerlos escritos en un solo sitio. relacionada esta vez con la seguridad. Digamos que tiene cinco páginas PHP y. podría hacerlo sabiendo que ese cambio en la configuración de MySQL sólo implica un cambio en su aplicación Web. Inconvenientes No todo iban a ser ventajas.ini tal y como estaban. El acceso por parte de desaprensivos a estos archivos es más complicado. Sin embargo. . si por cualquier motivo tuviese que cambiar el nombre de usuario o su contraseña. o sus propios archivos INI. el nombre de usuario y la clave. no todas las aplicaciones utilizarán los mismos parámetros de conexión. lo encontrará en la carpeta /apache/conf/.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. Es justo esto lo que queremos cambiar. 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. Vamos a editar el archivo de configuración de Apache. Mientras que la primera no tiene valor definido para el servidor MySQL predeterminado. Su nombre es httpd. si utiliza XAMPP. como en la figura 7. llamada pruebas.conf y.deny Allow from all php_admin_value mysqli. si revisa las opciones de configuración de MySQLi que dichas páginas muestran. puede separar sus aplicaciones PHP. Usando estas directivas.ini. . pero cada una con sus particularidades. todas basadas en las opciones de configuración contenidas en el archivo php. dentro de la carpeta en la que XAMPP se instaló. la segunda muestra el valor localhost. Vamos a crear una nueva carpeta. 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. PHP y Apache pueden trabajar de forma conjunta.7.default_host localhost </Directory> Guarde los cambios. Si abre dos clientes Web para observar la información devuelta por cada página podrá comprobar que son idénticas. comprobará que han dejado de contener la misma información. en la ruta en la que Apache esté instalado. Es posible incluir ciertas directivas en los archivos de configuración de Apache que serán pasadas a PHP. Debería ser algo así en Windows: <Directory "C:/xampp/htdocs"> La ruta será diferente en Linux y Mac OS X. 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. Ahora. Una vez tenga el archivo abierto con su editor preferido. dentro de htdocs. Y no sólo puede establecer estas diferentes configuraciones para cada carpeta que le interese. 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.'). también puede diferenciar entre servidores virtuales.Figura 7. en este caso sólo aplicable a la carpeta pruebas. por ejemplo. ''. . sepa que puede utilizar archivos . ''. Con php_admin_value le indica a Apache que lo que viene a continuación es una variable de configuración de PHP.7. exit().ht access para modificar las opciones de Apache de las carpetas Web a las que tenga acceso. if ($conexion == FALSE){ echo('Error en la conexión. ''). Diferentes valores locales y globales La línea importante es la siguiente: php_admin_value mysqli. 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. Para más información consulte la documentación de Apache y póngase en contacto con el administrador de sus sistemas. Si no tiene acceso a ellos o no puede solicitar estos cambios al administrador del sistema.. pudiendo realizar las conexiones con las bases de datos así: <?php $conexion = new mysqli(''. } . Ahora sí que podría establecer un nombre de usuario y una clave diferente por cada aplicación.. siempre que las colocase en carpetas diferentes.default_host localhost Puede ignorar las otras opciones de configuración. Y nunca más cierto que en este caso: no por ser el último es el menos importante de los motivos. . ha aprendido lo básico de PHP.8. Control de errores Sin embargo. 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. La gestión de errores que hemos realizado hasta ahora no ha servido de nada. El primero salta a la vista: el aspecto que tiene la lista de categorías no es demasiado vistoso. Pero. MySQL. ¿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. Esto es así por tres motivos. Podrá ver el desastre que muestra la figura 7. Aunque se trata de una página dinámica. Lo solucionaremos en el capítulo dedicado a Smarty. además de a usarlos de forma conjunta. A partir de aquí comienza la parte divertida. Cuando el servidor de bases de datos esté detenido. Hasta ahora. Figura 7. no permite que realicemos cambios. intente cargar de nuevo la página que muestra la lista de categorías. es cierto que en el código que acabamos de escribir hemos introducido algunos controles para los errores: al conectar y al realizar consultas.Anteriormente hicimos un comentario no del todo favorable acerca de la profesionalidad de las páginas que hemos programado durante este capítulo. El último motivo que vamos a mencionar es la gestión de errores. se trata de un proceso muy importante que con más frecuencia de la deseada se descuida. es necesario llevarlos a cabo en la base de datos para poder mostrarlos en la página. El segundo motivo es la falta de interactividad. 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.8. cuyo aspecto cambia a medida que cambia el contenido de la base de datos con la que está trabajando. Sí. entendiéndola como la posibilidad de modificar desde nuestro propio cliente Web la forma en la que nos presentan los datos que solicitamos. La figura 8. los clientes pueden responder con los valores que hayan introducido en los campos de los formularios. posteriormente. Uno de los principales atractivos de la programación con PHP y MySQL está en la interactividad. 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. junto con la petición de una nueva página. y éste se la devolvía? En el caso de los formularios se trata de algo parecido: desde una página.8 Formularios No sólo de mostrar información vive la Web. Si con lo visto hasta este capítulo ha logrado mostrar el contenido de una base de datos en una página Web. 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. e incluso los propios datos. Durante este capítulo verá cómo crear sus propios formularios. Cómo funcionan los formularios Hablar de formularios es hablar de intercambio de información. una serie de valores. como cadenas de texto donde se esperaba un número. Lograremos este objetivo utilizando scripts en el lado del cliente. en el primer capítulo. Verá también cómo orientar a los usuarios para que no envíen valores incorrectos.1 ilustra el proceso. el usuario puede enviar. pueden enviarse de vuelta al servidor. ¿Recuerda cómo. a partir de ahora será capaz de modificarlo. describimos la forma en la que un cliente Web solicitaba información a un servidor. . Al igual que el servidor envía las páginas a los clientes. 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. Los cuadros de texto nos permiten introducir el nombre del nuevo género y su descripción. Veamos cómo crear utilizarlos.Figura 8. 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. desde el formulario (sea lo que sea) enviamos de forma simultánea la petición de una nueva página y algunos valores. Formulario para nuevos géneros Not a: El aspecto de la página de la figura 8. Para los formularios disponemos de muchos otros elementos. En esta página hemos creado un formulario con tres elementos: dos cuadros de texto y un botón. En la figura 8. Figura 8. que los procesa y devuelve un resultado.2. además de los cuadros de texto y los botones.2 es muy rudimentario. El servidor Web pasa esos valores a la página. Al hacer clic en el botón Guardar (el tercer elemento del formulario). Intercambio entre páginas Es decir. Formularios HTML Los formularios son como cualquier otro elemento que .2 se puede apreciar el aspecto de un hipotético formulario para dar de alta nuevos géneros cinematográficos.1. 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. los datos que el cliente introduzca en los dos cuadros de texto se enviarán a la página de destino. pero lo mejoraremos notablemente en el capítulo dedicado a las plantillas. aunque sólo algunos de ellos enviarán información al servidor. puesto que se utilizará para dar de alta un nuevo género cinematográfico en nuestra base de datos. Cada método tiene sus ventajas e inconvenientes. No es sencillo de comprender sin ver un ejemplo. <form name="frm_alta_genero" action="genero. La información del formulario se enviará a la página genero. Es un nombre que describe adecuadamente la función del formulario. Los más importantes de estos aparecen en la tabla 8. Por ahora. Página a la que se enviará la información del formulario. se abra en una nueva ventana con sólo añadir t arget ="_blank" como atributo de la declaración del formulario. El elemento de apertura de un formulario dispone de algunos atributos con los que se puede modificar su comportamiento. la indicada en act ion. Por último. Tabla 8.. la siguiente sería la declaración del comienzo de un formulario: . Atributos de un formulario At rib ut o name action method target D escrip ció n Nombre con el que puede referirse al formulario.pueda definir en una página HTML.1. 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.php" method="get"> .. . El nombre de este formulario es frm_alta_genero. Truco: Puede provocar que la página de destino del formulario. Creación de formularios Un formulario HTML debe comenzar con la etiqueta <form> y terminar con la etiqueta </form>. Se consideran elementos del formulario todos los que haya entre estas dos etiquetas. mientras que el método POST los incluye en los encabezados HTTP. Su declaración sigue las mismas reglas que la creación de tablas o la inserción de imágenes..1. Forma en la que dicha información es enviada al servidor. baste decir que el método GET envía los datos en el mismo URL de llamada a la página de destino. el método determina cómo se enviarán los datos entre las dos páginas.php. algo que haremos en breve.. que también comentaremos en este capítulo. Es decir. Nos permite indicar en qué ventana se abrirá la página indicada en el atributo action del formulario. Cuadros de texto El más sencillo de todos los elementos de un formulario.3 puede verlos todos juntos.3.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. value: El valor que toma el elemento.Elementos de un formulario Hasta ahora ha visto dos de los elementos que pueden componer un formulario: cuadros de texto y botones. y con diferencia. así como sus atributos. en la figura 8. Not a: Aunque existen otros elementos que puede incluir en un formulario HTML. con los que vea en este capítulo podrá satisfacer la mayoría de las necesidades de sus aplicaciones Web. Estos elementos se crean de igual forma que cualquier otro elemento dentro de una página HTML: utilizando etiquetas. Pero también dispone de otros. botones de opción. botón. Un cuadro de texto puede tener los siguientes atributos: . Para crear uno dentro de sus formularios ha de crear un elemento input y asignar el valor text al atributo type. es el cuadro de texto. Antes de hablar de ellos. listas e incluso elementos ocultos. Veamos ahora uno por uno todos los elementos que podemos incluir en un formulario. menús desplegables. Figura 8. como casillas de verificación. Elementos de un formulario Seguro que los elementos mostrados en la figura 8. Todos ellos comparten el nombre de la etiqueta. La única diferencia está en que ahora es usted el que crea la aplicación y no otras personas. name: El nombre por el que tendrá que referirse a los elementos del formulario para recuperar su valor. etcétera). <input> y algunos atributos: type: Su valor determina de qué elemento se trata (cuadro de texto. lo que modificaría su aspecto. <input name="casilla" .. para evitar que miradas indiscretas sepan lo que está escribiendo. ésta aparecerá marcada.. su ancho. marcada por defecto: . TRUE o FALSE. Cuadro de texto El código HTML para generar este cuadro de texto es el siguiente: . En la figura 8. Figura 8. el siguiente código HTML sirve para generar una casilla de verificación.. Un cuadro de texto podría tener un tamaño de 16 caracteres. Las casillas de verificación también pueden tener asociado un valor. con un máximo de 32 caracteres. Si checked está presente en los atributos de la casilla de verificación.4...size: Determina el ancho del cuadro de texto. pero es el atributo checked el que determina si la casilla está marcada o no. por ejemplo. maxlength: Limita el número máximo de caracteres que se pueden incluir en el cuadro de texto. Así. <input name="texto" type="password" value="" size="16" maxlength="32"> . pero el número máximo de caracteres podría ser 32. cada carácter que introduzca en el cuadro de texto aparecerá como un asterisco. independientemente de si ha asignado un valor a dicho atributo.4 puede ver un cuadro de texto de 16 caracteres de ancho. type: Si este atributo está presente y su valor es password. y cuyo atributo type tiene el valor password.. Son ideales para representar valores de tipo booleano. Casillas de verificación Una casilla de verificación puede tener dos estados: marcada o no marcada. utilizando el atributo name.5. Si está presente.. <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" . no lo estará. Si selecciona uno de los botones de opción cancelará la selección de otro.name="casilla" type="checkbox" value="checkbox" checked="true"> . La figura 8. los botones de opción suelen ir por grupos y permiten escoger entre valores con más de una opción. activo o no). el estado de un botón de opción depende de la existencia o no del atributo checked. independientemente de su valor. Si no está presente.5: . Para lograr este comportamiento ha de llamar igual a todos los botones de opción. Botones de opción En contraste con las casillas de verificación. Botones de opción Y a continuación.5 muestra cómo puede utilizar estos elementos en un formulario. el botón de opción estará marcado.. Igual que las casillas de verificación. el código de los botones de opción dentro del formulario que puede verse en la figura 8. Figura 8.. que permiten seleccionar entre dos valores (cierto o falso.. Géneros disponibles Para crear una lista desplegable necesita dos elementos. El valor de este atributo es indiferente. Así. dispondrá del atributo selected. la seleccionada. Por otra parte.. <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> . Figura 8. Menús desplegables Podríamos establecer parecidos entre los botones de opción y los menús desplegables. ya que ambos ofrecen una serie de opciones de las que sólo puede seleccionar una.. El texto que aparecerá en cada una de las opciones del menú debe . el menú de la figura 8..6 se crea con el siguiente código: . El primero de ellos es el menú.6.. el segundo las opciones.type="radio" value="perl"> Perl<br/> <input name="lenguaje" type="radio" value="mande"> ¿Páginas dinámicas? ¿Mande?<br/> .. cada una de las opciones necesita un valor y una de ellas. el menú contiene las opciones.. La declaración del menú sólo precisa de un nombre.6 es una buena muestra de ello. La figura 8. 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">'); En segundo lugar. ?> Guarde en una página llamada formulario. echo('<th>Nombre</th><th>Valor</th>'). ya que le permitirá comprobar que una página pasa a la otra los valores que usted esperaba.12.12. La página le informará de que no se le ha pasado ningún valor. } echo('</table>'). sin llamarla desde ninguna otra. la página de destino será esta nueva. echo('</tr>'). esta página le será de mucha ayuda. Ahora ya puede emprender la tarea que era el objetivo desde que comenzó este capítulo: crear una página PHP . echo('</tr>'). intente cargar la página formulario. cambie el método de envío de la página HTML.php directamente. La primera. al hacer clic en el botón Guardar .$valor). salvo que ahora los valores pasados no aparecerán en el URL. Así. Recargue la página en su cliente Web. cambie el valor del atributo action por formulario. asigne valores a los cuadros de texto y haga clic en Guardar . de get a post . Podrá ver algo parecido a lo que muestra la figura 8. aquella cuyo código se podía ver al principio del apartado 8. introduzca valores en los cuadros de texto y haga clic en el botón.echo('<tr>'). Todos los valores pasados Pruebe dos cosas más. printf( "<td>%s</td><td>%s</td>". Seguirá viendo lo mismo que en la figura 8. Abra la página HTML en un cliente Web. en cualquiera de las páginas que hemos creado en este capítulo como.3. A medida que vaya creando sus propios formularios. Figura 8. por ejemplo. $nombre.php. foreach($pParametros as $nombre => $valor){ echo('<tr>').12.php el código que acaba de ver. Ahora. . ya sea el método GET o POST .que le permita dar de alta nuevos géneros. con la misma intención que en el apartado 8. }elseif(count($_POST) != 0){ $pParametros = $_POST. El primer paso consiste en crear la referencia a la matriz de valores pasados que corresponda. El resultado es que tendremos todos los parámetros pasados a la página en $pParametros: <?php $pParametros = FALSE. Vamos a utilizar una sola página.php. a la que llamaremos genero. introduciremos las instrucciones PHP al comienzo de ella. Aunque ya hemos visto 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> Como sólo vamos a utilizar una página. 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. Sólo nos queda ponerlo todo junto.4. no está de más recordarlo. if(count($_GET) != 0){ $pParametros = $_GET. . Debemos llevar a cabo tres tareas: 1. $sDescripcion = $pParametros['descripcion']. Primero.. creamos la consulta: . el siguiente paso era comprobar si $pParametros era FALSE . El primer paso es bien simple: .. sólo realizaremos alguna acción si se pasó algún parámetro a la página: . Lo que nos interesa ahora es ver qué código escribimos dentro del bloque if. Informar del éxito o fracaso de la operación. if(($sNombre == '') or ($sDescripcion == '')){ $sMensaje = 'El nombre y la descripción '.. Obtener los valores que necesitamos y comprobar que son válidos. 3...php.. así que vamos a ello.'.. $sNombre = $pParametros['nombre']... }else{ .. Es en la parte del else en la que realizaremos la inserción en la base de datos. pero ahora nos interesa hacer justo lo contrario. Ya disponemos de todos los valores necesarios. } . } . 2. En la página formulario. 'ser cadenas vacías. 'del nuevo género no pueden '.. Por lo tanto. puesto que ese será el que realizará la inserción en la base de datos.. Realizar la inserción en la base de datos.} .. echo($sMensaje). if($pParametros != FALSE){ . if($resultado == FALSE){ echo('Error en la consulta. exit(). '$sDescripcion' ). 'videoteca'). $videoteca = new mysqli( ''. $sConsulta = <<<CONSULTA INSERT INTO genero( nombre. ejecutar la consulta y cerrar la conexión: .. ''.6 del capítulo 7. Nada más sencillo. cómo incluir el nombre del servidor MySQL. Not a: Si le parece raro cómo realizamos la conexión con la base de datos. el del usuario y su clave en los archivos de configuración de Apache.. quizá necesite echar un vistazo al apartado 7. descripcion )VALUES( '$sNombre'.. HTML incluido: <?php $pParametros = FALSE. } $resultado = $videoteca->query($sConsulta). . } echo('Nuevo género añadido. echo($videoteca->error).. ''. Ahora sólo tenemos que establecer la conexión con la base de datos. CONSULTA.').. ... $videoteca->close(). exit(). ¿verdad? A continuación puede ver el código completo de está página..<hr/>'. }elseif(count($_POST) != 0){ . if ($videoteca == FALSE){ echo('Error en la conexión.'). En concreto.. if(count($_GET) != 0){ $pParametros = $_GET. en la que se comentan algunos aspectos de la configuración de las aplicaciones PHP. 'ser cadenas vacías. descripcion )VALUES( '$sNombre'. } $resultado = $videoteca->query($sConsulta). 'del nuevo género no pueden '.').'. ''. $videoteca->close(). if($resultado == FALSE){ echo('Error en la consulta. } } ?> . exit(). if ($videoteca == FALSE){ echo('Error en la conexión.'). CONSULTA. echo($videoteca->error). }else{ $sConsulta = <<<CONSULTA INSERT INTO genero( nombre.$pParametros = $_POST. '$sDescripcion' ). } echo('Nuevo género añadido. echo($sMensaje). 'videoteca').<hr/>'). } if($pParametros != FALSE){ $sNombre = $pParametros['nombre']. exit(). if(($sNombre == '') or ($sDescripcion == '')){ $sMensaje = 'El nombre y la descripción '. $videoteca = new mysqli( ''. $sDescripcion = $pParametros['descripcion']. ''. Pruebe a cargarla ahora. que los valores que se van a enviar cumplen los criterios que necesita. Puede mejorar el funcionamiento de sus formularios añadiendo un nivel más de control. verificando en el lado del cliente. . además de en el lado del servidor. podrá comprobar que dispone de un género más: el que acaba de añadir gracias a nuestro formulario.13 muestra el aspecto de esta página tras añadir una nueva categoría a la base de datos. 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. En el URL se pueden ver los parámetros que se han pasado a la página. Figura 8.<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. frm_genero. frm. lo normal es guardarlo en archivos independientes de la propia página.value. al que asignamos el nombre frm_genero. ajustándose a los parámetros que usted decida. var sNombre = frm. Ahora mismo sólo nos interesan los formularios y los valores de sus elementos. var sDescripcion = frm. return(false). return(false). antes de enviar nada al servidor. El elemento que comienza la jerarquía es document y representa a la página Web. if(sNombre == ''){ alert('Falta el nombre. que se han introducido tanto un nombre como una descripción para el género. Como puede que a alguien le parezca poco.value.nombre. De esta forma evitaremos más de una llamada errónea a la página. ¿qué nos interesa hacer con la página para dar de alta nuevos géneros? Comprobar.Control en el lado del cliente Este libro es como una torre de Babel: hasta ahora hablamos HTML. la variable frm es una referencia a document. Aunque puede incluir el código JavaScript en el mismo archivo PHP o HTML.descripcion. así que podremos acceder a él . En concreto. } Antes de ver cómo insertar este código en su página. Dentro de él está nuestro formulario. el formulario que contiene los valores que queremos comprobar. } return(true).select(). PHP y SQL.').nombre. La siguiente función realiza la tarea que nos interesa: function comprobar_valores(){ var frm = document. En primer lugar. JavaScript es un lenguaje que permite comprobar que los valores que los clientes intentan enviar en los formularios son correctos. Su sintaxis es muy similar a la de PHP (¿o deberíamos decir lo contrario?).frm_genero.').select().descripcion. } if(sDescripcion == ''){ alert('Falta la descripción. veamos qué hace. vamos a por otro lenguaje más: JavaScript. Desde JavaScript dispone de una jerarquía de clases que le permite acceder a cualquier elemento o atributo de la página. frm. 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"> .mediante document. y frm. Posteriormente comprobamos que no estén vacías. De igual forma.. accedemos a los elementos del formulario por su nombre: frm.. De ambos cuadros de texto nos interesa su valor.. Si una de ellas está vacía.js"> <!---> </script> . ¿cómo asociamos este código a la página PHP? Con una sencilla línea: . comparando su valor con una cadena vacía.descripcion el cuadro de texto para la descripción. Ahora..nombre será el cuadro de texto para el nombre.php debe quedar así: <html> <head> <title>Nuevo género</title> <script language="javascript" src="genero. <script language="javascript" src="genero. mostramos un mensaje al respecto y seleccionamos el cuadro de texto que corresponda. Lo guardamos en sendas variables. Esta instrucción debe ir antes del fin la etiqueta <head>.frm_genero. de forma que la parte HTML de la página genero. En ese caso. que se lanza cada vez que se hace clic sobre dicho botón. La figura 8. Cada vez que se haga clic.14 muestra lo que ocurriría si intentásemos crear un nuevo género sin descripción asociada. el envío del formulario se cancela. el cliente Web llamará a la función. la función devolverá true. 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. para que cuando se haga clic en dicho botón el cliente Web intente ejecutarla. <input type="submit" value="Guardar" onClick="return comprobar_valores()"> . como la función devuelve false. 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... pero . La existencia del campo es el primer paso. Si todos los valores necesarios han sido introducidos. Para ello utilizamos el evento onClick del botón. El código de la etiqueta del botón sería el siguiente: . Pero si no se cumple algún requisito.14. el formulario se enviará a la página de destino. Sin descripción.com/.</form> </body> </html> Ahora sólo tenemos que asociar la función comprobar_valores() al botón Guardar . un usuario pueda modificar valores de una base de datos. respectivamente. pero no el único.buscamos. Si pide al cliente que introduzca una fecha. La existencia del campo es el primer paso. un valor numérico o una dirección de correo electrónico con el formato correcto. 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. . las tareas más importantes son relegadas a un segundo plano. una lista de registros. Concretando. ¿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. Y. MySQL también proporciona medios para informar sobre los errores que se produzcan y profundizar en las causas de los mismos. en nuestro caso. aunque es cierto. Pero como hemos dicho.9 Gestión de errores Es curioso como. el problema no está en que ocurra un error en una de sus páginas sino en no saber tratarlo adecuadamente. 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. 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. Durante este capítulo verá cómo configurar PHP para que su comportamiento frente a los errores sea el que usted desee. las páginas PHP que hagamos deben devolver información de las bases de datos: por ejemplo. nuestro trabajo está hecho. Las herramientas que proporciona PHP para la gestión de errores son muchas y muy variadas. bajo cualquier circunstancia.1. la página debe comportarse adecuadamente bajo cualquier circunstancia: cuando el servidor de bases de datos no esté funcionando debe avisar de ello. También verá cómo MySQL informa de los errores que ocurren. cuando logramos que un programa se comporte de la forma esperada. . a veces. bueno. no lo es del todo. Un programa sólo puede darse por bueno cuando su comportamiento es el adecuado. De igual forma. a veces. 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. Porque. Y aprenderá a utilizar de forma conjunta la gestión de errores de PHP y MySQL para sacarles el mayor partido. 2 muestra los valores que más nos interesan de la sección PHP Core de la configuración de PHP.1. ni el nombre del usuario ni su contraseña. tal y como nos la muestra la función antes mencionada. 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. En su apartado 7. 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. Vamos a repetir la jugada. Configuración para los errores Como puede ver. Figura 9. La figura 9. Configuración Situémonos de nuevo en el capítulo 7. sólo indicando la base de datos predeterminada. el que se aplica por defecto a todas las zonas de Web. 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(). pero ahora nos vamos a fijar en otros valores. existen tres columnas.Figura 9.2. mientras que la tercera (Master Value) determina el valor global de esa opción. Not a: Recuerde del séptimo capítulo que puede tener una configuración . La primera (Directive) es el nombre de la opción de configuración.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. Not a: La ruta de la carpeta en el fragmento de configuración de Apache. Desactivamos display_errors ¿Qué efecto tendrá este cambio en la página que pudimos ver en la figura 9. Cree una carpeta llamada errores dentro de esa carpeta y.. <Directory "C:/xampp/htdocs/errores"> Options Indexes FollowSymlinks AllowOverride None Order allow. deberá añadir las siguientes líneas al archivo de configuración de Apache: . algo que puede verse en la figura 9. como es obvio. como pretendíamos. Suponga que está trabajando en la ruta predeterminada de Apache. 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. Tras reiniciar el servidor Apache.2 se puede observar que estos mensajes están activos. como ya hicimos en el capítulo 7.3. Figura 9.3.1.1? Si intenta cargarla cuando . display_errors Dependiendo del valor de esta variable..6. En la figura 9.. En concreto. dentro de ella. Veamos el impacto que desactivar esta opción tiene sobre los mensajes de error. como pudo comprobar en la figura 9. Son estos valores los que determinan cómo se comportarán nuestras aplicaciones en caso de que ocurra un error. ponga un archivo PHP que llame a la función phpinfo().5.diferente para algunas de las carpetas del servidor de páginas Web que utilice. Más detalles al respecto en el apartado 7. 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. los errores que se provoquen en nuestras páginas producirán mensajes o no..deny Allow from all php_admin_value display_errors "0" </Directory> . Dependiendo de la ubicación de la página PHP dentro del árbol de directorios del servidor se aplicará una configuración u otra. se corresponde con un sistema Windows. Veamos para qué sirve cada uno de ellos. la carpeta htdocs. '). Pero. exit(). . $fila[1]. $fila[2] ). if ($videoteca->errno != 0){ echo('Error en la conexión. el código de esta página era el siguiente: <?php $videoteca = new mysqli( 'localhost'. esta opción de configuración debe estar activada.4. 'clave'.4.%s<br/>". print_r($resultado->fetch_field()). ¿Cómo es que. Si recuerda. en el que esté probando el funcionamiento de sus páginas. si ha fallado la conexión.MySQL esté detenido podrá ver algo similar a lo que muestra la figura 9. if ($resultado == FALSE){ echo('Error en la consulta. mientras que durante su vida útil debe desactivarla y ser usted quien controle los mensajes de error. $fila[0]. } $resultado->close(). Controlamos los mensajes de error La conclusión: durante el proceso de desarrollo. ¡un momento! Aquí hay algo que no cuadra. 'videoteca' ). el mensaje de error que vemos es "Error en la consulta. Figura 9.'). 'usuario'. } while ($fila = $resultado->fetch_row()){ printf( "(%u) %s . } $resultado = $videoteca->query( 'SELECT * FROM genero' )."? Algo no es del todo correcto. $videoteca->close(). Ahora sí.. Con el servidor MySQL detenido y display_errors activa. } . como demuestra la figura 9. Figura 9. Estos errores no serán visibles a menos que el valor de esta opción de configuración sea On. se produzca algún error. 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. docref_ext y docref_root Como hemos visto. Si prueba a cargar esta página.. Es posible que. ahora que hemos modificado la comprobación de los errores de conexión podrá ver que sí obtiene la información correcta.. if (mysqli_connect_errno()){ echo('Error en la conexión. ?> . Vamos a provocar un error.. la instrucción new mysqli no ha logrado crear un ejemplar de la clase mysqli y. $videoteca->errno no contiene información alguna del código de error. además.?> ¿Por qué no se informa de un error en la conexión? Porque.5.5. al no llegar a realizarse. cree una página con el siguiente código y ábrala: <?php $videoteca = mysqli_connect(). durante el proceso de carga de PHP en memoria. En dicha página aparece. por lo tanto. Lo correcto es utilizar una función para comprobar si hubo errores durante el proceso de conexión: . error en la conexión display_startup_errors No sólo se producen errores al cargar una página. exit().'). 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. . Figura 9. Añadamos dos líneas a la configuración de la carpeta errores en Apache: . el enlace será el que se puede ver en la figura 9. 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.net/manual/es/" .php" php_admin_value docref_root "http://php. Sin embargo. si hace clic sobre ese enlace no encontrará ayuda alguna porque esa página no existe. php_admin_value docref_ext "..6. 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..6.6. En él puede ver que dicho enlace apunta al servidor local..7.. 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. Reinicie el servidor Web y vuelva a cargar la página de la figura 9. Ahora.Y se produce un error como el que muestra la figura 9. Si lo desea. De lo contrario no podrá acceder a esta documentación. error_reporting Quizás una de las más importantes de las opciones de configuración relacionadas con la gestión de errores. error_prepend_string y error_append_string Asocie una cadena de texto a estas opciones de configuración. y en español. No se detiene la ejecución del programa.Figura 9. Contiene un valor numérico que determina el nivel de detalle de los mensajes de error. E_WARNING: Errores no fatales. respectivamente. Deberá modificar la configuración de PHP adecuadamente. puede instalar la documentación en su propio servidor para poder consultarla en cualquier momento. Enlaces a la documentación Si hace clic sobre dicho enlace verá la documentación de la función mysqli_connect(). . 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. A partir de ese momento. Se detiene la ejecución del programa.7. dichas cadenas aparecerán antes y después del mensaje de error. E_PARSE: En nuestro código hay algo que no sigue las reglas sintácticas de PHP. Truco: Para aprovechar al máximo estas opciones de configuración es necesario que disponga de conexión a Internet mientras trabaja. E_RECOVERABLE_ERROR: Error fatal que quizá no dejó en un estado inutilizable al motor de PHP.8. salvo E_STRICT antes de la versión 5.4. E_USER_WARNING: Advertencia generada por el programador mediante el uso de la función trigger_error(). el valor de esta opción de configuración es E_ALL & ~E_NOTICE.8. E_STRICT: Consejos dados por PHP acerca de cómo mejorar el código que escribimos. E_CORE_WARNING: Error no fatal ocurrido durante la carga de PHP en memoria. E_CORE_ERROR: Error fatal ocurrido durante la carga de PHP en memoria.0 de PHP. html_errors Sólo si esta opción de configuración está activa podrá ver los mensajes de error con formato HTML. E_ALL incluye a E_STRICT . con enlaces a la documentación de PHP cuando sea necesario. ignore_repeated_source . E_ALL: Todos los errores. con lo que PHP le ayudará en sus programas todo lo que pueda. E_COMPILE_ERROR: Relacionado con Zend Script Engine.E_NOTICE: Avisos sobre posibles fallos en nuestro código. está fuera del alcance de este libro. 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. Le recomendamos que cambie ese valor por E_ALL & E_STRICT . Figura 9. Consejo: Por defecto. E_COMPILE_WARNING: Relacionado con Zend Script Engine. está fuera del alcance de este libro. A partir de esa versión. E_USER_ERROR: Error generado por el programador mediante el uso de la función trigger_error(). los mensajes de error tendrán el aspecto que puede ver en la figura 9. 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. E_USER_NOTICE: Aviso generado por el programador mediante el uso de la función trigger_error(). Si está desactivada. Si activa esta opción y un mensaje de error se produce de forma consecutiva en varias ocasiones. podrá modificar el valor de error_log. uno de los lenguajes de su clase que proporciona las funciones de gestión de errores más sencillas y útiles. 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. los mensajes de error se guardarán en el log del sistema. veamos qué funciones pone PHP a su disposición para gestionarlos. Existe un valor especial para esta opción de configuración. sin importar si se produjo en la misma página o en otra. No son sólo las que vamos a ver. no se informará de él más que la primera vez. Si en lugar de la ruta de acceso a un archivo indica el valor syslog. posiblemente. 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. nos centraremos en las más importantes. a una dirección de . Funciones PHP es. PHP informará de dicho problema. Si no se indica ningún valor no habrá límites de tamaño. Tras conocer las posibles opciones de configuración relacionadas con la gestión de errores. siempre podrá acceder en sus programas a la información del último error que se produjo a través de la variable $php_errormsg. Esta variable sólo contiene la descripción del error. log_errors y error_log Si log_errors está activo. 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. 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. 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). track_errors Si esta opción de configuración está activa. log_errors_max_len Tamaño máximo de los mensajes que se almacenará en el registro de errores. por último. ¡y por correo electrónico! Volvamos a nuestro ejemplo. Truco: Además de esta información. a un depurador de errores remoto o a un archivo (al final del cual se añade el mensaje). por cientos de razones diferentes. 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. la lista de géneros. y con el asunto describiendo qué es lo que ha pasado. en lugar del código que informa sobre el error en la conexión.com. ¿No sería fantástico que. en caso de que esta página se intentase cargar tras enviar información con un formulario. Suponga también que. "From: Servidor en producción\n" ). usted tendría constancia de ello. exit(). el destino propiamente dicho y. efectivamente. No se engañe: las aplicaciones pueden fallar. información asociada al tipo de destino. no se ha podido establecer una conexión con la base de datos. Se trata de una aplicación Web.". las variables pasadas a la página.correo electrónico. en caso de que sea necesario. Suponga que. sería muy interesante incluir otra en el cuerpo del mensaje como. con el remitente Servidor en producción.. tiene este otro: .'). aquel que le encargó su desarrollo. error_log( "No se pudo conectar con MySQL. "Subject: Error en la videoteca\n". indignado. por ejemplo. . cuando algún fallo ocurriera en las aplicaciones que ha desarrollado. } . el tipo de destino (cualquiera de los cuatro antes mencionados). if (mysqli_connect_errno()){ echo('Error en la conexión. instalada y funcionando en los sistemas de su cliente.. para que sepa de qué servidor le llega el mensaje. Suponga que su aplicación está terminada. "videoteca@example. o cualquier otro detalle que pueda ayudarle a resolver el problema que provocó que se le enviase el mensaje de correo electrónico.com". A veces. decirle que lo que ha programado no sirve para nada. 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. continuamente conectada a Internet.. incluso no es por su culpa.. 1. en este orden: el mensaje de error. Esta función acepta cuatro argumentos. 'del nuevo género no pueden '.. $sMensaje = 'El nombre y la descripción '. . es decir.. echo($sMensaje).. Por ejemplo.'.. 'del nuevo género no pueden '..'. el nivel de detalle con el que se informará de los errores. $sDescripcion = pParametros['descripcion']. del que acabamos de hablar. la página PHP que le permitía dar de alta nuevos géneros cinematográficos. }else{ . mostraba un mensaje: .. 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. .error_reporting() Esta función permite modificar en tiempo de ejecución.. 'ser cadenas vacías. 'ser cadenas vacías. Podríamos cambiar la llamada a la función echo() por una llamada a la función trigger_error(): .. desde el mismo código de una página. if( ($sNombre == '') or ($sDescripcion == '') ){ $sMensaje = 'El nombre y la descripción '. if($pParam != FALSE){ $sNombre = pParametros['nombre']. E_USER_ERROR). Cuando esta página no recibía el nombre del género o su descripción. recuerde el capítulo anterior. Utilizar esta función modifica el parámetro de configuración error_reporting. trigger_error($sMensaje. en este orden. "videoteca@example. como puede ver en la figura 9. Si desea más información al respecto consulte la documentación de PHP.<br/>"). puede solucionarlo ya que existe la posibilidad de que cree su propia rutina de gestión errores.9. printf("<b>Archivo:</b> %s. $linea ){ printf("Ha ocurrido un error. Figura 9. 1. El archivo PHP en el que se produjo el error. $descripcion. La función de gestión de errores sólo tiene que ser capaz de recibir cuatro parámetros que.<br/>".". printf("<b>Descripción:</b> %s. en lugar de un simple mensaje. representan: 1.<br/>". error_log( "Error. 3. printf("<b>Código:</b> %s.<br/>". $archivo). La siguiente es una versión minimalista de una función de gestión de errores: function informar_error( $codigo. viene adornado como un mensaje de error de los que ya conocemos. 2. 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. La línea en la que se produjo el 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. $linea). $codigo). set_error_handler() ¿No le gusta la información que PHP sobre los errores? No se preocupe. $archivo. printf("<b>Línea:</b> $s.El resultado. El código del error.9. 4. .<br/>". La descripción del error. $descripcion).com". Excepciones La gestión de errores que hemos realizado hasta ahora es la más utilizada. 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. Nosotros informamos del error Not a: Por otra parte.10 muestra el aspecto de los mensajes de error utilizando nuestra función. el resultado de utilizar esta función para informar sobre los errores es mucho más pobre. restore_error_handler() Llamando a esta función restauramos la función de gestión de errores que pasemos como parámetro. visualmente hablando.$descripcion.. . restore_error_handler ..10."\n".."Subject: ". La única ventaja que nuestra función aporta sobre la predeterminada de PHP es que. En el ejemplo del apartado anterior se trataría de la variable $gestor_anterior. además de informar sobre el error de forma diferente. podríamos hasta decir que es la . Figura 9. } 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.. 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. utilizar las instrucciones de inclusión que vimos durante el capítulo 4 y hacer la siguiente llamada al comienzo de la página: . La figura 9. $gestor_anterior = set_error_handler("informar_error"). Queda como ejercicio para el lector mejorarla. "From: Servidor en producción\n" ). MySQL y los errores Cada vez que ejecuta una consulta cuya sintaxis no es correcta o sobre unos datos inexistentes. por ejemplo. MySQL Query Browser o MySQLi) le informará sobre dichos errores. '<br/>'. Para controlar las excepciones que pudiesen tener lugar sólo es necesario incluir el código en cuestión en un bloque try: . } . la línea o el archivo en el que tuvo lugar el error.clásica. $e->getMessage() .. El primero paso para utilizar excepciones consiste en localizar aquellos fragmentos de código susceptibles de fallo.. igual que muchos otros lenguajes modernos. un objeto de tipo Exception que contiene toda la información que necesite mostrar para informar sobre el error como..... La principal ventana de utilizar bloques try y catch es que el código resultante está mucho más estructurado. Sin embargo. MySQL proporciona gran cantidad de datos en . 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' ). catch (Exception $e) { echo 'Error: ' . más organizado. por ejemplo... Un buen candidato podría ser el momento de realizar una consulta en una base de datos: . que si no se utilizasen.. La gestión de la posible excepción (es decir. Entre paréntesis.. PHP ofrece la posibilidad de gestionarlos utilizando excepciones.. el código. } .. del error) tiene lugar en el bloque catch definido a continuación del bloque try: . el cliente de MySQL que utilice (como. . try{ $resultado = $videoteca->query( 'SELECT * FROM genero' ). El registro de errores será el que más utilice cuando comience a trabajar con MySQL. Todas las conexiones que se establezcan con MySQL y las posteriores consultas quedan registradas aquí. 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] . examine los archivos de registro. le hará falta incluir información que aparezca en estos archivos. MySQL proporciona gran cantidad de datos en sus archivos de registro (log en inglés). o aquellas que no utilizan índices. El buscador de mensajes en los grupos de noticias http://groups. 2. aunque también puede ser mysql. 3. Existen otros archivos de registro de los que no se hablará porque no le serán útiles por el momento. Puede encontrar más información sobre ellos en la documentación de MySQL. MySQL mantiene registros de su actividad en diferentes archivos: 1. Not a: Si tiene algún problema utilizando MySQL y necesita buscar ayuda sobre el mismo. La ubicación de este archivo variará. además de durante su funcionamiento. El nombre del archivo se compone del nombre del ordenador con la extensión err (linux. Esta ruta dependerá de cómo y dónde haya instalado MySQL. para localizar problemas en caso de que los tenga. Por lo general. También registra las paradas y arranques del servicio. 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.google. dependiendo de si el servidor está instalado en Windows. El registro de errores: Guarda información sobre los errores aparecidos durante el proceso de arranque o de parada de MySQL. Examinar este archivo puede ayudarle a determinar por qué el servidor no se pone en marcha.com/ puede serle útil. dentro de la ruta de instalación de MySQL.err si el nombre del equipo fuese linux).sus archivos de registro (log en inglés). 4. pero ¿y si le interesa saber qué pasó hace unos días? Para esos casos. se tratará de la carpeta data. El registro de consultas: O registro general. El registro lento: Almacena información sobre aquellas consultas que tardan mucho tiempo en completarse. 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.err . Linux o Mac OS X. por ejemplo durante la conexión de algún programa con el servidor de bases de datos. Figura 9. 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. dentro de la carpeta en la que MySQL esté instalado. En cuanto al registro de consultas.11.11 muestra el contenido típico del archivo de registro de errores de un servidor MySQL instalado en Mac OS X. La figura 9. le pasa al servidor el parámetro: --log [= ruta] Este archivo de registro es especialmente útil si conoce la existencia de algún problema. pero no dispone de suficiente información para solucionarlo. 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.12 muestra el resultado de intentar leer directamente el contenido de un archivo de registro binario . Éste se diferencia del resto en que no es posible su examen directo.Fíjese en que la ruta del archivo es opcional.exe. Para que le muestre el contenido de un archivo de registro binario debe pasarle su ruta como argumento. mes y día). El tercer archivo de registro que puede resultarle interesante es el binario. con un editor de texto. A continuación la hora en la que se produjo en mensaje y. 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. puede seleccionar su ubicación si. al contrario que los dos anteriores. el mensaje. por último. que se encuentra en la carpeta bin. La figura 9. en el momento de arrancar. Puede obligar a MySQL a crear nuevos archivos de registro utilizando la siguiente instrucción. que puede quedarse sin espacio en disco. Ya dispone de dos tablas de registro en su servidor MySQL. así que estarán vacías. como puede ver en la figura 9.recién creado. yendo cada uno a una columna de la tabla correspondiente. dentro de la base de datos mysql: general_log y slow_log. su tarea como administrador se verá dificultada: trabajar con archivos demasiado extensos puede ser un problema. Los datos de cada línea del archivo de registro se desgajan. Not a: Le recomendamos que realice esta operación de forma periódica y haga una copia de seguridad de los archivos de registro. Tablas de registro. Se trata de algo muy interesante por varias razones. Por defecto. el tamaño de los archivos de registro puede llegar a ser excesivo. estas tablas no se están utilizando. vacías . Figura 9. archivo más reciente. Además de suponer un posible problema para el mismo servidor.13. como si estuviese ejecutando instrucciones SQL: FLUSH LOGS.13. en lugar de leerlo utilizando mysqlbinlog.12. Archivo de registro binario Si el número de operaciones realizadas en su servidor de bases de datos es muy grande. en lugar de en archivos.exe. Figura 9. Los archivos de registro binario utilizan una extensión compuesta de varios dígitos: mayor número. Archivos de registro en tablas MySQL permite guardar las entradas del registro en tablas. Tras el repaso a los archivos de registro que hicimos en el apartado anterior. 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. por lo que pueda pasar. 14. Así que comencemos comprobando si el registro general está activo: . esta información se puede guardar simultáneamente en archivos y tablas utilizando el parámetro --log-output=FILE. 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.TABLE . Figura 9. Si lo desea. Con el primero (--log-output=FILE ) se utilizarán archivos para el registro. 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. En la figura 9. puede tomar tres valores: FILE . Figura 9. Pero. El registro. o registro general. La figura 9. TABLE o NONE .15.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.La tabla general_log se utiliza para guardar las entradas del registro de consultas. El tercero desactiva la generación de información de registro. recordemos que sólo dos de ellos se ven afectados: el general y lento. no es necesario reiniciar el servidor para empezar a utilizar el registro en tablas. mientras que con el segundo se utilizarán tablas. Ahora bien. ahora en tablas Aunque hayamos configurado MySQL para que guarde el registro en tablas. Antes de nada tenemos que saber dónde guarda MySQL los datos de registro. Como vimos anteriormente. es posible activarlos utilizando la misma técnica que acaba de ver. En la tabla slow_log se guardan las entradas del registro lento. estos registros se activan a través de parámetros de inicio de MySQL. en archivos o en tablas. Para ello ejecute la siguiente consulta: SHOW VARIABLES LIKE 'log_output'. que se pasa como parámetro durante el arranque del servidor (--logoutput ). nos basta con utilizar la siguiente sentencia: SET GLOBAL log_output='TABLE'. Contenido de la tabla de registro Cada registro tiene 6 columnas: event_time: ¿Cuándo tuvo lugar el evento registrado? . Para comprobarlo.16. 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. en la 8 seleccionamos la base de datos que aparece en la fila 9 (mysql) y. en la 10. La figura 9. Utilice la siguiente sentencia para activarlo: SET GLOBAL general_log='ON'.16 muestra el resultado de llevar a cabo estas dos operaciones. Figura 9.17. Si el valor de esta opción de configuración es OFF significará que está desactivado. con el registro en tablas activo y el registro general en funcionamiento.17. Figura 9. SELECT * FROM general_log\G El resultado. Activación del registro general A partir de este momento. precisamente.SHOW VARIABLES LIKE 'general_log'. la tabla general_log comenzará a recibir datos de MySQL. realizamos la consulta de los datos de la tabla en cuestión. muestra. realice la siguiente consulta: USE mysql. argument: Parámetros pasados a la orden. además. ya sabe dónde encontrar la descripción del mismo. 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. Mensaje de error en inglés Para cambiarlo. 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. 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.18 es una buena muestra de ello. Una de las ventajas de mantener los registros en tablas es que podemos guardar información de diferentes servidores en la misma ubicación. por defecto. En el caso de una consulta será la consulta en sí. ¿No le gustaría. Así sólo tendrá que consultar esa tabla. En concreto. o la lista de todas las consultas. command_type: Tipo de orden. La figura 9. Si se produce un error. una consulta (Query) o la selección de una base de datos (Init DB). . la figura 9. por ejemplo. Por ejemplo. poder entender esos mensajes de error. Figura 9.user_host: ¿Quién generó el evento en cuestión? thread_id: Identificador del subproceso. server_id: Identificador del servidor.18. o desde cierto equipo conocida su IP. Configure los servidores a su cargo para que guarden sus registros en las tablas de uno de ellos. filtrando los registros por servidor.19 muestra el aspecto de las propiedades del servicio al incluir dicho parámetro. Al guardar la información de registro en tablas resulta sencillo obtener la lista de operaciones realizadas a lo largo de un día. por citar sólo algunos ejemplos. en español. 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. cada objeto con el que esté trabajando dispondrá de una pareja de propiedades que. Mensaje de error en español Como puede comprobar si compara la figura 9. MySQLi y los errores La gestión de los errores en MySQLi sigue unas pautas muy sencillas. independientemente del idioma en el que se muestren los mensajes de error el código es el mismo (en este caso. . en caso de error.18 con la 9.20. una consulta de selección sin indicar sobre qué base de datos. Para obtener mensajes en español Una vez reinicie el servicio podrá comprobar que los mensajes de error del servidor aparecen en español. no podrá utilizar las propiedades errno y error de la clase. expondrán el código del mismo y su descripción. el 1046). Figura 9. Se trata de errno y error .20.20. Prueba de ello es la figura 9.19. respectivamente. en la que puede ver el resultado de ejecutar la misma consulta con la que obtuvimos el mensaje de error de la figura 9. Como ya sabe. respectivamente. que devuelven el código del error y su descripción.18. En el caso de que el error se produzca al intentar establecer una conexión con un servidor de bases de datos. existe una excepción a esta regla. 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.Figura 9. Para esta eventualidad dispone de otras dos funciones. Si está utilizando la versión orientada a objetos de la misma. mysqli_connect_errno() y mysqli_connect_error(). puesto que no se habrá podido crear. Estas dos funciones necesitan una referencia a la variable con la que se realizó la operación que generó el error. . De cómo utilizar estas funciones poco podemos contar. un gestor de conexión. Por ejemplo. el valor obtenido tras establecer una conexión con una base de datos de MySQL. podrá utilizar las funciones mysqli_errno() y mysqli_error().respectivamente. En caso de que esté trabajando con la versión funcional de esta biblioteca. 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. puesto que ya las hemos utilizado en numerosas ocasiones a lo largo del libro. Sin embargo. 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. PHP. por su sencillez. la nota de PHP sería de las más altas. tras los cambios que hayan realizado. ya sea en la parte del diseño o en la parte de la programación. un servidor de páginas Web.10 Plantillas Si la calidad de un lenguaje de programación tuviese que medirse por la utilidad de las herramientas desarrolladas con él. Smarty podría situarse entre PHP y HTML. Como puede ver en la figura 10. En este proyecto. Por lo general. 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. Así una y otra vez. El verdadero problema viene cuando hemos de hacer un cambio. Las aplicaciones que hemos desarrollado hasta ahora. 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. HTML y JavaScript. Somos nosotros los que tenemos que volver a modificar sus páginas HTML para incluir el código PHP en ellas. un bucle allá. ¿Qué es Smarty? Smarty es una capa más dentro de nuestra particular torre de Babel.1. tiene otra opción mucho más interesante y útil: las plantillas de Smarty. así que siguen trabajando con su diseño. Aunque existen herramientas que le permiten localizar diferencias entre archivos y mezclar sólo aquellas partes que le interesen. Hasta ahora hemos apilado un buen montón de tecnologías: un servidor de bases de datos MySQL. . Suponga que está desarrollando una aplicación para una empresa. los diseñadores no tienen noción alguna sobre PHP. unas variables acá. por lo general. Se trata de algo muy sencillo. Sin embargo. podría ser el siguiente: . un archivo que. es interesante que sepa. Un pequeño ejemplo Este ejemplo le mostrará de qué es capaz Smarty. aquel que mostraba la hora. Figura 10. Lo mejor para entender lo que estamos diciendo es verlo en funcionamiento. De hecho. tendríamos dos archivos: el PHP y una plantilla con el diseño correspondiente. vamos a retomar el primer ejemplo que vimos en el capítulo 2. Poco diseño hay en esta página. El resultado de cargar esa página puede verse en la figura 10. El resultado: no hay código PHP en las páginas HTML. Aún no lo hemos instalado (lo haremos en el siguiente apartado). Esto permite que el equipo de desarrollo pueda trabajar de forma independiente al equipo de diseño.Figura 10. pero podemos dejarlo libre de código PHP. así que aún queda un poco para que pueda poner en funcionamiento lo que vamos a ver. Para nuestro ejemplo. ¿Dónde está Smarty? La principal misión de Smarty es aislar la lógica de la representación de las páginas. ni código HTML en las páginas PHP. lo que se puede conseguir con Smarty. Una sola línea de código cuyo resultado variaba en función de la hora a la que la página se cargase. tiene la extensión TPL (template. antes de nada.2. plantilla).2. ¿Qué hora es? HTML y PHP entremezclados en la misma línea.1. Con Smarty. El código de esa página era el siguiente: La hora es: <?= date("H:i:s") ?>. date("H:i:s")).2.class. añadiendo lo que le plazca.tpl'). que utilizaremos para llevar a cabo la magia. Figura 10. $smarty = new Smarty. podrá disponer de varios diseños diferentes para la página únicamente cambiando el nombre de la plantilla que quiera utilizar. Hablando claro: una vez tenga el programa que recupera la lista de géneros. 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. con tal de que cumpla una condición: incluir {$hora} donde deba ir la hora. ?> El primer requisito: tener acceso al archivo Smarty. Seguro que está impaciente por empezar a utilizar esta herramienta en sus páginas. Y ahora.class. existen muchas otras. Si guardase ese archivo con el nombre smarty. le toca al programador.La hora es: {$hora}. El código de la página PHP sería el siguiente: <?php include('Smarty. No es extraño.tpl y lo intentase cargar en un cliente Web podría ver algo parecido a lo que muestra la figura 10. $smarty->display('smarty.php. Plantilla sin aplicar Un diseñador podría trabajar con este archivo. 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. Instalación El primer paso para instalar Smarty es descargarlo desde su página Web: . El resultado será idéntico al que vimos en la figura 10.3. Una de las más importantes es que podrá cambiar el aspecto de las páginas sin que cambie la lógica del programa.php'). Además de la ventaja que supone separar el diseño de la lógica en sus programas.3. En este archivo está la descripción de la clase Smarty. $smarty->assign('hora'. Posteriormente. indica que el archivo ha sido comprimido con gzip.4. tar y gunzip (disponibles casi con total seguridad en su distribución de Linux) o Stuffit (http://my.net/download. Figura 10. Debido a la naturaleza de la Web.http://smarty. Como ya sabe por capítulos anteriores.php Descargue la última versión estable. modifique la configuración de PHP para que sepa dónde encontrar a Smarty. estas opciones de configuración pueden incluirse en el archivo php. por si acaso: http://smarty. mientras que t ar indica que se trata de un paquete de archivos. o en Apache.gz es muy frecuente en sistemas Unix.com/mac/stuffit/) le ayudarán a extraer el contenido del archivo en una carpeta temporal. se trata de un archivo con la extensión tar.org/).gz. Los archivos de Smarty El proceso de instalación es tan sencillo como colocar esta carpeta donde desee. En este caso vamos a copiarla dentro de la carpeta en la que XAMPP se haya instalado. . aunque también está disponible una versión en formato zip. si no utiliza XAMPP tendrá que guardar la carpeta de Smarty en otra ubicación.ini. Existe una variable de configuración llamada include_path. La parte final. como en la figura 10. 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. limitando su ámbito a una carpeta en particular. Herramientas como 7-Zip (http://7-zip. Obviamente. La extensión t ar.4. Esta ruta será diferente dependiendo del sistema operativo que utilice. Not a: Esto es para aquellos que utilicen Windows. no es seguro que éste sea enlace del que descargar Smarty cuando lea estas líneas pero. gz . para que estén disponibles de forma global. Por lo general.smithmicro.net/ Localice la página de descarga en la Web de Smarty. Vamos a optar por la segunda opción..php').class. En esa variable debe incluir dos carpetas. que ya vimos en anteriores capítulos: <?php phpinfo(). la carpeta en la que vaya a poner las plantillas. 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. aquella en la que haya instalado Smarty. que se encuentra en el interior de htdocs. ?> El valor de la variable include_path puede verse en la 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 ruta de Smarty Not a: En Windows..deny Allow from all php_admin_value include_path \ "C:/xampp/smarty/libs. En el resto de sistemas operativos.5. incluya una directiva php_admin_value con la que asignar un valor a la opción de configuración include_path. Como ya hicimos en el capítulo anterior y en el 7. ). Para ello. Figura 10. las rutas a incluir se separan con punto y coma (. La configuración de Apache para la carpeta plantillas podría ser algo así: .5. 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. con dos puntos (: ). <Directory "C:/xampp/htdocs/plantillas"> Options Indexes FollowSymlinks AllowOverride None Order allow. El nombre de esta carpeta será plantillas.C:/xampp/htdocs/plantillas" </Directory> . con el siguiente código: <?php require('Smarty.. la carpeta htdocs. . La primera. vamos a crear una nueva carpeta dentro de la predeterminada de Apache. La segunda. el código de dicha página es el siguiente: <?php $videoteca = new mysqli( ''. Lista de géneros En el capítulo 7 vimos cómo cargar la lista de géneros existentes en nuestra base de datos. ?> Si al cargar esta página no se produce ningún error. si no localiza el problema.%s<br/>". ?> Y ahora que tiene Smarty en su sistema.php' ). 'videoteca'). $fila[0]. vamos a retomar la página que muestra el listado de géneros.'). $fila[2] ). . Una posible solución. $smarty = new Smarty.class. $smarty = new Smarty. Revise la configuración y vuelva a cargar la página. todo ha ido bien.'). $fila[1]. es indicar la ruta completa del archivo requerido: <?php require( 'C:/xampp/smarty/libs/Smarty. ''. } $resultado = $videoteca->query( 'SELECT * FROM genero' ). exit(). if ($resultado == FALSE){ echo('Error en la consulta.class. if (mysqli_connect_errno() != 0){ echo('Error en la conexión. Tras lo visto en los capítulos siguientes a ese. lo más seguro es que PHP no haya sido capaz de encontrar los archivos necesarios. } while ($fila = $resultado->fetch_row()){ printf( "(%u) %s .require('Smarty.php'). ''. En caso contrario. La plantilla De golpe. el nombre de la variable es $generos. encargado de representar la información de los géneros. Vamos a comenzar haciendo algo sencillo: lograr que el aspecto de la página sea el mismo que tenía sin utilizar Smarty. dentro de la carpeta plantillas que creó anteriormente.géneros</title> </head> <body> {section name=i loop=$generos} ({$generos[i]. y en cada iteración se referirá a cada elemento de la matriz con el nombre i. En esa misma carpeta necesitará otras dos: templates y templates_c. En la primera guarde los archivos con la extensión TPL . no hay dolor.tpl. En este caso. 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(). ¿Y qué es lo que hace esta plantilla? Primero fíjese en los elementos {section}.nombre} {$generos[i]. $videoteca->close(). el punto que tendríamos que modificar para cambiar el aspecto de los datos mostrados será el bucle while. dentro de la carpeta plantillas. Guarde el código anterior en un archivo llamado generos.). la segunda es para uso interno de Smarty. Gracias a ellos puede realizar iteraciones. } $resultado->close(). ?> Analice el código PHP anterior. Olvidando los mensajes que envíe en caso de error en la conexión o la consulta.php. Es ahí donde tendremos que utilizar Smarty. . esta es la plantilla: <html> <head> <title>Smarty .id}) {$generos[i]. con el nombre generos.descripcion}<br/> {/section} </body> </html> Debe guardarla en la carpeta templates. Se trata de una matriz que contendrá la lista de géneros disponible. exit(). } $generos = array(). if ($resultado == FALSE){ echo('Error en la consulta. $smarty = new Smarty. $fila).'). se dedica a guardarlos todos en una matriz. while ($fila = $resultado->fetch_assoc()){ array_push($generos. $videoteca = new mysqli( ''. } $resultado->close(). . ¿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. if (mysqli_connect_errno() != 0) { echo('Error en la conexión.tpl').Dentro del bucle se accede al identificador del género así: $genero[i]. } $resultado = $videoteca->query( 'SELECT * FROM genero' ). todo es más o menos igual que antes de utilizar Smarty.id El atributo loop de la sección determina sobre qué variable va a iterar. salvo por el uso de la instrucción include. ''.'). $generos). $videoteca->close(). que en lugar de mostrar los detalles de cada género. $smarty->assign('generos'.class. $smarty->display('generos.php'). pero utilizando Smarty para ello: <?php include('Smarty. ?> Hasta que llegamos al bucle while. La primera diferencia la encontramos en este bucle. ''. mientras que el atributo name le da el índice del elemento actual. 'videoteca'). Esto en cuanto a la plantilla pero. $plantilla = $_GET['plantilla']. . todo seguirá funcionando correctamente. 'videoteca').6.tpl'. Ahí empieza la diferencia.. pase ese nombre de plantilla al método display(). Esta plantilla tendría el siguiente código: <html> . $smarty->display($plantilla). Entonces. vamos a crear una nueva plantilla.. Ahora. como antes. como texto. Va a recibir el nombre de la plantilla a través de la URL. le pasamos la lista de géneros. lo hará dentro de una tabla. Figura 10. Algo así: . El resultado es indistinguible del obtenido sin Smarty. Creamos un ejemplar de la clase Smarty.Tras este bucle. . Géneros.. Si carga la página tal y cual.class.. se cierra tanto el resultado de la consulta como la conexión con la base de datos.php'). include('Smarty. Otra plantilla Haga un pequeño cambio en la página PHP que muestra los géneros utilizando Smarty. ''.6... ''. con Smarty Pero sí que hay una importante diferencia. Veamos lo sencillo que resulta cambiar el aspecto de una página. como puede verse en la figura 10. } $videoteca = new mysqli( ''. if($plantilla == ''){ $plantilla = 'generos. En lugar de mostrar la lista de géneros tal cual. que tenemos en una matriz y llamamos al método display() para que la magia tenga lugar. Si no recibe ningún nombre se utilizará uno predeterminado. basada en la anterior. tpl dentro de la carpeta templates que creó anteriormente. La magia vuelve a ocurrir cuando carga la página pasando un valor para el nombre de la plantilla.descripcion}</td> </tr> {/section} </table> </body> </html> Guarde esta plantilla con el nombre tabla. como puede verse en la figura 10.7.7.nombre}</td> <td>{$generos[i]. Figura 10. varias plantillas . Mismo PHP.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]. Un mundo de posibilidades.id}</td> <td>{$generos[i]. abierto ante nosotros.<html> <head> <title>Smarty . 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. Este capítulo sirve como presentación de los procedimientos almacenados. Además. en los que se tratan en detalle las más importantes características de MySQL. para hacerlo posible es necesario que dichos capítulos sean independientes. Quizá algunos lectores de este libro hayan acudido directamente a los capítulos finales (como éste). Aunque no es recomendable. razón por la que muchos decidían utilizar otros sistemas gestores de bases de datos. consideradas por muchos como una variedad de procedimientos almacenados. Introducción A lo largo de los capítulos que preceden a éste ha podido comprobar cómo evoluciona una base de datos. Los procedimientos almacenados facilitan la ejecución de conjuntos de instrucciones SQL. Como comprobará. Además. partiendo de una sencilla idea que se va complicando a medida que se convierte en realidad. Empezaremos creando una base de datos con una sola tabla. A partir de ese momento veremos procedimientos almacenados más complejos. deberá conocer el lenguaje SQL. quizá. Para que pueda leerse independientemente del resto del libro utilizaremos un subconjunto de la base de datos de ejemplo desarrollada en capítulos anteriores. que utilizaremos para probar el funcionamiento de un sencillo procedimiento almacenado de ejemplo. del resto del libro. de alguna manera. La sintaxis será explicada en apartados posteriores. Base de datos reducida . esto ha dejado de ser una excusa. aunque también podrá utilizar la base de datos completa. si lo desea.11 Procedimientos almacenados La posibilidad de utilizar procedimientos almacenados en MySQL es. permitiendo agruparlos bajo un nombre común. La ausencia de los mismos en versiones anteriores a la 5 suponía una traba para el desarrollo de algunas aplicaciones. una de las características más esperadas. las diferencias existentes entre ambos no son demasiadas. También veremos cómo crear funciones almacenadas. gracias a su empleo se puede lograr cierto nivel de independencia entre la base de datos y las aplicaciones que hacen uso de ella. Por fortuna. Advert encia: Tenga cuidado: si ya dispone de una base de datos con ese nombre. Figura 11. Una vez disponga de la base de datos es necesario crear la tabla que contendrá los detalles de los actores. .1. nombre VARCHAR(64) NOT NULL. la base de datos que utilizaremos sólo contendrá la tabla actor . De hecho. DROP TABLE IF EXISTS actor. CREATE DATABASE videoteca. 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. En lo que a este capítulo respecta. CREATE TABLE actor ( id INT NOT NULL AUTO_INCREMENT. 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. Las siguientes instrucciones cumplen tal misión: USE videoteca. Puede ver un diagrama de la misma en la figura 11. En los siguientes dos apartados crearemos la base de datos de prueba e insertaremos algunos registros en su única tabla.1. las instrucciones anteriores la borrarán junto con su contenido. vamos a trabajar con una versión muy reducida de la misma.Seguramente ya esté familiarizado con la base de datos que hemos creado a lo largo de este libro. 'Ford'. Utilice las siguientes instrucciones: USE videoteca. apellidos. El siguiente código crea un procedimiento almacenado de tales características: USE videoteca. la lista de actores almacenados en la tabla actor . 'Crowe'.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. imdb VARCHAR(32) NOT NULL DEFAULT ''. Un sencillo ejemplo Una de las tareas más simples que se pueden realizar utilizando procedimientos almacenados es recuperar información. Fíjese en cómo está construido el nombre del procedimiento almacenado. Figura 11. imdb) VALUES('Russell'. imdb) VALUES('Harrison'. Como separador de palabras hemos utilizado el guión bajo (_). INSERT INTO actor(nombre.2. Por ejemplo. CREATE PROCEDURE pa_actores_lista() SELECT * FROM actor.nombre VARCHAR(64) NOT NULL. 'nm0000148'). 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. 'nm0000128'). apellidos. lo más parecido a un espacio que nos permiten las normas de MySQL para los . apellidos VARCHAR(64) NOT NULL. PRIMARY KEY(id) ) ENGINE = InnoDB. INSERT INTO actor(nombre. Está realizado con MySQL Workbench. La figura 11. Lo que diferencia las instrucciones anteriores de una consulta de selección es. 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.nombres. Para crear el procedimiento almacenado. El nombre comienza con pa. la instrucción CREATE PROCEDURE . CALL pa_actores_lista(). Posteriormente nos centraremos en la sintaxis necesaria para crear procedimientos almacenados. El resto del nombre intenta definir claramente la finalidad del procedimiento almacenado.3 muestra la respuesta que MySQL debería dar. La siguiente. guárdalas con el nombre pa_actores_lista porque luego las voy a necesitar". Ya conoce la misión de la primera línea del listado anterior: indicar la base de datos con la que queremos trabajar. ejecute las instrucciones anteriores como si estuviese ejecutando cualquier otro conjunto de instrucciones. que comienza con la instrucción CREATE PROCEDURE . precisamente. La figura 11. Creación del primer ejemplo Ha llegado el momento de obtener los frutos del trabajo realizado hasta ahora. Lista de actores Como puede comprobar si lo desea. las iniciales de procedimiento almacenado. Figura 11. De hecho. Figura 11. ejecutar el procedimiento almacenado devuelve el mismo resultado .4 muestra el resultado devuelto por el procedimiento almacenado que acabamos de crear.3. Se trata de una elección personal que depende de las preferencias de cada uno. pero no así el resto. se trata de una simple consulta de selección.4. Ejecute el procedimiento almacenado utilizando las siguientes instrucciones: USE videoteca. La figura 11. Así es posible diferenciarlo claramente de una tabla. le será desconocida. Sintaxis Las posibilidades ofrecidas por el uso de los procedimientos almacenados van mucho más allá de lo visto en el ejemplo anterior. este equipo nunca utilizaría consultas. La parte estructural estaría compuesta tanto por el diseño de la base de datos como por los registros almacenados en las tablas. el equipo dedicado a la creación de las páginas PHP. existe una muy obvia: quien ejecute este procedimiento almacenado no necesita saber nada en absoluto sobre la estructura de la base de datos. Por ejemplo. Por lo tanto. Para incorporar la información obtenida a partir de la base de datos. este lenguaje dispone de las herramientas necesarias para comunicarse con MySQL. Así que podría existir un equipo dedicado al mantenimiento de la base de datos. siempre y cuando los procedimientos almacenados sigan devolviendo los mismos datos. SELECT * FROM actor. Y. Entonces. sólo procedimientos almacenados. otro les proporcionaría todos los detalles del mismo. ¿por qué utilizar procedimientos almacenados? Aunque existen muchas otras ventajas. Para poder sacarles todo su . definiendo sus campos y creando los procedimientos almacenados que devuelvan información a partir de los datos contenidos en la base de datos. 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. y así para cada caso. Se podría decir que hemos divido la base de datos en dos partes: una estructural y otra lógica. El conjunto de procedimientos almacenados creados para recuperar información de esa base de datos sería la parte lógica. por otro lado. diseñando tablas. no sería necesario que conociesen la estructura de la base de datos. un tercero les mostraría la lista de películas protagonizadas por dicho actor. Esas páginas serán el cliente de la base de datos. ¿Y por qué supone esta división una ventaja? Porque ofrece la posibilidad de trabajar con dos equipos. la posibilidad de modificar el diseño de la base de datos sin por ello tener que modificar las páginas PHP. Not a: Esta independencia entre equipos tiene ventajas añadidas.que esta consulta: USE videoteca. Como ya hemos visto. sólo tendrían que llamar a un determinado procedimiento almacenado para obtener la lista de actores. Este espacio se encuentra en la memoria . Figura 11. En ellas se guardarán aquellos valores que haya que consultar o modificar posteriormente.visto en el ejemplo anterior. Si fuese necesario. El siguiente ejemplo calcula y muestra el número de registros de la tabla actor : USE videoteca.5. necesitará almacenarlos en algún lugar. 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. precisamente lo que veremos a partir de ahora. 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. Número de actores Variables Los datos no son etéreos y. más adelante).]) instrucciones Tras las palabras reservadas CREATE PROCEDURE se incluye el nombre del procedimiento almacenado..5. Para poder sacarles todo su jugo es necesario conocer cómo construirlos correctamente. En la jerga de los programadores.. El lenguaje SQL es un lenguaje de programación. [. mientras que la segunda es el cuerpo del procedimiento. CREATE PROCEDURE pa_actores_cantidad() SELECT COUNT(*) FROM actor. El resultado de ejecutar este procedimiento almacenado puede verse en la figura 11. puede recibir una serie de parámetros (más al respecto en el apartado “Funciones almacenadas”. Una variable es ese lugar. en ocasiones. El procedimiento almacenado estará completo cuando se incluyan las instrucciones asociadas al mismo. Consejo: Si quiere refrescar sus conocimientos sobre los tipos de datos. Por ejemplo. Incluya a continuación el tipo de datos de dicha variable. en la RAM.principal del ordenador. DECLARE actores INT. 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.. Existen dos formas de asignar un valor a una variable tras su creación: Directamente: Utilizando la palabra reservada SET . ... es posible declarar la variable actores para que su valor inicial sea 0: .. DECLARE actores INT.] tipo [DEFAULT valor_predeterminado] La palabra reservada DECLARE va seguida del nombre de la variable que se quiera declarar.. . que se incluye en la sintaxis de DECLARE . . Por ejemplo. En ella se hace un repaso de los más importantes ofrecidos por MySQL. algo que se logra gracias a la palabra reservada DEFAULT . SELECT . acuda a la sección 6 del capítulo 3. el valor almacenado en una variable es NULL .. Inicialmente. la siguiente instrucción sirve para crear una variable de tipo entero llamada actores: . SET actores = 0. la naturaleza de los datos que contendrá. la siguiente consulta recupera el número de registros en la tabla actor y guarda el valor en la variable actores: .. es decir... Así. Así... . podría asignarse el valor 0 a la variable tras declararla: .. Tomando su valor de una consulta: Utilizando la pal abra INTO en una consulta de selección.. DECLARE actores INT... “Tipos de datos”. es decir.. DECLARE actores INT DEFAULT 0. END. 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... es posible incluir tantas instrucciones como sea necesario. se devuelve dicho valor. CREATE PROCEDURE pa_actores_cantidad2() BEGIN DECLARE actores INT DEFAULT 0. Delimitadores Ya sabe que cuando se escribe una sentencia SQL es necesario utilizar punto y coma (. Puede comprobar que los dos procedimientos almacenados creados hasta ahora cumplen dicha norma. fíjese en esta versión del procedimiento almacenado visto anteriormente. A continuación. cuya misión era devolver el número de registros en la tabla actor : USE videoteca. como tal. la misma norma ha de seguirse en el cuerpo del procedimiento almacenado si éste está compuesto por más de una sentencia SQL. En lo que resta de capítulo podrá encontrar varios ejemplos del uso de variables en procedimientos almacenados. Por otra parte. se utiliza una variable en la que se almacena el resultado de la consulta. caso que hasta ahora no se ha dado. En lugar de ejecutar directamente la consulta. .) para indicar dónde acaba. necesita el empleo de dicho delimitador. El cuerpo de los procedimientos almacenados que hemos visto hasta ahora está compuesto de una sola sentencia SQL. Sin embargo. Es la posibilidad de realizar las mismas tareas de diferentes . SELECT actores. La sentencia de creación de un procedimiento almacenado también es SQL y.SELECT COUNT(*) INTO actores FROM actor. SELECT COUNT(*) INTO actores FROM actor. A continuación. estableciendo como delimitador el punto y coma.6 muestra la respuesta del cliente de MySQL al ejecutar las instrucciones de creación del procedimiento almacenado y una posterior llamada al mismo.formas lo que hace tan interesante utilizar este tipo de tecnologías. El siguiente es el código del procedimiento almacenado anterior. SELECT actores. La figura 11. se utiliza el delimitador declarado anteriormente. se deja todo como estaba. Antes de comenzar la creación del procedimiento almacenado se declara el nuevo delimitador. se crea el procedimiento almacenado y. La solución a este conflicto es relativamente simple: definir un delimitador diferente para los procedimientos almacenados. Si intenta crear el procedimiento almacenado anterior MySQL le mostrará varios mensajes de error. corregido para que sea correcto: USE videoteca. seguida de la secuencia de caracteres marcará el final del procedimiento almacenado. 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. Para terminar. tras la instrucción END. . END // DELIMITER . DELIMITER // CREATE PROCEDURE pa_actores_cantidad2() BEGIN DECLARE actores INT. SELECT COUNT(*) FROM actor INTO actores. Para ello se utiliza la palabra clave DELIMITER. Aunque existe la posibilidad de utilizar prácticamente cualquier delimitador en la documentación de MySQL se utilizan dos barras inclinadas (//). el tipo de . encabeza el resultado con COUNT(*). En primer lugar. para informar de un valor obtenido al ejecutar el procedimiento almacenado. Sin embargo. A su vez. se está pasando un valor desde la instrucción de llamada. los corchetes indican una opción.6. es decir.Figura 11. es decir. es decir. si no se indica nada. existe la posibilidad de declarar una serie de parámetros asociados. puesto que lo que se está seleccionando es el valor de la variable así llamada. 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 . OUT : Se trata de un parámetro de salida. 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. El primero de ellos. De forma predeterminada. para comunicarse con el exterior. Como el movimiento se demuestra andando. por lo que no es obligatorio incluir los valores IN o OUT . los parámetros de entrada. en la figura 11. Not a: Como ya sabe. en la figura 11. el parámetro será de tipo IN. nada mejor que un ejemplo sobre la utilización de cada tipo de parámetro para comprender su funcionamiento.6. Ese valor sólo se utilizará para proporcionar información al procedimiento almacenado. Efectivamente.5. el número mostrado bajo dicho texto es el resultado de esa instrucción. el encabezado es actores. Parámetros Como pudo verse en la descripción de la sintaxis de los procedimientos almacenados. 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. SELECT COUNT(*) INTO . CREATE PROCEDURE pa_actores_buscar(letra CHAR(2)) SELECT * FROM actor WHERE nombre LIKE letra.7 muestra el resultado de ejecutar esta consulta. OUT actores INT ) BEGIN SELECT * FROM actor WHERE nombre LIKE letra. Búsqueda de actores Suponga que. Es decir. DELIMITER // CREATE PROCEDURE pa_actores_buscar2( IN letra CHAR(2).7. 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%'). además de la lista de actores. La figura 11. Figura 11. necesita guardar en una variable de salida el número de actores localizados.parámetro predeterminado. ha de utilizarse una variable de tipo OUT : USE videoteca. Sin embargo. En la figura 11. conocido por su presencia en las direcciones de correo electrónico. 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. como se indica en el primer parámetro. 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.actores FROM actor WHERE nombre LIKE letra. END // DELIMITER . Figura 11. @cantidad). Valor de la variable de salida Not a: Existe un tercer tipo de parámetro. INOUT . fíjese en que el segundo comienza con el carácter @ (arroba). Así. que queda fuera de los objetivos de este capítulo. CALL pa_actores_buscar2('h%'. Para más información consulte la documentación de MySQL. Funciones almacenadas La sintaxis de las funciones almacenadas es . La llamada a este procedimiento almacenado es como sigue: USE videoteca.8. Utilice este símbolo para crear variables de sesión. También se buscan aquellos actores cuyo nombre comience con la letra h. tras la llamada al procedimiento almacenado de búsqueda es posible obtener el número de resultados obtenidos de la siguiente forma: SELECT @cantidad. ]) RETURNS tipo instrucciones A diferencia de los procedimientos.. Figura 11.prácticamente la misma que la de los procedimientos almacenados: CREATE FUNCTION nombre_fa ([parámetro.9. Función almacenada . El resultado de ejecutar la anterior consulta puede verse en la figura 11.. [. Al encabezado de la función se añade la palabra clave RETURNS seguida del tipo de datos del valor devuelto. los de entrada (IN ). DELIMITER // CREATE FUNCTION fa_actores_cantidad() RETURNS INT BEGIN DECLARE actores INT. Es posible utilizar las funciones dentro de consultas SQL. Considere esta versión modificada del procedimiento almacenado que mostraba el número de registros presentes en la tabla de actores: USE videoteca.9. Las funciones almacenadas proporcionan una forma diferente de realizar una misma tarea. como puede ver en la siguiente: USE videoteca. las funciones sólo pueden utilizar un tipo de parámetros. SELECT COUNT(*) INTO actores FROM actor. RETURN actores. SELECT fa_actores_cantidad(). END // DELIMITER . de manera que ahora el resultado se ordene alfabéticamente. tras crear un procedimiento almacenado. Así. De nuevo. vuelva a crear el procedimiento almacenado añadiendo las modificaciones que considere necesarias. una elección personal. suponga que quiere cambiar el procedimiento almacenado que devuelve la lista de actores. En esas ocasiones puede eliminar el procedimiento almacenado utilizando orden DROP . cuando la definición de la sintaxis de una determinada operación incluya la palabra reservada PROCEDURE . en los siguientes apartados nos referiremos a ambos como procedimientos almacenados. Deberá ejecutar las siguientes instrucciones: USE videoteca. nombre. Eliminación Es posible que.Not a: Fíjese en que. a diferencia de los procedimientos almacenados. 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. se localice algún error en el código del mismo o se quiera modificar su funcionamiento. recuerde que debe cambiarla por FUNCTION si va a trabajar con una función en lugar de con un procedimiento. primero por apellidos y luego por nombre. A continuación. Éste es el código necesario: <?php . CREATE PROCEDURE pa_actores_lista() SELECT * FROM actor ORDER BY apellidos. A pesar de las diferencias existentes entre los procedimientos y las funciones almacenadas. Para evitar un error en caso de que el procedimiento almacenado no exista puede añadir las palabras reservadas IF EXISTS. 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. Por ejemplo. DROP PROCEDURE IF EXISTS pa_actores_lista. el prefijo seleccionado para los nombres de las funciones almacenadas es fa . '). $fila[2]. } $resultado = $videoteca->query( 'CALL pa_actores_lista()' ).'). if ($videoteca->errno != 0) { echo('Error en la conexión.10. $videoteca->close(). ''. exit(). } while ($fila = $resultado->fetch_row()){ printf( "(%u) %s %s: %s<br/>".10 muestra el resultado del programa anterior. 'root'. simplificando la ejecución de tareas frecuentes como el acceso o la modificación del contenido de las tablas de una base de datos. Procedimientos almacenados y PHP A lo largo de este capítulo hemos visto los conceptos básicos necesarios para trabajar con procedimientos almacenados. Figura 11. if ($resultado == FALSE){ echo('Error en la consulta. .$videoteca = new mysqli( 'localhost'. Gracias a ellos es posible agrupar varias sentencias SQL bajo un mismo nombre. $fila[3] ). ?> Como puede comprobar. La figura 11. 'videoteca' ). } $resultado->close(). $fila[0]. $fila[1]. 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. que estos procedimientos almacenados pueden utilizarse desde lenguajes de programación como PHP. este capítulo es sólo el comienzo. Si desea ampliar sus conocimientos sobre procedimientos almacenados. modificar y eliminar procedimientos almacenados.html .mysql. Sin embargo.com/doc/mysql/en/create-procedure.com/tech-resources/articles/mysqlstoredprocedures. le recomendamos que visite la página de la documentación de MySQL dedicada a los mismos: http://dev. Obviamente.mysql. también cómo utilizarlos.Ahora sabe cómo crear. sin entrar en detalles.html Quizá encuentre interesante el siguiente artículo. Incluso ha visto. también publicado en la Web de MySQL: http://dev. También es posible asociar un desencadenador a una operación de actualización. una actualización o un borrado. Por lo tanto. Introducción Al igual que en el capítulo anterior. Además. Así. deteniendo la operación en caso de que se detecte alguna incongruencia. deberá conocer el lenguaje SQL. Como se reconoce en la documentación de MySQL. 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. es posible que muchos lectores tengan la tentación de leer estas páginas sin pasar por los capítulos anteriores. dedicado a los procedimientos almacenados. Para facilitarles las cosas. Si lo desea. de manera que una modificación de los datos de una determinada tabla active de forma automática una actualización en otra tabla. Si no cumple alguno de estos requisitos lo más razonable es que lea este libro como debe. algo que no disminuye la utilidad de los mismos. Y sólo se han enumerado algunas de las posibilidades que ofrece esta interesante característica de MySQL. manteniendo sincronizados los datos que se requieran. este capítulo pretende ser lo más independiente del resto del libro que sea posible. poco a poco. este capítulo trata una de las más importantes características de MySQL. . desde el principio. De nuevo. También conocidos por su nombre en inglés (triggers). El simple hecho de que sea posible utilizarlos deja prever que. las características ofrecidas por los desencadenadores son limitadas. 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. los desencadenadores permiten realizar tareas de forma automática cuando una determinada circunstancia tiene lugar. con los desencadenadores se puede verificar que los valores que se intenta insertar en una tabla cumplen unas determinadas condiciones. Se pueden crear desencadenadores que se activen antes o después de una inserción.12 Desencadenadores Este capítulo está dedicado a otra de las importantes características de MySQL: los desencadenadores. com/harrison_ford/ Aviso: En esa dirección no va a encontrar nada relacionado con el cine. Por lo visto ext viene de externo y hace referencia a que los datos que la tabla contiene son externos al actor.1 muestra el aspecto de las dos tablas que contendrán los datos de cada actor. se ha hecho cargo de videoteca. Aquí comienza un pequeño cambio. La sección homónima del capítulo anterior muestra más detalles sobre la misma. compuesto por el nombre y los apellidos del actor. Imagine que un nuevo diseñador de bases de datos. Esta tabla estará relacionada con la tabla actor gracias al identificador numérico. llamada actor. 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. en minúsculas y separados por un guión bajo (_). Anteriormente. .com/) asigna a cada actor. contiene un identificador numérico único para cada actor . existe un nuevo requisito solicitado por la empresa que está pagando el desarrollo de la base de datos: se debe crear un nuevo campo. sino con una fuente de información externa. La figura 12. Por lo visto. su nombre y sus apellidos. La primera de ellas. con más experiencia. Sólo por si acaso. los detalles de Harrison Ford estarían en la dirección: http://www. A su modo de ver. En lo que respecta a este capítulo. El nombre de la tabla será actor_ext . El diseñador ha considerado que el nuevo campo y el campo imdb tienen aspectos en común. le recomendamos que acuda a ella si quiere saber más al respecto. dicha base de datos está compuesta por dos tablas. esta tabla también contenía un campo llamado imdb: el identificador que IMDb (http://imdb.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.example. Además. se trata de un simple ejemplo. para proporcionar una forma de acceder a la información de dicha Web desde los programas que desarrolle. así que ha decidido crear una nueva tabla en la que guardar ambos. quieren que ese nombre se utilice en las direcciones Web de su propia página dedicada al cine: una por cada actor. Así. esta tabla sólo debe contener datos sobre el actor y el campo imdb no está relacionado con él. es necesario crear la base de datos: DROP DATABASE IF EXISTS videoteca.Figura 12. FOREIGN KEY(idactor) REFERENCES actor(id) ) ENGINE = InnoDB. 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. Inserción Por último. será necesario realizar una inserción por cada tabla: USE videoteca. apellidos) VALUES('Harrison'. carpeta VARCHAR(255) NOT NULL. CREATE TABLE actor_ext ( idactor INT NOT NULL. como hay dos. nombre VARCHAR(64) NOT NULL. INSERT INTO actor(nombre. Además. CREATE DATABASE videoteca. imdb VARCHAR(32) NOT NULL. INDEX ae_FK(idactor). imdb. PRIMARY KEY(id) ) ENGINE = InnoDB.1. 'Crowe'). carpeta) . si ha seguido los ejemplos de todo el libro ya tendrá una base de datos con ese nombre. 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. 'Ford'). cree las tablas de la base de datos utilizando las siguientes instrucciones: USE videoteca. insertaremos algunos registros de ejemplo para que la base de datos disponga de contenido con el que trabajar. A continuación. apellidos VARCHAR(64) NOT NULL. INSERT INTO actor_ext(idactor. inserte algunos valores en las tablas. En primer lugar. PRIMARY KEY(idactor). En este caso. apellidos) VALUES('Russell'. CREATE TABLE actor ( id INT NOT NULL AUTO_INCREMENT. INSERT INTO actor(nombre. Advert encia: Sea cauto. evento: Indique aquí el tipo de instrucción que activará el desencadenador. Sintaxis Siguiendo la costumbre. 'russell_crowe'). Las palabras que están en minúsculas son las que necesitan explicación: nombre: Es el nombre que recibe el desencadenador. imdb. los valores necesarios para realizar las inserciones en la tabla actor_ext han sido tomados de la tabla actor . imdb. carpeta) VALUES(2. momento: Puede tomar los valores BEFORE (antes) o AFTER (después). Eliminación Para eliminar un desencadenador debe seguir la siguiente sintaxis: DROP TRIGGER nombre. Como es lógico. carpeta) VALUES(1. 'harrison_ford'). INSERT INTO actor_ext(idactor. 'nm0000128'. El valor de idactor es el del campo id de la tabla actor tras guardar el registro. instrucciones: Utilice BEGIN y END. Al tratarse de un campo de incremento automático no es posible conocer su antes de realizar la inserción. Lógicamente. UPDATE o DELETE . tabla: Nombre de la tabla con la que estará asociado el desencadenador. antes de los ejemplos veremos la sintaxis de las instrucciones relacionadas con los desencadenadores. Creación Para crear desencadenadores es necesario seguir la siguiente sintaxis: CREATE TRIGGER nombre momento evento ON tabla FOR EACH ROW instrucciones. Se utiliza para determinar si las instrucciones asociadas al desencadenador se ejecutarán antes o después de la operación que lo activó. como en los procedimientos almacenados. aquel por el que nos referiremos a él cuando queramos utilizarlo. nombre se refiere al nombre del desencadenador que desea eliminar. Se puede tratar de INSERT .INSERT INTO actor_ext(idactor. 'nm0000148'. si desea que el desencadenador tenga asociada más de una orden. Ejemplos . En los siguientes apartados comprobaremos lo útiles que pueden llegar a ser los desencadenadores. Ahora crearemos un desencadenador que.Por fin. Ahora.. Incluya también el nombre de esa operación como parte del nombre del desencadenador. para diferenciar un desencadenador de cualquier otro objeto de la base de datos añadiremos el prefijo dc a su nombre. nos vamos a poner manos a la obra. En el caso que nos ocupa. Inserción ¿Recuerda que... podríamos llamar dc_actor_insertar a este desencadenador. Las instrucciones asociadas se ejecutarán cuando se inserte un nuevo registro en la tabla actor . automáticamente. La única ventaja de este sistema es que permite diferenciar de un vistazo entre un desencadenador y otros objetos de la base de datos. Pregúntese a qué tabla debe estar asociado el desencadenador. se trata de una de las infinitas posibilidades existentes. insertamos algunos registros en la tabla actor ? Después. las instrucciones deberán ejecutarse después. tras no pocas páginas introductorias. Sólo resta escribir las instrucciones asociadas al . a falta de las instrucciones asociadas: . por lo tanto. ¿qué operación activa el desencadenador? Una inserción. Incluya el nombre de esa tabla como parte del nombre del desencadenador. Obviamente. seleccione la que más apropiada considere. tanto en las tareas de inserción y actualización como en las de borrado. Por último. Por lo tanto. es necesario conocer el valor que toma el identificador del actor recién insertado. fue necesario comprobar qué identificador se asignó al registro de cada actor para así mantener la integridad referencial. En primer lugar hemos de seleccionar el nombre del desencadenador. para realizar la inserción de los registros correspondientes en la tabla actor_ext .. tras la inserción de un nuevo actor en su tabla. El siguiente sería el encabezado del desencadenador que estamos creando. así como saber qué tarea realiza. creará el registro correspondiente en la tabla actor_ext . anteriormente. insertando el valor adecuado en el campo carpeta. CREATE TRIGGER dc_actor_insertar AFTER INSERT ON actor . cuando dicho identificador ya exista. 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: . Por lo tanto. ''. Fíjese en que. END . nuevo_carpeta).apellidos) ). De nuevo. imdb.desencadenador. La inserción se realiza utilizando dicha variable. En primer lugar.. carpeta) VALUES(NEW. como no se dispone del identificador imdb.id. '_'. imdb.nombre). es necesario obtener el identificador del actor recién insertado.id. en minúsculas. DELIMITER // CREATE TRIGGER dc_actor_insertar AFTER INSERT ON actor FOR EACH ROW BEGIN DECLARE nuevo_carpeta VARCHAR(255). fruto de la concatenación del nombre y los apellidos. carpeta) VALUES(NEW.nombre). se inserta una cadena vacía en el campo correspondiente.. La declaración de la variable nuevo_carpeta es la primera acción que lleva a cabo el desencadenador. En segundo lugar.. '_'.. Puede acceder a todos los valores de la operación que provocó la activación del desencadenador gracias al alias NEW. . SET nuevo_carpeta = CONCAT( LOWER(NEW. INSERT INTO actor_ext(idactor. LOWER(NEW. es posible utilizar el alias NEW para tal fin.id. El código completo de este desencadenador es el siguiente: USE videoteca. SET nuevo_carpeta = CONCAT( LOWER(NEW. DECLARE nuevo_carpeta VARCHAR(255).apellidos) ). LOWER(NEW. nuevo_carpeta). hay que concatenar el nombre y los apellidos del actor. ''. con un guión bajo como separador. es posible acceder a dicho valor escribiendo NEW. En ella se almacenará el nombre de la carpeta asociada al actor. INSERT INTO actor_ext(idactor. 'Robins'). Not a: Más sobre variables y delimitadores en el capítulo 11. Figura 12. apellidos) VALUES('Tim'. Para ello. el desencadenador asociado creará el registro correspondiente en la tabla act or_ext . UPDATE actor SET .// DELIMITER . 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. Como consecuencia. dedicado a procedimientos almacenados. INSERT INTO actor(nombre. Es un error cometido a propósito para aprovechar las posibilidades de los desencadenadores en operaciones de actualización. Actualización Como puede que ya haya notado. La figura 12. 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. así como su identificador imdb.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 . Suponga que se ha dado cuenta del error y lo intenta subsanar. Este procedimiento almacenado realizará la inserción del nombre y el apellido en la tabla actor. tendría que utilizar las siguientes instrucciones (no lo haga todavía): USE videoteca. insertando el identificador imdb donde corresponda. Sólo quedaría actualizar esta última tabla. Inserte ahora un nuevo actor en la tabla actor : USE videoteca.2. esto sólo subsanaría el error en la tabla actor . Se han seguido los mismos razonamientos que con el desencadenador de inserción para seleccionar su nombre: USE videoteca. Podrá comprobar que. Ahora sí. realice la operación de modificación en la tabla actor . Pero claro.apellidos) ). ¿No sería mejor que esta segunda actualización se realizase de forma automática? A fin de cuentas. no en actor_ext . LOWER(NEW. de forma automática. END // DELIMITER . '_'.SET apellidos = 'Robbins' WHERE id = 3. El siguiente es el código del desencadenador asociado con las actualizaciones de la tabla actor . DELIMITER // CREATE TRIGGER dc_actor_actualizar AFTER UPDATE ON actor FOR EACH ROW BEGIN DECLARE nuevo_carpeta VARCHAR(255). SET nuevo_carpeta = CONCAT( LOWER(NEW. así que sería necesario realizar otra actualización (tampoco la haga ahora): USE videoteca. UPDATE actor_ext SET carpeta = nuevo_carpeta WHERE idactor = NEW. ya sabe las operaciones que debe realizar porque las utiliza en el desencadenador de inserción.id. el valor . UPDATE actor_ext SET carpeta = 'tim_robbins' WHERE idactor = 3.nombre). 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. antes de realizarlo.id. el que se insertó en el apartado anterior. todos los desencadenadores que hemos visto se ejecutaban tras la acción que los activaba. elimine el registro correspondiente en la tabla actor_ext .del campo carpeta de la tabla actor_ext ha cambiado y su valor también es el correcto. idactor . DELIMITER // CREATE TRIGGER dc_actor_eliminar BEFORE DELETE ON actor FOR EACH ROW BEGIN DELETE FROM actor_ext WHERE idactor = OLD. El ejemplo que veremos en este apartado ejecuta las instrucciones asociadas antes. No es posible eliminar el registro de la tabla actor sin antes eliminar el asociado de la tabla actor_ext . ¿Por qué antes y no después? Porque la tabla actor_ext tiene un campo. END . Inténtelo si quiere: USE videoteca. por ejemplo. puede que prefiera automatizar el trabajo. Figura 12. como ya sabe utilizar desencadenadores. no después. Borrado Hasta ahora. Vamos a crear un desencadenador que se active al intentar un borrado en la tabla de actores y. Para eliminarlo es necesario borrar tanto el registro asociado en la tabla actor_ext como el de la tabla actor . que está relacionado con el campo id de la tabla actor . Obtendrá un error como el que se puede ver en la figura 12. Supongamos que queremos eliminar a uno de los actores de la base de datos.3. DELETE FROM actor WHERE id = 3.3. Pero. Puede acceder a los campos de la tabla a la que está asociado el desencadenador mediante el alias OLD. su base de datos será tan rápida como si no estuviesen presentes. actualizaciones y borrados. Utilizar desencadenadores en exceso puede complicar las operaciones de mantenimiento de la base de datos si su funcionamiento o existencia no está completamente documentado. Lógicamente. . tenga cuidado. En resumen: sus operaciones de selección tendrán el mismo rendimiento con y sin desencadenadores. una de las interesantes características de MySQL que le permitirá automatizar tareas tediosas. Así. añaden ciclos de proceso cuando están en funcionamiento pero. si las operaciones que realiza no los activan. como inserciones dependientes de claves de incremento automático. Tras crear el desencadenador podrá comprobar que la operación de borrado ya no provoca error alguno.id. Contrariamente a lo que se piensa. los desencadenadores no ralentizan el funcionamiento global de la base de datos. En este capítulo ha aprendido a utilizar desencadenadores. Sin embargo.// DELIMITER . el identificador del registro que se está intentado eliminar es OLD. Dejando tecnicismos a un lado. Estará en su mano sacar el máximo partido de ellas en su trabajo. Sintaxis . crearemos una vista que permitirá simular que la tabla que contiene los datos de los actores no fue dividida en ningún momento. 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. Se trata de una característica de MySQL que. dada su importancia. se presenta en su propio capítulo. Introducción Para trabajar en este capítulo aprovecharemos parte del trabajo realizado en el anterior. Puede pensar en las vistas como en tablas ficticias que toman sus datos de las tablas existentes. modificar y eliminar vistas. Base de datos de trabajo Así pues. Las vistas le permitirán añadir una nueva capa a esas dos.1. Cuando termine. En ella puede ver las dos únicas tablas que componen la base de datos. En los dos capítulos anteriores se presentaron los conceptos básicos necesarios para poder trabajar con procedimientos almacenados y desencadenadores.1. dedicado a los desencadenadores. 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. aumentando el valor de su base de datos. En este capítulo aprenderemos la sintaxis necesaria para crear. las vistas permiten modificar la forma en la que los datos son presentados. 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. A todos los efectos. Utilizando la base de datos de ejemplo que vimos en el capítulo anterior. el usuario no apreciará que haya habido cambio alguno en el diseño de la base de datos. siga todos los pasos de dicho apartado si aún no lo ha hecho. Figura 13.13 Vistas Como su propio nombre deja al descubierto. Refresquemos la memoria de aquellos que ya hayan pasado por él con la figura 13. vuelva aquí y continúe leyendo. Como ya sabe. utiliza esas palabras reservadas y ya existe una con el mismo nombre. Ejemplos La base de datos con la que trabajaremos durante este capítulo está compuesta por dos tablas. Creación Para crear vistas en sus bases de datos debe seguir la siguiente sintaxis: CREATE [OR REPLACE] VIEW nombre AS consulta. En la sección 3 de este mismo capítulo veremos algunos ejemplos. De esa forma. 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. 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 . Eliminación Cuando no necesite seguir utilizando una determinada vista puede eliminarla utilizando DROP VIEW: DROP VIEW [IF EXISTS] nombre. son el resultado de dividir la tabla actor original. la instrucción de borrado sólo se ejecutará si la vista existe. modificación y borrado. El resto de la vista estará compuesto por una consulta de selección. Para evitar que el intento de borrado provoque un error si no existiese ninguna vista con ese nombre. La sintaxis de esta última es: ALTER VIEW nombre AS consulta. Indique el nombre por el que desea referirse a la vista en nombre. Este último campo es de nueva aparición y fue creado en el capítulo anterior.Antes de comenzar a trabajar con vistas veremos la sintaxis de las diferentes operaciones que se pueden realizar con ellas: creación. 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. al crear la vista. Como ya sabrá. Entre corchetes. Si. incluya IF EXISTS. eso puede lograrse con la siguiente consulta: . ésta será reemplazada con la nueva. OR REPLACE . CREATE VIEW v_actor AS SELECT a.id = ae.2.apellidos.id. El resultado de ejecutar la consulta anterior puede verse en la figura 13.nombre. Para estos usuarios podría crear una vista en la que los datos de las tablas actor y actor_ext se combinasen. ae. Figura 13.imdb FROM actor a JOIN actor_ext ae ON a. Al igual que con los procedimientos almacenados y los desencadenadores.idactor. Las vistas se comportan a todos los efectos como si fuesen tablas. a aquellos con menos conocimientos de SQL. es posible realizar consultas de selección sobre ellas: USE videoteca. Por lo tanto.apellidos. a.2. SELECT a. comportándose como una sola tabla.USE videoteca. a. ae. En este caso. El código necesario para crear dicha vista es el siguiente: USE videoteca.id.nombre. . a.imdb FROM actor a JOIN actor_ext ae ON a. utilizaremos un prefijo que permita diferenciar las vistas del resto de objetos de la base de datos.id = ae.idactor. Datos de actores ¿No le parece interesante poder ocultar a algunos usuarios los detalles de la estructura de la base de datos? Por ejemplo. dicho prefijo será v. a. SELECT * FROM v_actor ORDER BY apellidos. 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.SELECT * FROM v_actor. nombre.5.3. como los de ordenación. que se muestra en la figura 13. Figura 13.2. Fíjese en el resultado de ejecutar esta consulta. . Figura 13. en las consultas que sobre ella se realicen. Pruebe a utilizar el nombre act or en la vista que acaba de crear. Por ejemplo: USE videoteca. MySQL le avisará de que ya existe una tabla con ese nombre. y compárelo con el obtenido en la figura 13. En la figura 13.4.4. Conflicto en el nombre Modificación Hasta tal punto las vistas se comportan como si de tablas se tratase que es posible incluir modificadores. Podrá comprobar que el orden en el que se devuelven los registros ha cambiado.3 puede ver el resultado de crear la vista y realizar una consulta sobre ella. como puede ver en la figura 13. a.apellidos. nombre.id. Como vimos en el apartado dedicado a la sintaxis de las operaciones relacionadas con la gestión de las vistas.id = ae. El código necesario para modificar la vista utilizando la primera de las opciones es el siguiente: USE videoteca.5. directamente. . nombre. a.imdb FROM actor a JOIN actor_ext ae ON a.apellidos.id = ae.Figura 13.nombre. Orden en las vistas Pero también es posible modificar el orden en el que los registros son devueltos.idactor ORDER BY apellidos. a. disponemos de dos opciones: CREATE OR REPLACE VIEW y ALTER VIEW. Aunque también puede obtener el mismo resultado con las siguientes instrucciones: USE videoteca.idactor ORDER BY apellidos.id.nombre. ae. por la vista. Para ello. CREATE OR REPLACE VIEW v_actor AS SELECT a. a. sólo hay que modificar la consulta.imdb FROM actor a JOIN actor_ext ae ON a. ae. ALTER VIEW v_actor AS SELECT a. En la figura 13. } $resultado = $videoteca->query( 'CALL pa_actores_lista()' ).').6 puede comprobar que ahora la vista devuelve los datos de los actores ordenados. Por ejemplo. if ($resultado == FALSE){ echo('Error en la consulta. 'root'.6. ''. Figura 13. exit(). las siguientes instrucciones eliminan la vista v_actor de la base de datos videoteca: USE videoteca.'). La eliminación de una vista no supone la eliminación de las tablas de las que obtenía los datos. DROP VIEW v_actor. 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. } . 'videoteca' ). É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'. 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. Gracias a ellas puede ocultar la verdadera estructura de la base de datos a algunos de los usuarios de la misma. Entre ellos.7. debe tener especial cuidado en mantener completamente documentados todos los aspectos de la base de datos. además.7 muestra el resultado del programa anterior. ?> Como puede comprobar. $fila[3] ). La figura 13. Así. Figura 13. la sobrecarga de trabajo que la gestión de las vistas puede suponer a los administradores de la base de datos. administradores y usuarios sabrán qué resultados pueden esperar de sus operaciones. Si.while ($fila = $resultado->fetch_row()){ printf( "(%u) %s %s: %s<br/>". la base de datos también tiene procedimientos almacenados y desencadenadores. el uso de vistas también presenta inconvenientes. $videoteca->close(). $fila[1]. Sin embargo. las vistas. 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. $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. 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. $fila[2]. . Vistas y PHP Durante este capítulo ha aprendido a gestionar una de las características más interesantes de MySQL. } $resultado->close(). y lo que es seguro es que. En primer lugar. aprenderemos trabajar directamente con XML. sin formato. Estás siglas. que tanto han dado que hablar. la utilización de XML con MySQL y PHP no resolverá todos nuestros problemas. Aunque dista mucho de ser el soporte completo que a todos nos gustaría tener. son sencillos caracteres de texto puestos uno tras otro. desde consultas SQL y. sí que se trata de un punto de partida. hace más fácil la posibilidad de que en la base de datos sólo haya datos puros. PHP dispone de multitud de herramientas para tratar con XML. utilizando herramientas como mysql o mysqldump. luego. no se trata de nada extraño. Pero. Ni una cosa ni otra: no son sólo unas siglas. por último. En este capítulo encontrará una introducción al formato XML. Por otra. En segundo lugar. La pareja formada por las aplicaciones Web (desarrolladas con MySQL y PHP) y XML resulta especialmente interesante. 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. ¿Qué es XML? Al hablar de XML y MySQL nos debatimos entre la sencillez de unas siglas y la panacea universal. mediante dos funciones que permiten manipular cadenas de texto con formato XML que se encuentren almacenadas en algún campo. Por su parte. por sí sola. permite almacenar en bruto grandes cantidades de datos en un único campo y. ¿qué aspecto tiene un documento XML? En realidad. Por una parte. proceden del inglés eXtensible Markup Language (lenguaje extensible de marcas). Como antes con muchos otros estándares. Veremos cómo obtener valores en formato XML desde la línea de órdenes. Aunque también es seguro que hará más sencillo encontrar soluciones a los mismos. cuya apariencia pueda ser modificada posteriormente. El siguiente contiene detalles sobre el reparto de Blade Runner: <?xml version="1. extraer o modificar únicamente un fragmento.14 XML De un tiempo a esta parte las siglas XML se han hecho omnipresentes en el ámbito de la informática.0"?> <reparto> <papel protagonista="si"> <personaje>Rick Deckard</personaje> . MySQL nos ofrece dos formas de combinar datos y XML. utilizaremos PHP junto con XML. tampoco es tan sorprendente: XML está pensado con Internet como uno de sus objetivos. La figura 14.<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. si lo piensa un poco. En el caso de XML. XML en un cliente Web Lo que sí queda claro es que.1. Es interesante comprobar que. Partes de un documento XML Antes de describir con más detalle cada parte de un documento XML recordemos que es un lenguaje de . Todo lenguaje tiene unas reglas más o menos estrictas que deben ser cumplidas para que pueda ser entendido. Aunque.1 muestra cómo se ve el anterior documento XML en un cliente Web. más fácil será crear programas capaces de leerlo de forma eficaz. Mientras más estricto sea. aunque los que mejor van a entender XML son las máquinas y los procesos. dada su naturaleza estructurada. en este caso) están listas para desempeñar muchas otras funciones. vayamos por partes. aplicaciones que pensábamos que tenían una única misión (visitar páginas Web. XML es un lenguaje en el que prima la sencillez y la portabilidad. nosotros también somos capaces de sacar conclusiones a partir de un documento XML. esto es aún más cierto. de un vistazo. Parafraseando a Jack el destripador. Figura 14. desde el principio. Este elemento se conoce como la raíz del documento. Seguir esta recomendación le evitará muchos quebraderos de cabeza en el futuro. puede estar compuesto de instrucciones de proceso como las del prólogo. Las etiquetas están compuestas por un nombre y unos atributos. <personaje> y <actor> son etiquetas. En el caso de nuestro ejemplo. la versión de la norma a la que se adhiere y muchas otras características. Todo lo que se encuentre entre esos dos símbolos es una marca o etiqueta. a excepción de declaraciones XML o de tipo de documento. las marcas están delimitadas por los símbolos "menor que" (<) y "mayor que" (>). o una combinación de ambas. En el ejemplo que nos ocupa el prólogo es el siguiente: <?xml version="1. Dicho lo cual. Nombres Es más que recomendable ceñirse a un determinado patrón al dar nombre a las etiquetas: todo minúsculas. lo que resulta en (<?) y (?>). todo mayúsculas. pensado para la descripción de datos. Cuerpo Los datos que un documento XML nos ofrece están en lo que se conoce como cuerpo. A continuación del prólogo nos encontramos con el contenido del documento. Prólogo Todo documento XML debe comenzar con un prólogo que se encargue de presentar el tipo del documento. Epílogo Situado a continuación del cuerpo del documento. debe existir una de apertura y otra de cierre y deben estar correctamente situadas.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. un documento XML puede presentar tres partes diferentes: el prólogo. a éstos se añade un símbolo de cierre de interrogación. Eso quiere decir que se trata de una instrucción que contiene información sobre el documento. Por ejemplo. se trataría de todo lo que está entre <reparto> y </reparto>. pero siempre con el mismo patrón. el cuerpo y el epílogo.marcas. . lo que se conoce como instrucción de proceso. Etiquetas Para diferenciar entre los distintos elementos que componen un documento XML hemos de utilizar etiquetas. incluidas estas dos etiquetas. Este nodo tiene como descendientes nodos <papel> que. Estas comillas pueden ser simples o dobles. los nombres de las etiquetas de apertura y cierre deben coincidir. Por ejemplo: <actor>Harrison Ford</actor> Las etiquetas de cierre son como las de apertura. Si conoce HTML ya habrá tenido su primer contacto con los atributos. sus propiedades. El valor del atributo debe estar obligatoriamente entre comillas. Los atributos sólo pueden indicarse en las etiquetas de apertura. pero si la apertura de comillas es simple. y el atributo. ¿qué tenemos? Nodos Un nodo está compuesto por una etiqueta.. lo que puede incluir a otros nodos. la etiqueta HTML para crear un enlace a otra página podría ser la siguiente: . y nietos del otro. El caso de XML no es diferente: la etiqueta denota el nombre del elemento. a su vez. utilizando atributos. El contenido es todo lo que está entre la etiqueta de apertura y la de cierre. nos referiremos a ellos como nodos descendientes. En el primer nivel de descendencia están los nodos hijos. La jerarquía en nuestro ejemplo está muy clara: el primer nodo del árbol es <reparto>. Si estos nodos tienen a su vez otros nodos en su interior.. Por ejemplo. Esta estructura de padres e hijos también es conocida como estructura arbórea o jerarquía. . separados ambos por un signo de igualdad (=). En este caso. Obviamente. Atributos Las etiquetas pueden aprovecharse para incluir otros datos. 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. el cierre también debe serlo.Cada etiqueta de apertura debe tener una de correspondiente de cierre. <A HREF=http://enreas. e igual si son dobles. la etiqueta A se refiere a un enlace y HREF es un atributo. serán hijos del inmediatamente anterior. Un atributo está formado por el nombre del mismo y el valor que toma. atributos y valores. sus atributos y su contenido.. tienen como descendientes a los nodos <personaje> y <actor>.. pero con una barra inclinada antes del nombre de la misma. Si en el contenido de un nodo hay otros nodos. no en las de cierre. Uniendo etiquetas.com/mysql> Guía de MySQL </A> . 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. A su vez. statement . uno por fila obtenida como resultado de la consulta. en inglés. pero basta con que realice una consulta para darse cuenta de que no es así. SELECT * FROM soporte. Dentro del cuerpo podemos ver el nodo raíz.).2 muestra el resultado de ejecutar esta consulta tras utilizar ese parámetro. Así. 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. xml. de la que tanto partido hemos sacado durante este libro. por ejemplo. En este caso son todos los campos de cada fila de la tabla soporte. uno por cada campo solicitado en la consulta. pero no hay epílogo. Los descendientes de resulset son nodos row. Sólo tenemos que añadir un parámetro más. Por ejemplo.2. resultset (conjunto de resultados. El valor de cada campo se encuentra entre las etiquetas de apertura y . Figura 14. 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. La figura 14. los descendientes de este nodo son nodos field. mysql. es la consulta que dio como resultado el documento XML que estamos examinando. vamos a seleccionar todos los soportes guardados en la base de datos: USE videoteca. El valor de uno de sus atributos. cierre de los nodos field. gracias a esta consulta su valor será soporte en lugar de nombre: USE videoteca. La figura 14. un elemento field correspondiente con el campo nombre. Puede ver el resultado en la figura 14. Sí. Consulta SQL con un único campo Como puede comprobar.3. Por ejemplo. supongamos que no nos interesan ni los identificadores ni las siglas.3 muestra el resultado de ejecutar esta consulta: USE videoteca. pero también puede ejecutar esta orden: mysql -u root -p --xml -e "SELECT * FROM soporte" videoteca > soportes.4. pero quizá lo fuese más si pudiésemos guardarlo en un archivo para poder utilizarlo desde otras aplicaciones. El documento XML obtenido responde fielmente a las características de la consulta SQL realizada.4. Cambio en el nombre del campo Obtener el resultado en formato XML es muy interesante. Figura 14. El documento XML también puede modificarse desde la consulta SQL para que el valor del atributo name sea el que queramos. SELECT nombre FROM soporte. Por ejemplo. SELECT nombre AS soporte FROM soporte. Figura 14.xml . ahora cada elemento row sólo tiene un descendiente. puede copiar el resultado obtenido y pegarlo en un editor de textos. A continuación veremos que es posible guardar documentos XML en los campos de una tabla. por último. abierto con Internet Explorer.6? . el reparto de cada película. ya que no incluiremos el prólogo. ¿Dónde encajaría dentro del modelo que puede ver en la figura 14. En realidad. estas dos funciones trabajan con fragmentos de cadenas en formato XML. A continuación. Figura 14. ¿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. indicamos el nombre de la base de datos con la que queremos trabajar y.5 puede ver el archivo resultante. Funciones XML MySQL proporciona dos funciones para trabajar con documentos XML: ExtractValue y UpdateXML .5. redirigimos el resultado a un archivo. En la figura 14. así como extraer valores de ellos y modificarlos. que necesita el texto de la consulta a realizar (la de selección de soportes. En este caso. Pero. en este caso). Resultado XML en Internet Explorer Ya sabemos cómo obtener el resultado de nuestras consultas en formato XML. siendo precisos.Tras el parámetro xml aparece el parámetro e. 7 puede ver el reparto de la primera parte de Spiderman.6. Deberíamos crear una tabla de personajes relacionada con la tabla de actores y con la de películas. . Está claro que se trata de información relacionada con cada película. con un número al final para diferenciarlas. 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. ¿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.Figura 14. Pero eso no soluciona otro problema: estamos añadiendo datos duplicados. podríamos tener tantas como quisiésemos. pero también con cada actor. Tobey Maguire se encarga tanto de Peter Parker como de Spiderman). No parece demasiado lógico. Si añadiésemos más parejas reparto_personaje y reparto_actor . Fíjese en que se trata sólo de parte de ella. 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. ¿verdad? Sólo podríamos almacenar uno de los personajes del reparto. además. un mismo actor puede interpretar varios personajes en la misma película (en este caso. La base de datos de la videoteca Podríamos añadir una pareja de campos nuevos: reparto_personaje y reparto_actor . A fin de cuentas. XPath La clave de utilizar XML es doble: guardar y extraer. hay que saber extraer información a partir de los datos.Figura 14.7. Recordemos el documento XML con el que comenzó el capítulo: . Reparto de Spiderman Supongamos que no nos interesa para nada mantener la tabla de personajes. es decir. En definitiva. hay que saber cómo almacenar los datos. una consulta XPath puede ser absoluta o relativa. sólo necesitamos guardar una lista. Se dice que es absoluta si parte del nodo raíz. Segundo. XPath no es más que un conjunto de reglas sintácticas que definen un sistema de consulta para documentos XML. Igual que ocurre dentro de un sistema de archivos. precisamente. Primero. Las funciones ExtractValue y UpdateXML nos permitirán hacer esto. sólo queremos disponer del reparto como simple referencia. Tampoco queremos que el reparto mantenga relación con la tabla de actores. Aunque se trata sólo de una de las múltiples aplicaciones que se le pueden dar. y debe hacerse de forma homogénea. el primer carácter de la consulta es /. Pero antes de ver estas dos funciones hablemos un poquito de XPath. a partir de /reparto. ALTER TABLE pelicula ADD reparto TEXT NOT NULL. Ahora vamos a insertar en ese nuevo campo el fragmento XML con el reparto de Blade Runner. Si el identificador de esta película es el 1. UPDATE pelicula SET reparto = '<reparto> <papel protagonista="si"> <personaje>Rick Deckard</personaje> <actor>Harrisond Ford</actor> </papel> . para obtener los valores del atributo protagonista tendríamos que utilizar la ruta: /reparto/papel/personaje@protagonista. la consulta de actualización sería: USE videoteca. Una ruta relativa: papel/personaje. Por ejemplo. Crearemos un nuevo campo que contendrá fragmentos de XML con el reparto. Ejecute la siguiente consulta para añadir este nuevo campo: USE videoteca. XPath también permite acceder al valor de los atributos. 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.<?xml version="1.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. ¿qué hacemos con todo esto? ExtractValue La función ExtractValue permite recuperar valores de un fragmento de un documento XML.8 muestra el resultado de realizar una consulta de selección sobre la tabla de películas para ver los campos de Blade Runner. Figura 14.9.8. .</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. Recibe dos parámetros: el fragmento en cuestión y una expresión XPath que determina qué valores debe devolver. El resultado de ejecutar esta consulta aparece en la figura 14. La figura 14. Como acaba de ver. no es necesario que el fragmento se tome de una tabla. '/papel/personaje' ) AS personaje. El siguiente es un sencillo ejemplo del funcionamiento de esta función: SELECT ExtractValue( '<papel> <personaje>Roy Batty</personaje> <actor>Rutger Hauer</actor> </papel>'. Datos de la película Blade Runner Y ahora. 10.9. papel y luego el nodo personaje. Ejemplo de utilización de ExtractValue Truco: Las cosas serían mucho más feas sin esa última cláusula AS personaje. Como muestra la figura 14. Pero. El valor del segundo parámetro es /papel/personaje. Figura 14. Si interpreta ese valor como una ruta sólo tiene que seguir los nodos para obtener el resultado mostrado en la figura 14. Obtendríamos un resultado distinto si utilizásemos como segundo parámetro la expresión XPath /papel/actor . '/reparto/papel/personaje' ) AS personajes FROM pelicula WHERE id = 1. La figura . Lista de personajes Igual de sencillo es obtener la lista de intérpretes. Haga la prueba. Primero el nodo raíz.9.10. SELECT ExtractValue( reparto. ¿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.Figura 14. También podemos acceder a los atributos utilizando la expresión XPath /reparto/papel/@protagonista. el resultado es la lista de personajes contenidos en el fragmento XML del campo. En este último ejemplo sí es fácil diferenciar entre cada uno de los elementos devueltos pero. Vamos a utilizar el siguiente código para crear un procedimiento almacenado que recupere. si llama al procedimiento almacenado desde un lenguaje de programación.11. SELECT ExtractValue( reparto. El código del procedimiento almacenado es el siguiente: DELIMITER // DROP PROCEDURE IF EXISTS pa_personajes_obtener.14. de poco nos sirven los resultados que acabamos de obtener. uno por uno. Figura 14. Atributos de cada papel Sin embargo. CREATE PROCEDURE pa_personajes_obtener ( idpelicula INT ) BEGIN DECLARE i INT DEFAULT 1. en el caso de los nombres de los personajes (Rick Deckard Roy Batty Rachael) resulta un poco más complicado. DECLARE personaje TEXT DEFAULT ''. 'count(/reparto/papel)') INTO j FROM . DECLARE personajes TEXT DEFAULT ''. los nombres de los personajes y los devuelva separados por comas. De esa forma. DECLARE j INT DEFAULT 0.11 muestra el resultado utilizarla en una consulta. Podemos solucionarlo si combinamos varias de las técnicas aprendidas a lo largo de este libro. podrá acceder fácilmente a cada uno de ellos. Not a: Encontrará más información sobre los procedimientos almacenados en el capítulo 11. END // DELIMITER . Personajes. personaje). SELECT personajes. '). personaje) INTO personaje. en la figura 14. END WHILE. '. separados por comas . Figura 14. SET personajes = CONCAT( personajes. SET i = i + 1. CONCAT(personaje. SELECT IF( i <> j.12. El resultado.12.FROM pelicula WHERE id = idpelicula. CALL pa_personajes_obtener(1). '/reparto/papel[$i]/personaje') INTO personaje FROM pelicula WHERE id = idpelicula. WHILE i <= j DO SELECT ExtractValue( reparto. Para obtener la lista de personajes de la película con identificador 1 (Blade Runner) tendría que ejecutar la siguiente consulta: USE videoteca. En este procedimiento almacenado se utilizan varias técnicas avanzadas. Si se fija. /reparto/papel[2] al segundo y así sucesivamente. UPDATE pelicula SET reparto = UpdateXML( reparto. '/reparto/papel[1]/actor'. Recordemos que ésta última permite extraer datos de fragmentos de documentos XML almacenados en campos de una tabla. No tendría mucho sentido que para modificar los valores de esos campos tuviésemos que guardar una nueva versión de dichos fragmentos. Para empezar. El resultado de esa consulta se guarda en la variable j. Si desea más información sobre ellas consulte la documentación de MySQL. '<actor>Harrison Ford</actor>' ) WHERE . UpdateXML recibe tres parámetros: el fragmento XML con el que trabajar.8. obtenemos uno por uno los nombres de los personajes y los guardamos en otra variable. Not a: En el procedimiento almacenado anterior utilizamos la instrucción de control de flujo WHILE y la función IF. Ejecute la siguiente consulta para corregirlo: USE videoteca. eche un vistazo a la lista de actores presentes en el campo reparto. Para empezar. El último nombre no incluye una coma al final. técnicas avanzadas que no han tenido su hueco en este libro. por último. contamos el número de papeles de que disponemos en el fragmento XML. hemos metido la pata: el actor principal de Blade Runner no es Harrisond Ford sino Harrison Ford. el nuevo valor que queremos guardar. donde $i toma los valores desde 1 hasta el número de papeles existentes: /reparto/papel[1] representa al primer nodo papel. Pudimos verla en la figura 14. Para poder acceder a ellos de uno en uno utilizamos la expresión XPath /reparto/papel[$i]/personaje. UpdateXML La función UpdateXML es la contrapartida necesaria de ExtractValue. Terminamos devolviendo el valor guardado en la variable personajes. la expresión XPath que determina qué valores se quieren modificar y. separados por comas. A continuación. Volvamos a utilizar los datos de ejemplo. Por ejemplo. el correspondiente al papel de Rick Deckard.id = 1. Existen otras alternativas. con diferencia. . '/reparto/papel[1]/actor' ) AS actor FROM pelicula WHERE id = 1. entre corchetes.13 muestra el resultado de ejecutar tanto la modificación como la consulta de datos. la siguiente orden devuelve la lista de géneros contenidos en la tabla correspondiente de la base de datos. la posición en la que se encuentra el elemento papel que queremos modificar. 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.13. Apertura Según vimos en los apartados anteriores. DOM (o DOM XML si utiliza PHP 4) o la pareja XMLReader y XMLWriter. La figura 14. En este caso se trata del primero de ellos. cada una con sus ventajas y sus inconvenientes si las comparamos entre sí. SELECT ExtractValue( reparto. ¿Ha tenido éxito el cambio? Compruébelo con la siguiente consulta: USE videoteca. Tras papel. Figura 14. Se trata del siguiente documento XML: <?xml version="1.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. echo $xml->asXML().mysql -u root -p --xml -e "SELECT * FROM soporte" videoteca > soportes. pero eso es porque el cliente Web está interpretando el código XML y sólo muestra la parte .xml'.14 muestra el resultado de este breve programa.0"?> <resultset statement="SELECT * FROM soporte" xmlns:xsi= "http://www.w3.5 mostraba el resultado de ejecutar dicha orden. Figura 14. NULL. no parece un documento XML en absoluto. ?> La figura 14. pues eso. TRUE ). simple: <?php $xml = new SimpleXMLElement( 'C:\soportes. Carga de un documento XML Truco: Efectivamente.14. Como resultado se devolverán todos los nodos del documento que cumplan ese criterio. lo que resulta realmente interesante es poder acceder a sus elementos. que quedan fuera del alcance de esta guía. si es FALSE como texto XML. dependiendo del valor del tercer parámetro. 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. foreach($rows as $row){ echo $row->asXML() . Sus descendientes son los nodos row que. en lugar de mostrar el contenido del documento utilizamos el método xpath para acceder a los nodos que nos interesan. Recorrido de nodos El nodo raíz del documento XML que estamos utilizando en este apartado es resultset . NULL. meros seres humanos. '<br/>'. el parámetro de que debemos pasar a xpath es /resultset/row. Resulta sencillo recorrer cada nodo row del documento: <?php $xml = new SimpleXMLElement( 'C:\soportes.xml'. 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). Aunque poder mostrar el contenido de un documento XML está muy bien. En este caso se trata de los nodos row que contiene el nodo resultset . $rows = $xml->xpath('/resultset/row'). TRUE ). 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á. Para cargar el documento XML utilizamos el constructor de la clase SimpleXMLElement .interesante para nosotros. el primer parámetro se interpretará como URL. } ?> La apertura del documento es exactamente igual que antes. Ahora. a su vez. La figura . Para acceder a cada nodo sólo tenemos que iterar por $rows y mostrar su contenido utilizando asXML. contienen nodos field. Por lo tanto. libxml. Si su valor es TRUE . Not a: El segundo parámetro se puede utilizar para pasar opciones al intérprete XML. El primer parámetro es el contenido XML que deseamos cargar. 14. break. 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. podría utilizar un bucle foreach para obtener todos los nodos row. .15 muestra lo que se vería al ejecutar el anterior programa. foreach($attributes as $attribute){ switch($attribute){ case 'id': echo('(' . la descripción. NULL. $rows = $xml->xpath('/resultset/row'). Figura 14. al principio. otro bucle para obtener todos los nodos field y. $field->asXML() . TRUE ). tras dos puntos. el identificador irá entre paréntesis. case 'nombre': echo('<b>' . Dependiendo del valor del atributo name de cada nodo field contenido en su interior mostraremos la información de una forma o de otra. terminada en punto. '</b>: '). Así. a continuación. foreach($rows as $row){ $fields = $row->xpath('field'). El código resultante sería el siguiente: <?php $xml = new SimpleXMLElement( 'C:\soportes. break. el nombre en negrita y.15. foreach($fields as $field){ $attributes = $field->attributes(). una vez allí. $field->asXML() . Por ejemplo. obtener todos los atributos con otro bucle foreach. ') ').xml'. La elección dependerá de las necesidades de sus programas. le garantizo que MySQL seguirá incorporando nuevas características para facilitar el trabajo con XML. Para terminar. por ejemplo. . hemos aprendido cómo funcionan tanto ExtractValue como UpdateXML .16.<br/>'). La mayoría de los lenguajes de programación modernos permiten trabajar directamente con XML. incluso construirlos desde cero. Cada una de ellas tiene sus virtudes y sus defectos. break.16. '. en la figura 14. que permiten extraer y modificar valores de campos que contengan fragmentos de documentos en formato XML. algo que puede serle útil si quiere utilizar esos datos en otros programas. Aunque las capacidades de MySQL en lo que a este formato se refiere son bastante rudimentarias. Además. hemos aprendido a tratar esos datos XML desde PHP. Es más. Figura 14. } } } } ?> El resultado. se trata sólo de la punta del iceberg. No podemos decir lo mismo de PHP. Acceso a los atributos Not a: SimpleXML también permite modificar el contenido de los documentos XML. Tras lo visto en este capítulo ya sabe cómo obtener en resultado de sus consultas SQL en formato XML. Este lenguaje de programación ofrece diferentes interfaces de acceso a XML además de SimpleXML como. case 'descripcion': echo($field->asXML() . así que todo el tiempo que invierta en aprender sobre él será una buena inversión. DOM o la pareja XMLReader y XMLWriter. Consulte la documentación de SimpleXML si desea más información al respecto.break. Espero que. Y de todas estas herramientas diferentes hemos sido capaces de lograr lo impensable. servidores de bases de datos. al menos.Epílogo Durante este libro hemos recorrido una gran cantidad de tecnologías de diferente naturaleza: servidores Web. diferentes lenguajes de programación. 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. El espacio del que disponemos en una guía de estas características es limitado y sin embargo. gracias a que son capaces de colaborar entre ellas. Recuerde: aún queda mucho que aprender. . hemos trabado contacto con una gran cantidad de productos diferentes. 2.1. Instrucciones iterativas 2.6.5.1. Creación 3. Instrucciones condicionales 2.3.4.5. Operaciones sobre tablas 3.3.3.3.5. Operadores de incremento 2. MySQL 3.6.5. Inserciones 1.6. Herramientas de consulta 3.5.5.4.Table of Contents Dedicatoria Agradecimientos Introducción Cómo usar este libro Prólogo 1.5.2.3.4.6. Creación de la base de datos 3.1. Funciones de salida 2.1.1.2.4.4.3.6. La primera aplicación 1.1.2.5. PHP 2. MySQL y PHP 1. Modificación 3. Operadores lógicos 2. MyISAM 3. Introducción 2. Creación de la base de datos 1. Estructura de un archivo PHP 2. Escapar de HTML 2.2.3.1. Concatenación de cadenas 2.5. InnoDB 3.2.4. Cambios de tipo 2. Operadores 2.1. Tipos de tabla 3.3.2. Creación de la tabla 1. Trabajando con PHP 2.3.3. Tipos de texto .3. Trabajando con MySQL 1. Base de datos de ejemplo 3.3.2. Comentarios 2. Operadores de comparación 2.5.1.1.6. Operador básico de asignación 2.5.5.8. Precedencia de operadores 2. Editores 2. ¿Qué es una tabla? 3.2. Borrado 3. Instrucciones de control 2.7.4. Tipos de datos 3. Tipos de datos 2.4.2.1. Variables 2.1.2. Bases de datos 3. XAMPP 1. Puesta en marcha de XAMPP 1.3. Salida de bucles 3.3.5. Operadores aritméticos 2.3.6.1.3. 2. Inserción de datos 6. El ejemplo 5. SQL 6.1.4.4. Instalación 5. MySQL Workbench 5.4.1.2.2.3. La base de datos de ejemplo 6.3. Operadores 6. El modelo relacional 5.1.1.2.1.3.3.3. Inclusión de archivos 4. Columnas de incremento automático 5.3. Creación de tablas con MySQL Workbench 5.4.1.6.1.5. Operadores lógicos 6. Orientación a objetos 4.2.1.1. Listados de varias tablas 6. PHP y MySQL 7.4.2.2.4. Actualizaciones 6.2.1. Objetivos 5.5. Consultas de selección 6.2.3. El ejemplo finalizado 6. Conjuntos de registros .2.5.3.1. El valor NULL 5.1. Limitaciones 5.2.2. Creación de la base de datos 6.7.3. Creación 6. Inserciones 6.1.1. PHP orientado a objetos 4.4.3.2. Devolución de valores 4. División de tablas 5. Divide y vencerás 5. Tipos numéricos 3. Fechas y horas 4.3.3. Índices 5.4.3. Listados de una tabla 6.2.3.4. Parámetros 4.1. Borrados 7.3.2.1.2.1.6.1.2.4.2. Cambiando la precedencia 6. Acceso mejorado a MySQL 7.3.3.1.4. Desconexión 7. Operadores aritméticos 6.2. Manipulación de bases de datos 6.3.3. Trabajando con funciones 4.2.1. Operadores de comparación 6. Diseño de bases de datos 5. Borrado 6.6.2. Relaciones muchos a muchos 5. Operación 7. El ciclo de la vida 7.2. Conceptos varios 5. Funciones 4. Conexión 7.3.4. Más allá de las clases 5.1. Relacionar tablas 5.2.1. Claves primarias 5. Clases 4. 6. Inserción 12.2. MySQLi y los errores 10. Ventajas 7.2.2.3.4. Otra plantilla 11. Variables 11. Base de datos reducida 11.5.3.2. Formularios 8.6.5.3.2. Control en el lado del cliente 9.7.6.1.3.3. Lista de géneros 10. Eliminación 11. Plantillas 10.3. Introducción 12.2. Un sencillo ejemplo 11. Base de datos reducida 12.2.2.1.2. Inconvenientes 7.6. Elementos de un formulario 8.3. Instalación 10.1. Configuración 9. Desencadenadores 12.1.3.3. Creación 11. Funciones almacenadas 11. La página PHP 10.1. Utilización desde PHP 12. Sintaxis 12.1.1. Un pequeño ejemplo 10.6. Valores de configuración 7. Creación 11.1.3. Excepciones 9.3. Gestión de errores 9.1. Creación 12. MySQL y los errores 9. Configuración 7.6. ¿Qué es Smarty? 10. Formularios HTML 8.1. Envío de información 8.2.3. Introducción 11.1. Parámetros 11.2. Funciones 9.1.3.1.2.6. PHP y los errores 9.2. Recuperación de información 8.1.4.1.5.1. Archivos de registro en tablas 9.4.1.1.1.1. Otras consultas 7.3. Opciones de PHP en Apache 8.2. Modificación de la configuración 7.4.1.1.3.4. Sintaxis 11.3. Creación . Delimitadores 11.1.2.5.2.3. Idioma de los errores 9. Creación de formularios 8.1.3.1.3.2.2.6. Procedimientos almacenados 11. Inserción de registros 8. Consultas escapadas 7. Inserción 11.2. La plantilla 10. Archivos de registro 9.3. Cómo funcionan los formularios 8. 1.4. Funciones XML 14.4. SimpleXML 14. ExtractValue 14.3.2.2. Utilización desde PHP 14. ¿Qué es XML? 14.1. XPath 14.3. Modificación 13.4. Introducción 13. Recorrido de nodos 14.2.1.3.1. Eliminación 12.3.4. Apertura 14.1.3. Borrado 13.3.3.2. Actualización 12. Ejemplos 12.12.4. Vistas 13.2. Etiquetas 14. Partes de un documento XML 14.2.2.2.2.3.2.3.3.3.1.2.2. Creación 13.3.3. Ejemplos 13. Eliminación 13.3. Creación 13. Sintaxis 13.4. XML desde la línea de órdenes 14.3. Eliminación 13.1.3.3.1. Modificación 13.1. Inserción 12.2. XML 14. Acceso a atributos Epílogo . Datos de ejemplo 14. UpdateXML 14.1.3.
Copyright © 2024 DOKUMEN.SITE Inc.