2009-11-16 9 views
6

¿Cuál es la mejor manera en PHP para manejar excepciones de clave externa en una base de datos mysql? ¿Hay una clase mysql que se pueda usar para simplificar cualquier código?Manejo de excepciones de clave externa en PHP

Idealmente, lo que quiero hacer, por ejemplo, es tratar de eliminar un registro donde es la clave externa principal para cualquier número de tablas secundarias. La clave externa arroja la excepción, entonces me gustaría poder ver cada tabla de clave externa y probarla, dando retroalimentación significativa sobre las tablas y el número de registros que causan la excepción. Esto se devolverá como el error para que el usuario final pueda hacer referencia y eliminar los registros ofensivos.

Respuesta

6

La forma en que manejo esto es configurar mi clase contenedora de base de datos para que siempre genere una excepción cuando encuentre un error en la base de datos. Así, por ejemplo, podría tener una clase llamada MySQL con las siguientes funciones:

public function query($query_string) 
{ 
    $this->queryId = mysql_query($query_string,$this->connectionId); 
    if (! $this->queryId) { 
     $this->_throwException($query_string); 
    } 
    return $this->queryId; 
} 

private function _throwException($query = null) 
{ 
    $msg = mysql_error().". Query was:\n\n".$query. 
       "\n\nError number: ".mysql_errno(); 
    throw new Exception($msg,mysql_errno()); 
} 

Cada vez que falla una consulta, una excepción de PHP regulares se lanza. Tenga en cuenta que los lanzaría también desde otros lugares, como una función connect() o una función selectDb(), dependiendo de si la operación fue exitosa o no.

Con esa configuración, ya está listo para empezar. Cualquier lugar que es de esperar que pueda necesitar estar manejando un error de base de datos, hacer algo como lo siguiente:

//assume $db has been set up to be an instance of the MySQL class 

try { 
    $db->query("DELETE FROM parent WHERE id=123"); 
} catch (Exception $e) { 
    //uh-oh, maybe a foreign key restraint failed? 
    if ($e->getCode() == 'mysql foreign key error code') { 
     //yep, it failed. Do some stuff. 
    } 
} 

Editar

En respuesta al comentario del cartel a continuación, usted tiene cierta información limitada disponible para usted para ayudar a diagnosticar un problema de clave extranjera. El texto de error creado por una restricción de clave externa fallado y devuelto por mysql_error() ve algo como esto:

Cannot delete or update a parent row: 
a foreign key constraint fails 
(`dbname`.`childtable`, CONSTRAINT `FK_name_1` FOREIGN KEY 
(`fieldName`) REFERENCES `parenttable` (`fieldName`)); 

Si sus claves externas son lo suficientemente complejas que no se puede estar seguro de lo que podría causar un error de clave externa para un determinado consulta, entonces probablemente podría analizar este texto de error para ayudar a resolverlo. El comando SHOW ENGINE INNODB STATUS también arroja un resultado más detallado para el último error de clave externa.

De lo contrario, es probable que deba hacer algunas excavaciones usted mismo. La siguiente consulta le dará una lista de claves externas en una tabla dada, que puede examinar para obtener información:

select * from information_schema.table_constraints 
WHERE table_schema=schema() AND table_name='table_name'; 

Por desgracia, no creo que hay una bala mágica para su solución que no sea el examen de los errores y restricciones muy cuidadosamente.

+0

Esto parece una buena manera de controlar el manejo de errores estructuralmente, pero realmente quiero averiguar si puedo enumerar dinámicamente las tablas secundarias y luego consultarlas para enumerar las excepciones reales. Así que es un poco dentro de 'Hacer algunas cosas' con las que estoy luchando. :) – Das123

+0

Esto es casi idéntico a mi propio enfoque. –

+0

Impresionante. Gracias. :) La información adicional completa la imagen para mí. :) – Das123

0

Creo que la mejor opción es que hagas un transaction. De esa forma, la inserción siempre será válida o no se realizará en absoluto. Eso puede devolver un mensaje de error con el que puede trabajar también. Esto evitará tener que verificar manualmente cada tabla, la base de datos lo hace por usted.

+0

Gracias por la respuesta, pero por lo que entiendo, la transacción solo empaqueta la (s) consulta (s). Lo que quiero hacer es, después de que se haya activado la excepción, dar retroalimentación significativa de los registros secundarios reales que causaron la excepción. – Das123