Noticias Weblogs Foros Wiki Código
Sponsors:

Meta-Info

¿Que es?

Planeta Código es un agregador de weblogs sobre programación y desarrollo en castellano. Si eres lector te permite seguirlos de modo cómodo en esta misma página o mediante el fichero de subscripción.

rss subscripción

Sponsors

PlanetaCódigo en inglés

Puedes utilizar las siguientes imagenes para enlazar PlanetaCodigo:
planetacodigo

planetacodigo

Si tienes un weblog de programación y quieres ser añadido aquí, envíame un email solicitándolo.

Idea: Juanjo Navarro

Diseño: Albin

mundoxbase.info

Mysql, la integridad referencial en la práctica

Diciembre 31st, 2006 - [Enlace local]

El último día veíamos los pasos necesarios para crear una base de datos InnoDb que soportan integridad referencial y decíamos que esta característica nos permitiría ahorrarnos buena parte del trabajo “sucio” a la hora confeccionar los programas que hacen uso de ésta. Veamos si es cierto.

Recordemos brevemente los pasos necesarios para entrar en nuestra base de datos
- Primero accedemos al intérprete de comandos de Mysql
- Luego “usamos” la base de datos

Una vez aquí, vamos a introducir nuestro primer registro en una de las tablas, por ejemplo, la de artículos:

mysql> INSERT INTO articulos VALUES (null,"Primer articulo",null);
Query OK, 1 row affected (0.03 sec)

-

Como podemos ver, utilizamos la instrucción INSERT INTO seguido del nombre de la tabla dónde vamos a insertar los datos (VALUES) y los datos a insertar encerrados entre paréntesis y separados por comas.

En nuestro ejemplo, el primer dato (correspondiente al campo “Codigo”) que como recordaréis es un campo autoincremental, lo dejamos a “null”, de tal forma que el propio Mysql se encargará de asignarle un código correlativo.
El segundo dato, corresponde al campo “Descripcion” y el tercer dato corresponde al campo “similar”, que como esta artículo no tiene ningúno similar, lo dejamos a null (sin datos).

También podemos ver como Mysql nos indica que todo está OK, y que nuestra instrucción afecta a un registo (el que hemos insertado) y el tiempo empleado en terminar la operación.

Podemos ver cómo ha quedado nuestra tabla “Articulos” haciendo una selección

mysql> select * from articulos;
+——–+—————–+———+
| Codigo | Descripcion     | Similar |
+——–+—————–+———+
|      1 | Primer articulo |    NULL |
+——–+—————–+———+
1 row in set (0.00 sec)

A la hora de insertar un nuevo registro, también podemos indicar los campos que intervienen en la inserción. Imaginaros una tabla con, no sé, 30 campos, y que sólo queremos insertar el nombre del artículo, en lugar de poner

