Mostrando entradas con la etiqueta MYSQL. Mostrar todas las entradas
Mostrando entradas con la etiqueta MYSQL. Mostrar todas las entradas

sábado, 12 de febrero de 2011

Phpmyadmin no admite crear triggers con DELIMITER y BEGIN END;

CONCEPTOS TEÓRICOS SOBRE CREACIÓN DE TRIGGER EN MYSQL
Si consultamos la página oficial de mysql, vemos que hay que tener en cuenta 2 aspectos que difieren con el resto de SGBD (El delimiter y el BEGIN END).

DELIMITER |

CREATE TRIGGER testref BEFORE INSERT ON test1
  FOR EACH ROW BEGIN
    INSERT INTO test2 SET a2 = NEW.a1;
    DELETE FROM test3 WHERE a3 = NEW.a1;  
    UPDATE test4 SET b4 = b4 + 1 WHERE a4 = NEW.a1;
  END
|

DELIMITER ;

*ANOTACIÓN SOBRE BEGIN END: Si sólo voy a ejecutar una sentencia dentro del trigger no es necesario poner la opción BEGIN END, pero si el trigger tiene que ejecutar multiples sentencias si que es necesario ponerlo.

PROBLEMA DE TRIGGERS EN PHPMYADMIN

El problema viene cuando queremos crear un trigger en phpmyadmin y utilizamos la sintaxis oficial de creación de un trigger en mysql. Según el mensaje que aparece por pantalla, parece que phpmyadmin si que lo crea, porque nos dice que es todo correcto.

Pero cuando vamos a consultar a ver si el trigger está creado, nos damos cuenta que realmente no lo ha creado. Sentencia: SHOW TRIGGERS.

SOLUCIÓN PARA CREACIÓN DE TRIGGERS EN PHPMYADMIN

Entonces...phpmyadmin no admite la sintaxis oficial de mysql???...Realmente si que la admite, lo que pasa es que parte del código que nosotros escribimos, él ya lo hace internamente.
Si nos fijamos en la ventana donde creamos el trigger o cualquier sentencia, abajo del todo hay una casilla que pone “DELIMITADOR ;”, lo que esta ocurriendo es que cada vez que nosotros ejecutamos un trigger el internamente nos pone la cabecera y el final del trigger con delimitador y utilizar el carácter “;”.
Al utilizar el carácter “;”, hace que nosotros no podamos crear en trigger con la opción BEGIN END; (sentencia que nos es necesaria cuando queremos ejecutar más de una sentencia).

La solución la tenéis en la imagen, hay que indicar al phpmyadmin que elija otro delimitador cualquiera (un carácter que no utilicemos dentro de nuestro código) y de esta forma podemos acabar el trigger con un BEGIN END;







miércoles, 14 de octubre de 2009

Crear base de datos en mysql (debian)

Para crear una base de datos en mysql.

Abrimos la consola y escribimos mysql (entrará dentro del mysql en línea de comandos).

debian:/home/alumno# mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.0.32-Debian_7etch11-log Debian etch distribution

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql>


Después indicamos el archivo.sql donde se encuentra la sintaxis de nuestra base de datos. Ojo! en ese archivo si no creais la base de datos internamente tendreis que hacerlo antes de lanzarlo, y se hace asi:

mysql> create database nombre;
mysql> use nombre;

mysql> \. /home/alumno/Desktop/BD1CreateBD.sql

Y se abrá creado la base de datos, con el comando show tables, nos tiene que mostrar todas las tablas de la base de datos.

mysql> show tables;
+-----------------------+
| Tables_in_proveedores |
+-----------------------+
| inventario |
| linped |
| pedido |
| pieza |
| preciosum |
| vendedor |
+-----------------------+
6 rows in set (0.00 sec)

martes, 3 de marzo de 2009

mysql - ERROR 1442 (HY000) - trigger recursivo

ERROR MYSQL
ERROR 1442 (HY000): Can't update table 'docencia' in storedfunction/trigger because it is already used by statement which invokedthis stored function/trigger.

Esto se debe a que si se crease el trigger se harian llamadas recursivas infinitas.

Por ejemplo.
+---------+--------+---------+
cod_pro cod_asp creditos
+---------+--------+---------+
1 1 10
+---------+--------+---------+

Si quiero hacer que si se modifican los creditos, vaya a la tablaprofesores (cod_pro) y le modifique el número de créditos que imparte.

