Pues MySQL con el motor innodb están diseñados para ese tipo de trabajo de manera automática y no, no siempre se debe poner on cascade, debes tomar cada relación y pensar bien que debería suceder cuando se elimina o actualiza un registro, la mayoría de las veces son on cascade, eso si, pero no siempre es así, hay veces que necesitas establecer a null, yo en lo personal nunca he utilizado el restringir el valor o la fila, siempre uso cascade o set null dependiendo del caso, en el caso de una tabla relacional de muchos a muchos si es necesario hacerlo con cascade y no necesitarás triggers, de hecho de mis años programando jamás he necesitado utilizar triggers o funciones procedure, de hecho intento jamás usarlos ya que dejo ese trabajo de calculo al lenguaje de programación del lado del código y no de la base de datos ya que cuando necesitas hacer un flujo de una aplicación, documentarla y llevar un cierto orden no puedes dejar toda la lógica desparramada entre la base de datos y el código, para mi la base de datos es base de datos y el calculo de recoger y buscar datos se lo dejo al código y libero la carga del servidor (útil cuando trabajas con separación de capas).
Mira esto:
-- MySQL Workbench Synchronization
-- Generated: 2015-06-29 10:30
-- Model: New Model
-- Version: 1.0
-- Project: Name of the project
-- Author: WHK
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
CREATE TABLE IF NOT EXISTS `blank`.`personaje` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`nombre` VARCHAR(256) NOT NULL,
`reino_id` INT(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`),
INDEX `fk_personaje_reinos_idx` (`reino_id` ASC),
CONSTRAINT `fk_personaje_reinos`
FOREIGN KEY (`reino_id`)
REFERENCES `blank`.`reinos` (`id`)
ON DELETE SET NULL
ON UPDATE CASCADE)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;
CREATE TABLE IF NOT EXISTS `blank`.`reinos` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`nombre` VARCHAR(256) NOT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
En esta base de datos tienes personaje y reinos y la tabla de personajes tiene una columna con el id de reino, esto quiere decir que el personaje va a pertenecer a un solo reino o ninguno, por este motivo el valor por defecto es null, ahora, este valor tiene una acción de cascade cuando se actualiza el registro o set null cuando se elimina... como funciona esto?:
Cuando se actualiza el registro del reino entonces se actualiza tambien el valor en la fila del personaje, pero que pasa si eliminas el reino? si le pones cascade se va a eliminar el personaje, por eso lo estableces a null, ahora, si necesitas que el personaje siempre tenga un reino entonces le das la opcioon de bloqueo y restringes la fila, de esta manera no podra usarse el personaje hasta que manualmente le asignes un nuevo reino y no tendras problemas en la selección o actualización de registros.
Ahora, digamos que necesitas que el personaje pueda estar en mas de un reino asociado:
-- MySQL Workbench Synchronization
-- Generated: 2015-06-29 10:35
-- Model: New Model
-- Version: 1.0
-- Project: Name of the project
-- Author: WHK
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
CREATE TABLE IF NOT EXISTS `blank`.`personaje` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`nombre` VARCHAR(256) NOT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;
CREATE TABLE IF NOT EXISTS `blank`.`reinos` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`nombre` VARCHAR(256) NOT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;
CREATE TABLE IF NOT EXISTS `blank`.`personajes_reinos_relacion` (
`personaje_id` INT(11) NOT NULL,
`reino_id` INT(11) NOT NULL,
PRIMARY KEY (`personaje_id`, `reino_id`),
INDEX `fk_personajes_reinos_relacion_reinos1_idx` (`reino_id` ASC),
CONSTRAINT `fk_personajes_reinos_relacion_personaje`
FOREIGN KEY (`personaje_id`)
REFERENCES `blank`.`personaje` (`id`)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT `fk_personajes_reinos_relacion_reinos1`
FOREIGN KEY (`reino_id`)
REFERENCES `blank`.`reinos` (`id`)
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
En este caso hay una tabla intermedia de muchos a muchos donde un personaje puede estar asociado a mas de un mundo, ahora, si te fijas ambas columnas de esta tablas son llaves, esto quiere decir que no se podrán repetir los mundos con los personajes, esto quiere decir que si hay dos reinos entonces un personaje no podrá tener mas de dos reinos y si intentas asociar un reino por segunda ves la base de datos te arrojará un error diciendo que el registro está duplicado. Esto es súper útil si deseas mantener la integridad de datos de tu aplicación ya que si permites duplicidades vas a tener problemas muy serios al momento de manejar tus datos, esto te restringe en parte a diseñar una buena aplicación.
Si te fijas, en este ejemplo ambas funciones son cascade en ambas columnas ya que si eliminas un personaje o eliminas un reino entonces la relación desaparece, si eliminas un reino el personaje ya no estará asociado a el y eso es lo normal que pase y no que quede un registro fantasma que te diga que pertenece a un reino que no existe.
Bueno.... todo eso lo hace innodb de manera automática e innodb viene integrado por defecto con mysql.
Saludos.