INSERT INTO Articulos VALUES(null, null, null, null, "articulo", null, nul…..

-

Podemos hacerlo mucho más sencillo con

mysql> INSERT INTO articulos(descripcion) VALUES ("Segundo articulo")
Query OK, 1 row affected (0.02 sec)

-

Como vemos, todo consiste en indicar, además del nombre de la tabla, los campos que se ven afectados por la inserción encerrados entre paréntesis.
Así, en este caso, el campo autoincremental se incrementará automáticamente y el campo similar tomará el valor Null, su valor por defecto.

mysql> select * from articulos;
+——–+——————+———+
| Codigo | Descripcion      | Similar |
+——–+——————+———+
|      1 | Primer articulo  |    NULL |
|      2 | Segundo articulo |    NULL |
+——–+——————+———+
2 rows in set (0.00 sec)

Otra opción que nos ofrece Mysql es insertar varios registros a la vez, para ello tan sólo es necesario encerrar entra paréntesis los distintos registros y separarlos por comas

mysql> INSERT INTO articulos(descripcion) VALUES ("Tercer articulo"), ("Cuarto articulo"), ("Quinto articulo");
Query OK, 3 rows affected (0.02 sec)
Records: 3  Duplicates: 0  Warnings: 0




mysql> select * from articulos;
+——–+——————+———+
| Codigo | Descripcion      | Similar |
+——–+——————+———+
|      1 | Primer articulo  |    NULL |
|      2 | Segundo articulo |    NULL |
|      3 | Tercer articulo  |    NULL |
|      4 | Cuarto articulo  |    NULL |
|      5 | Quinto articulo  |    NULL |
+——–+——————+———+
5 rows in set (0.00 sec)

Vamos ahora a insertar las características de nuestro primer artículo

mysql> INSERT INTO caracteristicas VALUES (1,10.25,null);
Query OK, 1 row affected (0.02 sec)


mysql> INSERT INTO caracteristicas VALUES (2,2.20 ,null);
Query OK, 1 row affected (0.02 sec)


mysql> SELECT * FROM caracteristicas;
+——————+——-+———+
| Articulos_Codigo | Peso  | Volumen |
+——————+——-+———+
|                1 | 10.25 |    NULL |
|                2 |  2.20 |    NULL |
+——————+——-+———+
2 row in set (0.00 sec)

Veamos ahora que pasa si intentamos pasarnos de listos y pretendemos insertar de nuevo otras características para nuestro primer artículo

mysql> INSERT INTO caracteristicas VALUES (1,20,null);
ERROR 1062 (23000): Duplicate entry ‘1′ for key 1

¡Exacto!, fijaos que el campo Articulo_Codigo de la tabla Características es una clave primaria, y por lo tanto no pueden existir dos registro con el código 1 en dicho campo.

¿Y si intentamos crear las características de un artículo que no existe?

mysql> INSERT INTO caracteristicas VALUES (10,20,null);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint
fails (`prueba/caracteristicas`, CONSTRAINT `caracteristicas_ibfk_1` FOREIGN KEY
(`Articulos_Codigo`) REFERENCES `articulos` (`Codigo`) ON DELETE CASCADE ON UPDATE NO ACTION)

¡Mysql nos ha vuelto a pillar! Al insertar unas características para un artículo inexistente estamos rompiendo una de las reglas de integridad referencial, que dice que todo artículo puede tener unas características, pero que las características siempre corresponderán a un determinado artículo.

Y… si borramos nuestro primer artículo?

mysql> DELETE FROM articulos WHERE codigo=1;
Query OK, 1 row affected (0.01 sec)

mysql> SELECT * FROM articulos;
+——–+——————+———+
| Codigo | Descripcion      | Similar |
+——–+——————+———+
|      2 | Segundo articulo |    NULL |
|      3 | Tercer articulo  |    NULL |
|      4 | Cuarto articulo  |    NULL |
|      5 | Quinto articulo  |    NULL |
+——–+——————+———+
4 rows in set (0.00 sec)

¡Ojo con el delete!!. Si se nos ocurre poner simplemente DELETE FROM articulos nos “pulimos” TODOS los datos de la tabla !!.

Recordar siempre que en sql trabajamos sobre la base de datos completa, no como con las dbf que estábamos posicionados en un determinado registro y nuestras acciones actuaban sólo sobre ese registro.
En clipper, al hacer un “delete” afectaba al registro sobre el que estábamos posicionados, en cambio, en sql no estamos “posicionados” en “ningún sitio”, por eso, al hacer un delete en Mysql le tenemos que decir qué tabla (FROM) y qué registro de la tabla (WHERE)

Hemos visto que nuestro “delete” ha borrado el registro indicado, pero… qué ha pasado con las características asociadas al artículo borrado. Veamos la tabla características

mysql> select * from caracteristicas;
+——————+——+———+
| Articulos_Codigo | Peso | Volumen |
+——————+——+———+
|                2 | 2.20 |    NULL |
+——————+——+———+
1 row in set (0.00 sec)

¿Os acordáis del ON DELETE CASCADE?
Mysql se ha encargado por nosotros de “propagar” el borrado de datos a las tablas indicadas.

Hoy hemos visto cómo efectivamente la integridad referencial funciona y nos ahorra el trabajo de realizar por nosotros mismos parte del mantenimiento propio de una base de datos.

El año próximo veremos con un poco más de detalle la inserción y modificación de datos dentro de una tabla, y cómo nos pueden ayudar los procedimientos almacenados.

Pero antes de terminar, hagamos una pequeña ampliación a nuestra tabla “artículos”. Vamos a añadir dos nuevos campos a la tabla. Veremos cómo usarlos en el próximo capítulo

mysql> ALTER TABLE articulos
    ->       ADD creado date,
    ->       ADD modificado date,
    ->       ADD cambios Tinyint;
Query OK, 4 rows affected (0.16 sec)
Records: 4  Duplicates: 0  Warnings: 0


mysql> desc articulos;
+————-+——————+——+—–+———+—————-+
| Field       | Type             | Null | Key | Default | Extra          |
+————-+——————+——+—–+———+—————-+
| Codigo      | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| Descripcion | varchar(30)      | YES  |     | NULL    |                |
| Similar     | int(10) unsigned | YES  | MUL | NULL    |                |
| creado      | date             | YES  |     | NULL    |                |
| modificado  | date             | YES  |     | NULL    |                |
| cambios     | tinyint(4)       | YES  |     | NULL    |                |
+————-+——————+——+—–+———+—————-+
6 rows in set (0.01 sec)

» Leer más, comentarios, etc...