Con un trigger con mysql, no podría hacerlo porque, cada vez que yolance un update, se lanza el trigger y dentro del trigger hay unupdate sobre la misma tabla, por lo que también se lanzaría de nuevoel trigger...y así sucesivamente.

Ejemplo de trigger
delimiter //
CREATE TRIGGER total_creditos3
AFTER UPDATE ON docencia
FOR EACH ROW
BEGIN
IF OLD.creditos != NEW.creditos then
UPDATE docencia SET creditos=creditos + (new.creditos -old.creditos)
wherecod_pro=old.cod_pro;
END IF;
END;//
delimiter ;

miércoles, 4 de febrero de 2009

Restricción CHECK

USO CHECK: Restringir los valores que puede tomar un campo en concreto de la tabla.

Ejemplos:
check (id between 1 and 20) : Que el id solo pueda tomar valores entre 1 y 20
check (turno in ('Mañanas','Tardes')): Que el campo turno solo pueda tomar valores Mañanas o Tardes.

Ejemplo práctico POSTGRESQL:

#Creamos una tabla
postgres=# create table prucheck(
postgres(# id bigint,
postgres(# nombre varchar(20),
postgres(# check (id between 1 and 20),
postgres(# check (nombre in ('Lunes','Martes')));
CREATE TABLE

Probamos a insertar valores válidos
postgres=# insert into prucheck (id, nombre) values (1,'Lunes');
INSERT 29781 1

Probamos a insertar valores no válidos
postgres=# insert into prucheck (id, nombre) values (21,'Martes');
ERROR: el nuevo registro para la relación "prucheck" viola la restricción check "$1"

Ejemplo práctico MYSQL:
CREATE TABLE `tablacheck3` (
`id` INT NOT NULL,
`semana` VARCHAR(20) NOT NULL,
check (id between 1 and 20),
check (semana in ('Lunes','Martes'))
)
ENGINE = myisam;

PERO NO FUNCIONA EL CHECK--> deja insertar valores que no cumplen la restricción.

INSERT INTO `tablacheck3` ( `id` , `semana` )
VALUES (
'1', '''Lunes'''
), (
'221', '''hola'''
);


ANOTACIÓN: Esta probado bajo myisam, posiblemente con innodb si que se cumpla la restricción.

MYSQL no cumple las claves ajenas!!.

EJEMPLO.

Tenemos la tabla cantantes que tiene como clave primaria titulo y cantante, y como clave ajena cantante.

mysql> describe cd;
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| titulo | varchar(30) | NO | PRI | | |
| cantante | int(11) | NO | PRI | | |
| coste | int(11) | YES | | NULL | |
| copias | int(11) | YES | | NULL | |
+----------+-------------+------+-----+---------+-------+

INSERCIÓN QUE CUMPLA LA RESTRICCIÓN.

Si realizamos una insercion de un cantante que existe en la tabla de cantantes nos deja --> cumple la restricción de integridad.

mysql> insert into cd (titulo,cantante) values ('kk',10);
Query OK, 1 row affected (0.33 sec)

INSERCIÓN QUE NO CUMPLA LA RESTRICCIÓN.

Si realizamos una inserción de un cantante que no existe en la tabla de cantantes, nos debería decir que viola la restriccion de integridad.

mysql> insert into cd (titulo,cantante) values ('kk',103233);
Query OK, 1 row affected (0.00 sec)

PROBLEMA

No nos sirve de nada mantener una base de datos, que no nos asegura las relaciones entre tablas.
No nos va a permitir tener una base de datos consistente.


SOLUCIÓN.

Debemos crear las tablas como innoDB.
Ejemplo:

CREATE TABLE cd(
titulo varchar(30) NOT NULL,
cantante int NOT NULL,
coste int,
copias int,
PRIMARY KEY (titulo, cantante),
FOREIGN KEY(cantante) REFERENCES artista(cif) ON UPDATE CASCADE
)TYPE=INNODB;


Si realizamos una insercción de un cantante que no existe sobre la tabla cantantes, nos dará un error.

mysql> insert into cd (titulo,cantante) values ("titulo 1", 987);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`musicainnodb/cd`, CONSTRAINT `cd_ibfk_1` FOREIGN KEY (`cantante`) REFERENCES `artista` (`cif`) ON UPDATE CASCADE)



CONCLUSION

Como puede ser que el motor de almacenamiento por defecto de MySQL, sea MyISAM, y este no soporte ninguna regla de integridad referencial???..

No tiene sentido que por defecto no se cumpla ni las claves ajenas, y ademas! que me deje meter como clave primaria un vacio!!.

palyginti kainas